Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

机器学习函数

evalMLMethod

使用已拟合的回归模型进行预测时,可使用 evalMLMethod 函数。请参阅 linearRegression 中的链接。

stochasticLinearRegression

stochasticLinearRegression 聚合函数实现了基于线性模型和 MSE 损失函数的随机梯度下降方法。使用 evalMLMethod 对新数据进行预测。

stochasticLogisticRegression

stochasticLogisticRegression 聚合函数实现了用于二元分类问题的随机梯度下降方法。使用 evalMLMethod 对新数据进行预测。

naiveBayesClassifier

使用带有 n-gram 和拉普拉斯平滑的朴素贝叶斯模型对输入文本进行分类。该模型必须先在 ClickHouse 中配置后方可使用。

语法

naiveBayesClassifier(model_name, input_text);

参数

  • model_name — 预配置模型的名称。String 该模型必须在 ClickHouse 的配置文件中定义 (见下文) 。
  • input_text — 要分类的文本。String 输入会完全按原样处理 (保留大小写和标点) 。

返回值

  • 预测类别 ID,以无符号整数表示。UInt32 类别 ID 对应于模型构建时定义的类别。

示例

使用语言检测模型对文本进行分类:

SELECT naiveBayesClassifier('language', 'How are you?');
┌─naiveBayesClassifier('language', 'How are you?')─┐
│ 0                                                │
└──────────────────────────────────────────────────┘

结果 0 可能表示英语,而 1 可能表示法语——具体类别含义取决于你的训练数据。


实现细节

算法 使用朴素贝叶斯分类算法,并结合 拉普拉斯平滑 处理未见过的 n-gram;n-gram 概率的计算方法参考了这份资料

主要特性

  • 支持任意长度的 n-gram
  • 三种标记化模式:
    • byte:基于原始字节进行处理。每个字节都是一个标记。
    • codepoint:基于从 UTF‑8 解码得到的 Unicode 标量值进行处理。每个码点都是一个标记。
    • token:按连续的 Unicode 空白字符 (正则 \s+) 拆分。标记是非空白的子字符串;如果与标点符号相邻,标点符号也会被视为该标记的一部分 (例如,"you?" 是一个标记) 。

模型配置

你可以在这里找到用于创建语言检测朴素贝叶斯模型的示例源代码。

此外,这里还提供了示例模型及其对应的配置文件。

下面是 ClickHouse 中朴素贝叶斯模型的一个示例配置:

<clickhouse>
    <nb_models>
        <model>
            <name>sentiment</name>
            <path>/etc/clickhouse-server/config.d/sentiment.bin</path>
            <n>2</n>
            <mode>token</mode>
            <alpha>1.0</alpha>
            <priors>
                <prior>
                    <class>0</class>
                    <value>0.6</value>
                </prior>
                <prior>
                    <class>1</class>
                    <value>0.4</value>
                </prior>
            </priors>
        </model>
    </nb_models>
</clickhouse>

配置参数

参数 说明 示例 默认值
name 唯一模型标识符 language_detection 必填
path 模型二进制文件的完整路径 /etc/clickhouse-server/config.d/language_detection.bin 必填
mode 标记化方式:
- byte:字节序列
- codepoint:Unicode 字符
- token:标记
token 必填
n N-gram 大小 (token 模式) :
- 1=单个词
- 2=词对
- 3=三个词一组
2 必填
alpha 分类时使用的 拉普拉斯平滑 系数,用于处理模型中未出现的 n-grams 0.5 1.0
priors 类别概率 (属于某一类别的文档占比) 类别 0 占 60%,类别 1 占 40% 均匀分布

模型训练指南

文件格式 在可读性较高的格式中,对于 n=1token 模式,模型可能如下所示:

<class_id> <n-gram> <count>
0 excellent 15
1 refund 28

n=3 且为 codepoint 模式时,可能如下所示:

<class_id> <n-gram> <count>
0 exc 15
1 ref 28

