1 GBMLlib简介
1.1 GBMLlib简介
GBMLlib是GBase8a的数据挖掘和机器学习扩展库,以插件的形式添加到GBase8a中。通过其提供的机器学习算法,GBase8a可以对用户数据进行深层次的分析和挖掘,将用户数据转化为用户价值,
GBMLlib提供了基于SQL的机器学习算法,目前包括的算法有:回归算法(线性回归)、分类算法(Logistic回归、支持向量机)和聚类算法(K-Means)。同时也提供了一些数组操作和线性代数计算的基本函数。
1.2 技术特点
GBMLlib具备以下技术特征:
1) SQL接口:GBMLlib提供了SQL方式的数据挖掘算法,模型的训练、评估和预测都通过SQL语句来执行,使得数据分析师非常容易掌握,并与其现有技能结合,充分发挥其创造力、提高工作效率。
2) In-database分析:不同于其他分析工具需要通过api或odbc把数据从数据库搬移到分析节点进行处理的方式,GBMLlib的分析算法以数据库udf/udaf的形式运行在GBase8a的线程内部,通过GBase8a的执行计划进行调度,最大程度的减少数据的搬移、提升运行速度。
3) 方便扩展:GBMLlib以插件的形式添加到GBase8a中,并采用弹性灵活的软件架构,方便后续添加新的数据挖掘和机器学习算法。
1.3 产品功能简介
GBMLlib支持的数据挖掘功能如下表所示:
类 别 |
算 法 |
描 述 |
回归 |
线性回归 |
利用数理统计中回归分析,来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法 |
分类 |
Logistic回归 |
二类分类模型,根据现有数据对分类边界建立回归公式,以此进行分类 |
支撑向量机(SVM) |
二类分类模型,模型定义为特征空间上的间隔最大的线性分类器,学习策略为间隔最大化,最终可转化为一个凸二次规划问题的求解。 |
|
聚类 |
K-Means聚类 |
把n个点(可以是样本的一次观察或一个实例)划分到k个聚类中,使得每个点都属于离他最近的均值(此即聚类中心)对应的聚类,以之作为聚类的标准。 |
1.4 名词解释
特征属性:
在关系型数据库中,是指参与到数据挖掘的表字段,也可以称为特征属性,特征字段,特征因子,特征变量等等。
自变量(Independent Variable):
指可以独立发挥作用,一般不可改变的特征指标,比如用户的年龄,性别,职业等等。又可以称为驱动因子,驱动变量,被依赖变量等。大数据挖掘一般通过自变量的不同值的变化发现因变量的变化规律。
因变量(Dependent Variable):
指依赖于一个或多个自变量而变化的特征属性。又可以称为被驱动因子,依赖变量,目标变量,分类变量(class)等等。因变量通常表现为一个主体的行为模式,如是否购买某种产品,是否具有贷款偿还能力等等。大数据挖掘一般着重于发现因变量的变化规律
挖掘算法(Data Mining Algorithm):
一种用数学语言描述的使用数学方法的数据操作过程,也可以称为机器学习算法
2 用法概述
GBMLlib以GBase8a数据库插件形式提供,提供的一系列进行数据挖掘和机器学习的SQL函数。数据分析师在GBase8a的客户端,通过执行SQL命令,就可以进行机器学习建模、模型评估和数据预测等工作。
2.1 数据挖掘流程
- 准备数据GBMLlib直接对GBase8a的数据表进行分析、挖掘,在数据准备阶段,用户把要挖掘的数据组织成数据表,存储到GBase8a中即可。
- 调用GBMLlib挖掘方法对训练数据进行挖掘,挖掘结果存在结果表中。GBMLlib的挖掘函数基本上都会遵循train-predict的命名规则。对于一个挖掘算法,会提供algorithm_train()的训练函数和algorithm_predict()的预测函数,通过train函数训练出的模型保存在结果表中;利用结果表中保存的模型,通过predict函数进行预测。
如下面语句是logistic回归的训练函数调用方法,后面章节详细说明:
SELECT mllib.logregr_train(
'test.patients', -- source table
'test.patients_logregr', -- result table
'second_attack', -- dependent variable
'array double[1, treatment, trait_anxiety]',
-- independent variable
NULL, -- group-by column
20, -- max_iter
0.0001 -- tolerance
);
- 查询结果表查看挖掘结果训练结果保存在用户指定的结果表中(如上例的patients_logregr),同时还会生成一个摘要表,记录训练的摘要信息,摘要表的表名是结果表加上“_summary”,如上例会生成patients_logregr_summary的摘要表。通过查询结果表和摘要表可以查看挖掘结果和模型信息。
- 调用预测函数对新数据进行预测
对新数据预测通过predict()函数完成,函数的输入通常是结果表中保存的模型系数(coefficients)和新数据的数据表因变量。如下面的logistic回归的预测语句:
SELECT p.id,
logregr_predict(
coef, -- coefficients
array double[1, treatment, trait_anxiety] -- independent variable
) as predict,
p.second_attack
FROM patients p, patients_logregr m
ORDER BY p.id;
2.2 数组类型用法说明
GBMLlib提供的数据挖掘算法涉及大量的线性代数运算,需要处理向量和矩阵。向量和矩阵在GBase8a中通过BLOB类型进行存储,同时提供函数把整数和浮点数类型的数据组装成数组和显示数组的内容
- 组装数组
语法:
ARRAY type[ expr1 [, expr2 …] ]
type指定保存到数组中的数据的类型。目前支持double和bigint
示例:
创建t1表,插入数组类型的数据
gbase> create table t1(a int, b blob);
Query OK, 0 rows affected (Elapsed: 00:00:00.01)
gbase> insert into t1 values(1, ARRAY BIGINT[1,2]);
Query OK, 1 row affected (Elapsed: 00:00:00.01)
gbase> insert into t1 values(2, ARRAY BIGINT[3,4]);
Query OK, 1 row affected (Elapsed: 00:00:00.00)
- 显示数组中的数据
语法:
ARRAY_TEXT(expr)
示例:
显示t1表中数组的内容
gbase> select a, ARRAY_TEXT(b) from t1;
+------+---------------+
| a | ARRAY_TEXT(b) |
+------+---------------+
| 1 | {1,2} |
| 2 | {3,4} |
+------+---------------+
2 rows in set (Elapsed: 00:00:00.00)
可以参考下面各个挖掘算法的示例获取更多数组类型使用的信息。
3 回归算法
3.1 线性回归
线性回归模型用来发现一个纯量的因变量与一个或者多个自变量之间的线性关系,并通过此回归公式进行结果预测。
线性回归的示意图如上图,通过训练找到一组系数以便达到对数据的最佳拟合,并将系数在结果表中保存,用于新数据的预测。
3.1.1 训练函数
线性回归的训练函数的语法如下:
linregr_train( source_table,
out_table,
dependent_varname,
independent_varname)
参数说明:
source_table: 含训练数据的输入表
out_table: 保存训练结果的结果表
dependent_varname: 因变量的列名
independent_varname: 自变量的列名,数组类型
结果表说明:
训练函数成功执行后,会创建保存模型信息的结果表,结果表包含如下字段用来表示模型信息:
coef: 相关系数,用于预测
3.1.2 预测函数
Linear回归的预测函数的语法如下:
linregr_predict(coefficients,
ndependent_varname
)
参数说明:
coefficients: 模型结果表中保存的相关系数
independent_varname: 自变量的列名,数组类型
3.1.3 示例
- 创建用于训练的数据表并插入训练数据
CREATE TABLE houses (id INT, tax INT, bedroom INT, bath double, price INT,
size INT, lot INT);
INSERT INTO houses VALUES
( 1, 590, 2, 1, 50000, 770, 22100),
( 2, 1050, 3, 2, 85000, 1410, 12000),
( 3, 20, 3, 1, 22500, 1060, 3500),
( 4, 870, 2, 2, 90000, 1300, 17500),
( 5, 1320, 3, 2, 133000, 1500, 30000),
( 6, 1350, 2, 1, 90500, 820, 25700),
( 7, 2790, 3, 2.5, 260000, 2130, 25000),
( 8, 680, 2, 1, 142500, 1170, 22000),
( 9, 1840, 3, 2, 160000, 1500, 19000),
(10, 3680, 4, 2, 240000, 2790, 20000),
(11, 1660, 3, 1, 87000, 1030, 17500),
(12, 1620, 3, 2, 118600, 1250, 20000),
(13, 3100, 3, 2, 140000, 1760, 38000),
(14, 2070, 2, 3, 148000, 1550, 14000),
(15, 650, 3, 1.5, 65000, 1450, 12000);
- 训练一个分类模型
SELECT mllib.linregr_train( 'madtest.houses',
'madtest.houses_linregr',
'price',
'ARRAY DOUBLE [1, tax, bath, size]'
);
Ø 查看训练结果
gbase> SELECT array_text(coef) FROM houses_linregr \G;
*************************** 1. row ***************************
array_text(coef): {-12849.4168959872,28.9613922651765,10181.6290712648,50.516894915354}
1 row in set (Elapsed: 00:00:00.00)
- 用模型进行预测并显示实际值与预测值的差值
gbase> SELECT houses.id, houses.price,
mllib.linregr_predict( ARRAY DOUBLE [1,tax,bath,size],
m.coef
) AS predict,
(
price -
mllib.linregr_predict( ARRAY DOUBLE [1,tax,bath,size],
m.coef
)
) / price AS deviation
FROM houses, houses_linregr m;
+------+--------+------------------+---------------------+
| id | price | predict | deviation |
+------+--------+------------------+---------------------+
| 1 | 50000 | 53317.4426965542 | -0.0663488539310849 |
| 2 | 85000 | 109152.124955627 | -0.284142646536785 |
| 3 | 22500 | 51459.3486308563 | -1.28708216137139 |
| 4 | 90000 | 98382.215907206 | -0.0931357323022894 |
| 5 | 133000 | 121518.221409606 | 0.0863291623337872 |
| 6 | 90500 | 77853.9455638561 | 0.139735408134187 |
| 7 | 260000 | 201007.926371721 | 0.226892590877995 |
| 8 | 142500 | 76130.7259665617 | 0.465749291462725 |
| 9 | 160000 | 136578.145387498 | 0.146386591328137 |
| 10 | 240000 | 255033.90159623 | -0.0626412566509564 |
| 11 | 87000 | 97440.5250982852 | -0.120006035612473 |
| 12 | 118600 | 117577.415360321 | 0.0086221301827931 |
| 13 | 140000 | 186203.892319613 | -0.330027802282947 |
| 14 | 148000 | 155946.739425521 | -0.0536941853075755 |
| 15 | 65000 | 94497.4293105379 | -0.453806604777507 |
+------+--------+------------------+---------------------+
15 rows in set (Elapsed: 00:00:00.02)
如上的结果是对房屋价格的线性回归预测,其中price列是房屋的实际价格,predict列是通过模型预测的价格, deviation 列是预测价格与实际价格的偏差百分比,从结果可以看出线性模型的基本正确的。
4 分类算法
4.1 Logistic回归
二元logistic回归模型用来发现一个二值 (取值0或者1)的因变量与自变量之间的关系,通过建立回归公式确定自变量数据的分类边界,并通过此回归公式进行分类预测。由于其判别分类的函数使用logistic函数,故称Logistic回归。
Logistic回归的示意图如上图,通过训练找到一个分割超平面,把二元(标记为x的数据和标记为o的数据)的训练数据区分开,并在结果表中保存此分割超平面的系数值,用于新数据的预测。
4.1.1 训练函数
Logistic回归的训练函数的语法如下:
logregr_train( source_table,
out_table,
dependent_varname,
independent_varname,
grouping_cols,
max_iter,
tolerance
)
参数说明:
source_table: 含训练数据的输入表
out_table: 保存训练结果的结果表
dependent_varname: 因变量的列名
independent_varname: 自变量的列名,数组类型
grouping_cols: group_by的列名
max_iter: 最大的迭代次数
tolerance: 容忍度。两次迭代的对数似然差小于该值则结束迭代
结果表说明:
训练函数成功执行后,会创建保存模型信息的结果表,结果表包含如下字段用来表示模型信息:
coef: 相关系数,用于预测
log_likelihood: 对数似然值,训练中评估模型的参数
std_err: 相关系数的标准差
z_stats: 相关系数的z-统计量
num_rows_processed: 处理的数据行数
num_missing_rows_skipped: 略过的数据行数
num_iterations: 迭代次数
摘要表说明:
训练结束还会生出一个摘要表,其名为为结果表表名加上”_summary”,摘要表的字段说明如下:
method: 挖掘算法名称,为logregr
source_table: 输入表名
out_table: 结果表名
dependent_varname: 因变量名
independent_varname: 自变量名
optimizer_params: 优化器参数,最大迭代次数、容忍度等
num_failed_groups: 训练失败的分组数
num_rows_processed: 处理的数据行数
num_missing_rows_skipped: 略过的数据行数
4.1.2 预测函数
Logistic回归的预测函数的语法如下:
logregr_predict(coefficients,
ndependent_varname
)
参数说明:
coefficients: 模型结果表中保存的相关系数
independent_varname: 自变量的列名,数组类型
4.1.3 示例
- 创建用于训练的数据表并插入训练数据
CREATE TABLE patients( id INTEGER NOT NULL,
second_attack INTEGER,
treatment INTEGER,
trait_anxiety INTEGER);
INSERT INTO patients VALUES
( 1, 1, 1, 70),
( 3, 1, 1, 50),
( 5, 1, 0, 40),
( 7, 1, 0, 75),
( 9, 1, 0, 70),
(11, 0, 1, 65),
(13, 0, 1, 45),
(15, 0, 1, 40),
(17, 0, 0, 55),
(19, 0, 0, 50),
( 2, 1, 1, 80),
( 4, 1, 0, 60),
( 6, 1, 0, 65),
( 8, 1, 0, 80),
(10, 1, 0, 60),
(12, 0, 1, 50),
(14, 0, 1, 35),
(16, 0, 1, 50),
(18, 0, 0, 45),
(20, 0, 0, 60)
;
- 训练一个分类模型
SELECT mllib.logregr_train(
'test.patients',
'test.patients_logregr',
'second_attack',
'array double[1, treatment, trait_anxiety]',
NULL,
20,
0.0001
);
- 查看训练结果
gbase> SELECT * FROM patients_logregr\G
*************************** 1. row ***************************
coef: -5.828, -0.888858, 0.108851
log_likelihood: -9.70259
std_err: 2.70859, 1.08267, 0.0461127
z_stats: -2.15168, -0.820985, 2.36054
num_rows_processed: 20
num_missing_rows_skipped: 0
num_iterations: 17
1 row in set (Elapsed: 00:00:00.00)
gbase> select * from test.patients_logregr_summary\G
*************************** 1. row ***************************
method: logregr
source_table: test.patients
out_table: test.patients_logregr
dependent_varname: second_attack
independent_varname: array double[1, treatment, trait_anxiety]
optimizer_params: optimizer=cg, max_iter=20, tolerance=0.0001
num_all_groups: 1
num_failed_groups: 0
num_rows_processed: 20
num_missing_rows_skipped: 0
grouping_col: NULL
1 row in set (Elapsed: 00:00:00.00)
- 用模型进行预测
gbase> SELECT p.id,
-> logregr_predict(
-> coef,
-> array double[1, treatment, trait_anxiety]
-> ) as predict,
-> p.second_attack
-> FROM patients p, patients_logregr m
-> ORDER BY p.id;
+----+---------+---------------+
| id | predict | second_attack |
+----+---------+---------------+
| 1 | 1 | 1 |
| 2 | 1 | 1 |
| 3 | 0 | 1 |
| 4 | 1 | 1 |
| 5 | 0 | 1 |
| 6 | 1 | 1 |
| 7 | 1 | 1 |
| 8 | 1 | 1 |
| 9 | 1 | 1 |
| 10 | 1 | 1 |
| 11 | 1 | 0 |
| 12 | 0 | 0 |
| 13 | 0 | 0 |
| 14 | 0 | 0 |
| 15 | 0 | 0 |
| 16 | 0 | 0 |
| 17 | 1 | 0 |
| 18 | 0 | 0 |
| 19 | 0 | 0 |
| 20 | 1 | 0 |
+----+---------+---------------+
20 rows in set (Elapsed: 00:00:00.00)
预测语句输出的id列代表不同的患者,predict列的值代表对患者是否会复发的预测值(0代表不复发,1代表复发),second_attach列的值是患者是否复发的真实值,模型的预测准确度为80%,由此可知使用Logistic回归模型进行分析是比较恰当的。
4.2 支持向量机
支持向量机(SVM)也是一种二元分类算法,支持向量机模型的一个显著的优点是对噪声数据的鲁棒性。线性支持向量机采用线性超平面进行数据分类。
支持向量机模型是求解分割超平面与最近的训练数据的距离(称为边界)最大化的问题。处于边界线上的点称为支持向量,当支持向量确定后,不在边界线上的点的变化不会影响模型的结果,这个特性保证了支持向量机的鲁棒性。
4.2.1 训练函数
支持向量机分类模型的训练函数的语法如下:
svm_classification(
source_table,
model_table,
dependent_varname,
independent_varname,
grouping_col,
params
)
参数说明:
source_table: 含训练数据的输入表
model _table: 保存训练结果的结果表
dependent_varname: 因变量的列名
independent_varname: 自变量的列名,数组类型
grouping_cols: group_by的列名
params: 模型训练参数
其中的模型训练参数(params)是以逗号分割的键-值(key-value)对,支持的键值如下:
init_stepsize(初始步长)
缺省值: [0.01]. 初始的学习步长。一个比较小的值可以保证收敛结果,而较大的值可以提高修炼速度。
decay_factor(衰减系数)
缺省值: [0.9].控制迭代过程中使用的学习步长: 0 表示恒定步长; -1 表示反向缩放, 步长 = 初始步长 / 迭代次数; > 0 表示指数衰减, 步长 = 初始步长 *衰减系数^迭代次数。
max_iter(最大迭代次数)
缺省值: [100].
tolerance(容忍度)
缺省值: 1e-10. 两次迭代的模型差值小于容忍度时结束迭代。
Lambda(正则化参数)
缺省值: [0.01]. 必须大于0,不能为负值。
结果表说明:
训练函数成功执行后,会创建保存模型信息的结果表,结果表包含如下字段用来表示模型信息:
coef: 相关系数,用于预测
loss: 损失函数值
norm_of_gradient: 损失函数的梯度值
num_iterations: 迭代次数
num_rows_processed: 处理的数据行数
num_rows_skipped: 略过的数据行数
dep_var_mapping: 因变量的可能取值
摘要表说明:
训练结束还会生出一个摘要表,其名为为结果表表名加上”_summary”,摘要表的字段说明如下:
method: 挖掘算法名称,SVC代表SVM分类算法
source_table: 输入表名
model_table: 结果表名
dependent_varname: 因变量名
independent_varname: 自变量名
grouping_col: 分组列名
optim_params: 优化参数
num_all_groups: 全部分组数
num_failed_groups: 训练失败分组数
total_rows_processed: 处理的数据行数
total_rows_skipped: 略过的数据行数
4.2.2 预测函数
支持向量机的预测函数的语法如下:
svm_predict(model_table,
new_data_table,
id_col_name,
output_table)
参数说明:
model_table: 模型结果表
new_data_table: 要预测的新数据表
id_col_name: 新数据表的id标识列
output_table: 保存预测结果的表
4.2.3 示例
- 创建用于训练的数据表并插入训练数据
CREATE TABLE houses (id INT, tax INT, bedroom INT, bath REAL, price INT,
size INT, lot INT);
INSERT INTO houses VALUES
( 1, 590, 2, 1, 50000, 770, 22100),
( 2, 1050, 3, 2, 85000, 1410, 12000),
( 3, 20, 3, 1, 22500, 1060, 3500),
( 4, 870, 2, 2, 90000, 1300, 17500),
( 5, 1320, 3, 2, 133000, 1500, 30000),
( 6, 1350, 2, 1, 90500, 820, 25700),
( 7, 2790, 3, 2.5, 260000, 2130, 25000),
( 8, 680, 2, 1, 142500, 1170, 22000),
( 9, 1840, 3, 2, 160000, 1500, 19000),
(10, 3680, 4, 2, 240000, 2790, 20000),
(11, 1660, 3, 1, 87000, 1030, 17500),
(12, 1620, 3, 2, 118600, 1250, 20000),
(13, 3100, 3, 2, 140000, 1760, 38000),
(14, 2070, 2, 3, 148000, 1550, 14000),
(15, 650, 3, 1.5, 65000, 1450, 12000)
;
Ø 训练一个支持向量机分类模型
SELECT mllib.svm_classification(
'test.houses',
'test.houses_svm',
'price < 100000',
'array double[1, tax, bath, size]',
'',
'max_iter=20'
);
Ø 查看训练结果
gbase> SELECT * FROM houses_svm\G
*************************** 1. row ***************************
coef: 0.103513, -1.17016, -0.0573659, 1.29247
loss: 14119.6
norm_of_gradient: 21880
num_iterations: 20
num_rows_processed: 15
num_rows_skipped: 0
dep_var_mapping: 0,1
1 row in set (Elapsed: 00:00:00.00)
gbase> SELECT * FROM houses_svm_summary\G
*************************** 1. row ***************************
method: SVC
source_table: test.houses
model_table: test.houses_svm
dependent_varname: price < 100000
independent_varname: array double[1, tax, bath, size]
grouping_col: NULL
optim_params: init_stepsize=0.01,
decay_factor=0.9,
max_iter=20,
tolerance=1e-10,
epsilon=0.01,
eps_table=,
class_weight=
num_all_groups: 1
num_failed_groups: 0
total_rows_processed: 15
total_rows_skipped: 0
1 row in set (Elapsed: 00:00:00.00)
- 用模型进行预测
gbase> SELECT mllib.svm_predict('test.houses_svm', 'test.houses', 'id', 'test.houses_pred') as result;
+---------+
| result |
+---------+
| Success |
+---------+
1 row in set (Elapsed: 00:00:00.02)
gbase> SELECT id, prediction, (price < 100000) as pred_target FROM houses JOIN houses_pred USING (id) ORDER BY id;
+------+------------+-------------+
| id | prediction | pred_target |
+------+------------+-------------+
| 1 | 1 | 1 |
| 2 | 1 | 1 |
| 3 | 1 | 1 |
| 4 | 1 | 1 |
| 5 | 1 | 0 |
| 6 | 0 | 1 |
| 7 | 0 | 0 |
| 8 | 1 | 0 |
| 9 | 0 | 0 |
| 10 | 0 | 0 |
| 11 | 0 | 1 |
| 12 | 0 | 0 |
| 13 | 0 | 0 |
| 14 | 0 | 0 |
| 15 | 1 | 1 |
+------+------------+-------------+
15 rows in set (Elapsed: 00:00:00.00)
如上的预测查询语句是使用支持向量机模型判断房屋价格是否少于100000。id列为房屋编号,prediction列是预测结果(1代表少于100000,0代表不少于100000),pred_target是实际情况,从输出结果看,模型得准确率为73.3%,由此可以判断持向量机模型基本正确。
5 聚类算法
5.1 k-Means聚类
k-Means 算法是聚类算法的一种,目标是把 n 个样本点划分到 k 个类簇中,使得每个样本点都属于理他最近的质心对应的类簇,以之作为聚类的标准,如下图所示:
5.1.0.1 聚类函数
5.1.0.2 k-Means 算法
k-Means 算法通过计算和比较各个点与指定种子点(质心点)的距离来对原始点进行分类并计算出新的质心点,反复迭代,直到分组变化小于期望值或者迭代次数已满,然后结束迭代并生成结果表。
kmeans函数的语法如下:
kmeans ( source_table,
expr_point,
initial_centroids,
fn_dist,
agg_centrioid,
max_num_iterations,
min_frac_reassinged
)
参数说明:
source_table: 含训练数据的输入表,形如 “库名.表名”,
库名不可省略,以便在对应的库中建立结果表。
expr_point: 表达式,用于从表中计算得到坐标点
initial_centroids: 包含初始质心点的二维数组
fn_dist: 用于计算点距的函数名,参见5.1.1.4, 推
荐使用 mllib.squared_dist_norm2。
agg_centrioid: 聚集函数,用于给定一组输入点时,计算得到
质心点,推荐使用 mllib.avg_vector.
max_num_iterations: 最大的迭代次数
min_frac_reassinged: 容忍度,迭代过程中如发现分组发生变化的
点数占总点数量的比例小于该值则结束迭代
结果表说明:
聚类函数成功执行后,会创建保存模型信息的结果表,结果表包含如下字段用来表示模型信息:
iteration: 进行的迭代次数
centroids: 聚类形成的质心点
frac_reassigned: 迭代结束时分组发生改变的点与总点数的占比
k-Means 算法对初始种子有很大依赖,不同的种子有时会得到不同的结果。目前 GBMLlib 提供了额外的两种算法 kmeans_random 和 kmeanpp 算法:分别使用随机算法和 kmeans++ 算法来自动选取初始种子并开始 k-Means 迭代,两种方法生成的结果表与本节介绍的结果表相同。
5.1.0.3 kmeans_random
kmeans_random算法通过随机选取种子点来开始迭代,实现简单,但如果初始种子选取不当,则聚类的结果可能不理想。
kmeans_random函数的语法如下:
kmeans_random( source_table,
expr_point,
dependent_varname,
k,
fn_dist,
agg_centrioid,
max_num_iterations,
min_frac_reassinged
)
参数说明:
source_table: 含训练数据的输入表,形如 “库名.表名”,
库名不可省略,以便在对应的库中建立结果表。
expr_point: 表达式,用于从表中计算得到坐标点
k: 最终的类簇数量
fn_dist: 用于计算点距的函数名,参见5.1.1.4, 推
荐使用 mllib.squared_dist_norm2。
agg_centrioid: 聚集函数,用于给定一组输入点时,计算得到
质心点,推荐使用 mllib.avg_vector.
max_num_iterations: 最大的迭代次数
min_frac_reassinged: 容忍度,迭代过程中如发现分组发生变化的
点数占总点数量的比例小于该值则结束迭代
5.1.0.4 kmeanspp
kmeanspp通过 k-means++ 算法来选取种子点并开始迭代。 k-mean++ 算法通过让初始种子点尽量离散来改进分类结果。
函数的语法如下:
kmeanspp( source_table,
expr_point,
dependent_varname,
k,
fn_dist,
agg_centrioid,
max_num_iterations,
min_frac_reassinged,
seeding_sample_rate
)
参数说明:
source_table: 含训练数据的输入表,形如 “库名.表名”,
库名不可省略,以便在对应的库中建立结果表。
expr_point: 表达式,用于从表中计算得到坐标点
k: 最终的类簇数量
fn_dist: 用于计算点距的函数名,参见5.1.1.4, 推
荐使用 mllib.squared_dist_norm2。
agg_centrioid: 聚集函数,用于给定一组输入点时,计算得到
质心点,推荐使用 mllib.avg_vector.
max_num_iterations: 最大的迭代次数
min_frac_reassinged: 容忍度,迭代过程中如发现分组发生变化的
点数占总点数量的比例小于该值则结束迭代
seeding_sample_rate: 采样率,取值范围 。如果为 1.0,
则采样时使用全部数据;小于 1.0 则仅使用
部分数据。
5.1.0.5 距离函数
k-Means 算法通过距离函数来计算点与点之间的距离,目前内置的函数包括:
- squared_dist_norm2
欧式距离的平方,计算公式如下:
- dist_norm2
欧式距离,计算公式如下:
- dist_norm1
L1模距离,计算公式如下:
- dist_angle
夹角的余弦值,计算公式如下:
- dist_tanimotoo
tanimotoo相似度值,计算公式如下:
5.1.1 示例
本例采用的数据为某配送车队的 4000 名司机的驾驶数据,可以从 https://raw.githubusercontent.com/datascienceinc/learn-data-science/master/Introduction-to-K-means-Clustering/Data/data_1024.csv 上下载得到。为了便利绘图,这里只选取数据中的两列作为参考因素:
1. 一天的平均距离
2. 一天中超速超过 5 mph 的时间占工作时间的比例
Ø 创建用于训练的数据表并插入训练数据
DROP TABLE IF EXISTS km_sample;
CREATE TABLE km_sample
(
Driver_ID BIGINT,
Distance_Feature DOUBLE,
Speeding_Feature DOUBLE
);
LOAD DATA INFILE 'https://raw.githubusercontent.com/datascienceinc/learn-data-science/master/Introduction-to-K-means-Clustering/Data/data_1024.cs' INTO TABLE km_sample FIELDS TERMINATED BY ' ' preserve blanks;
- 对输入进行聚类,以 kmeanspp为例:
SELECT mllib.kmeanspp ('madtest.km_sample',
ARRAY DOUBLE [Distance_Feature, Speeding_Feature],
2,
'squared_dist_norm2',
'avg_vector',
20, 0.001, 1.0);
- 查看结果表
gbase> select iteration, array_text(centroids), frac_reassigned from km_sample_result \G;
*************************** 1. row ***************************
iteration: 3
array_text(centroids): {{180.017075,18.29},{50.047634375,8.82875}}
frac_reassigned: 0
1 row in set (Elapsed: 00:00:00.00)
- 通过 closest_column 函数显示具体分组:
gbase>SELECT
_src.pid AS pid,
array_text(ARRAY DOUBLE [_src.Distance_Feature, _src.Speeding_Feature]) AS point,
closest_column
(
(
SELECT
rel_result.centroids
FROM
km_sample_result as rel_result
),
ARRAY DOUBLE [_src.Distance_Feature, _src.Speeding_Feature],
'squared_dist_norm2',
'squared_dist_norm2'
)
AS cluster_id
FROM km_sample AS _src ORDER BY cluster_id;
+------------+--------------+------------+
| pid | point | cluster_id |
+------------+--------------+------------+
| 3423312310 | {199.92,0} | 0 |
| 3423312424 | {190.94,20} | 0 |
| 3423312071 | {200.05,9} | 0 |
| 3423311718 | {200.41,7} | 0 |
| 3423311409 | {170.58,22} | 0 |
| 3423313707 | {211.26,6} | 0 |
| .......... | ........... | ...........|
| 3423311860 | {56.24,5} | 1 |
| 3423310540 | {43.69,4} | 1 |
| 3423314226 | {33.56,7} | 1 |
| 3423311407 | {54.64,5} | 1 |
| 3423311944 | {57.68,2} | 1 |
| 3423313012 | {41.35,23} | 1 |
| 3423310869 | {81.96,27} | 1 |
+------------+--------------+------------+
- 通过 gnuplot直观显示分组与质心点:
n k=2
下图通过 gnuplot 直观展示了前面示例中 k=2 时的聚类结果:
图中绿色点和红色点分别代表两个聚类,蓝色点表示质心点。图中可以明显看出,这些司机大致可以分成两类,一类每天的驾驶距离较近,估计主要在市区内进行配送,另外一类则距离较远,主要从事市外配送。
n k=3
下图展示了当 k 设置为 3 时的聚类结果,从中可以看出,从事市内短途运输的司机还可以细分成为两类,其中一类经常超速行驶。
n k=4
k=4时的聚类结果如下图所示:
该结果并未将远途运输的司机也细分成经常超速和不经常超速两类,而是将超速的短途运输司机进行了细化。这可能是因为从事远途运输的司机数量过小的缘故:
gbase> select count(*) from sample where Distance_Feature > 120;
+----------+
| count(*) |
+----------+
| 799 |
+----------+
1 row in set (Elapsed: 00:00:00.00)