ClickHouse 不会直接使用人类可读格式;必须先将其转换为下文所述的二进制格式。

二进制格式详情 每个存储的 n-gram 格式如下:

  1. 4 字节 class_id (UInt,小端序)
  2. 4 字节 n-gram 字节长度 (UInt,小端序)
  3. 原始 n-gram 字节
  4. 4 字节 count (UInt,小端序)

预处理要求 在根据文档语料库创建模型之前,必须先按照指定的 moden 对文档进行预处理,以提取 n-gram。以下步骤概述了预处理过程:

  1. 根据标记化模式,在每个文档的开头和结尾添加边界标记:

    • Byte0x01 (起始) ,0xFF (结束)
    • CodepointU+10FFFE (起始) ,U+10FFFF (结束)
    • Token<s> (起始) ,</s> (结束)

    注意: 文档开头和结尾各添加 (n - 1) 个标记。

  2. token 模式下 n=3 的示例:

    • 文档: "ClickHouse is fast"
    • 处理结果: <s> <s> ClickHouse is fast </s> </s>
    • 生成的三元组:
      • <s> <s> ClickHouse
      • <s> ClickHouse is
      • ClickHouse is fast
      • is fast </s>
      • fast </s> </s>

为简化 bytecodepoint 模式下的模型创建,可先将文档标记化为标记 (byte 模式下为 byte 列表,codepoint 模式下为 codepoint 列表) 。然后,在文档开头添加 n - 1 个起始标记,在文档末尾添加 n - 1 个结束标记。最后,生成 n-grams 并将其写入序列化文件。


evalMLMethod

引入版本:v20.1.0

将训练好的机器学习模型应用于输入特征,生成预测结果。

语法

evalMLMethod(model, x1[, x2, ...])

参数

返回值

返回基于训练后模型的预测值。Float64

示例

使用示例

CREATE TABLE trips (pickup_datetime DateTime('UTC'), trip_distance Float64, total_amount Float64) ENGINE = Memory;

-- A fare of 3, plus 2.5 for every unit of distance.
INSERT INTO trips
SELECT toDateTime('2020-01-01 00:00:00', 'UTC') + number * 60, number % 10 + 1, 2.5 * (number % 10 + 1) + 3
FROM numbers(1000);

-- One model per year of the data.
CREATE TABLE models ENGINE = Memory AS
SELECT
    toYear(pickup_datetime) AS year,
    stochasticLinearRegressionState(0.01, 0.0, 10, 'SGD')(total_amount, trip_distance) AS model
FROM trips
GROUP BY year;

SELECT
    trip_distance,
    round(evalMLMethod(model, trip_distance), 2) AS predicted,
    total_amount
FROM trips
LEFT JOIN models ON year = toYear(pickup_datetime)
ORDER BY pickup_datetime
LIMIT 5
┌─trip_distance─┬─predicted─┬─total_amount─┐
│             1 │      4.05 │          5.5 │
│             2 │      6.79 │            8 │
│             3 │      9.53 │         10.5 │
│             4 │     12.28 │           13 │
│             5 │     15.02 │         15.5 │
└───────────────┴───────────┴──────────────┘

naiveBayesClassifier

引入版本:v25.11.0

使用 NAIVE_BAYES 字典对输入文本进行分类。返回与 dictGet(dictionary_name, class_attribute, input_text) 相同的预测类别值,其中 class_attribute 是在字典 布局 中配置的类别标签属性名称。与 dictGet 不同,返回结果的类型始终为 UInt32,而不是类别属性的声明类型;并且 input_text 必须是 String (不进行键类型转换) 。

语法

naiveBayesClassifier(dictionary_name, input_text)

参数

  • dictionary_name — 使用 NAIVE_BAYES 布局的字典名称。String
  • input_text — 待分类的文本。String

返回值

预测的类别 ID。UInt32

示例

文本分类

-- A dictionary built from the token counts of two classes: 0 for a positive review, 1 for a negative one.
CREATE TABLE review_tokens (ngram String, class_id UInt32, count UInt64) ENGINE = Memory;
INSERT INTO review_tokens VALUES ('good', 0, 5), ('great', 0, 4), ('excellent', 0, 3), ('bad', 1, 5), ('awful', 1, 4), ('terrible', 1, 3);

CREATE DICTIONARY sentiment (ngram String, class_id UInt32 DEFAULT 0, count UInt64 DEFAULT 0)
PRIMARY KEY ngram
SOURCE(CLICKHOUSE(TABLE 'review_tokens'))
LAYOUT(NAIVE_BAYES(class_attribute 'class_id' n 1 mode 'token'))
LIFETIME(0);

SELECT naiveBayesClassifier('sentiment', 'a good and great film') AS class_id;
┌─class_id─┐
│        0 │
└──────────┘

naiveBayesClassifierWithAllProbs

引入版本:v26.7.0

使用 NAIVE_BAYES 字典对输入文本进行分类,并返回所有类别及其对应的概率,按概率从高到低排列。

语法

naiveBayesClassifierWithAllProbs(dictionary_name, input_text)

参数

  • dictionary_name — 采用 NAIVE_BAYES 布局的字典名称。String
  • input_text — 待分类的文本。String

返回值

由 (class_id, probability) Tuple 组成的数组,按概率从高到低排序。Array(Tuple(UInt32, Float64))

示例

所有类别的概率

-- A dictionary built from the token counts of two classes: 0 for a positive review, 1 for a negative one.
CREATE TABLE review_tokens (ngram String, class_id UInt32, count UInt64) ENGINE = Memory;
INSERT INTO review_tokens VALUES ('good', 0, 5), ('great', 0, 4), ('excellent', 0, 3), ('bad', 1, 5), ('awful', 1, 4), ('terrible', 1, 3);

CREATE DICTIONARY sentiment (ngram String, class_id UInt32 DEFAULT 0, count UInt64 DEFAULT 0)
PRIMARY KEY ngram
SOURCE(CLICKHOUSE(TABLE 'review_tokens'))
LAYOUT(NAIVE_BAYES(class_attribute 'class_id' n 1 mode 'token'))
LIFETIME(0);

SELECT arrayMap(p -> (p.1, round(p.2, 4)), naiveBayesClassifierWithAllProbs('sentiment', 'a good and great film')) AS predictions;
┌─predictions─────────────┐
│ [(0,0.9677),(1,0.0323)] │
└─────────────────────────┘

naiveBayesClassifierWithProb

引入版本:v26.7.0

使用 NAIVE_BAYES 字典对输入文本进行分类,并返回预测类别及其概率。

语法

naiveBayesClassifierWithProb(dictionary_name, input_text)

参数

  • dictionary_name — 使用 NAIVE_BAYES 布局的字典名称。 String
  • input_text — 待分类的文本。 String

返回值

(class_id, probability) 组成的 Tuple。 Tuple(UInt32, Float64)

示例

输出分类及其概率

-- A dictionary built from the token counts of two classes: 0 for a positive review, 1 for a negative one.
CREATE TABLE review_tokens (ngram String, class_id UInt32, count UInt64) ENGINE = Memory;
INSERT INTO review_tokens VALUES ('good', 0, 5), ('great', 0, 4), ('excellent', 0, 3), ('bad', 1, 5), ('awful', 1, 4), ('terrible', 1, 3);

CREATE DICTIONARY sentiment (ngram String, class_id UInt32 DEFAULT 0, count UInt64 DEFAULT 0)
PRIMARY KEY ngram
SOURCE(CLICKHOUSE(TABLE 'review_tokens'))
LAYOUT(NAIVE_BAYES(class_attribute 'class_id' n 1 mode 'token'))
LIFETIME(0);

WITH naiveBayesClassifierWithProb('sentiment', 'a good and great film') AS p
SELECT (p.1, round(p.2, 4)) AS prediction;
┌─prediction─┐
│ (0,0.9677) │
└────────────┘
Navigation