基本算法——聚类
目录
创建工程
加载数据
聚类算法
评估
完整代码
结论
相比于有监督的分类器,聚类的目标是从一组未打标签的数据中识别相似对象组。它可 以用于识别同类群体的代表性样本,找到有用与合适的分组;或者找到不寻常的样本,比如 异常值。
下面通过分析银行数据集演示如何实现聚类。数据集包含600个实例,每个实例用11个属性 进行描述,这些属性包括年龄、性别、地区、收入、婚姻状况、是否有子女、汽车拥有情况、存 款活动、当前活动、房地产抵押、PEP。分析中,我们将尝试使用EM(Expectation Maximization, 期望最大化)聚类算法识别常见的客户组。
EM工作过程如下:给定一组簇(clusters),EM首先为每个实例指派一个属于某个特定簇的 概率分布。比如,起初有3个簇A、B、C,一个实例分别属于簇A、B、C的概率分布依次为0.7、 0.10、0.20。第二步中,EM重新评估每个类的概率分布的参数向量。算法不断对这两步做迭代, 直到参数收敛或者达到迭代的最大值。
对于EM中使用的簇数,可以手动设置,也可以通过交叉验证进行自动设置。另外一个确 定数据集中簇数的方法是肘部法则(elbow-method),这个方法会查看特定簇数所解释的偏差 百分比。使用该方法会不断增加簇数,直到新加的簇不会带来很多信息,即只能解释很少的额外 差异。
创建工程
依然使用上一篇文章的工程
加载数据
// 从文件中读取数据集
Instances data = new Instances(new BufferedReader(new FileReader(PATH)));
聚类算法
创建聚类模型的过程与创建分类模型的过程很类似,即加载数据与创建模型。Weka中,使 用weka.clusterers包实现聚类算法
// 创建一个新的聚类器实例
EM model = new EM();
// 构建聚类模型
model.buildClusterer(data);
// 打印聚类模型的详细信息
System.out.println(model);
EM
==
Number of clusters selected by cross validation: 6
Number of iterations performed: 100
Cluster
Attribute 0 1 2 3 4 5
(0.1) (0.13) (0.26) (0.25) (0.12) (0.14)
======================================================================
age
0_34 10.0535 51.8472 122.2815 12.6207 3.1023 1.0948
35_51 38.6282 24.4056 29.6252 89.4447 34.5208 3.3755
52_max 13.4293 6.693 6.3459 50.8984 37.861 81.7724
[total] 62.1111 82.9457 158.2526 152.9638 75.4841 86.2428
sex
FEMALE 27.1812 32.2338 77.9304 83.5129 40.3199 44.8218
MALE 33.9299 49.7119 79.3222 68.4509 34.1642 40.421
[total] 61.1111 81.9457 157.2526 151.9638 74.4841 85.2428
region
INNER_CITY 26.1651 46.7431 73.874 60.1973 33.3759 34.6445
TOWN 24.6991 13.0716 48.4446 53.1731 21.617 17.9946
RURAL 8.4113 12.7871 21.7634 25.7529 11.1622 22.1231
SUBURBAN 3.8356 11.344 15.1706 14.8404 10.3289 12.4805
[total] 63.1111 83.9457 159.2526 153.9638 76.4841 87.2428
income
0_24386 22.5301 77.3981 150.8728 35.3652 3.0947 1.7391
24387_43758 38.0636 4.5119 6.2909 113.3875 70.4654 8.2808
43759_max 1.5174 1.0357 1.0889 4.2111 1.924 76.2228
[total] 62.1111 82.9457 158.2526 152.9638 75.4841 86.2428
married
NO 15.0163 34.8213 48.6021 32.7954 49.5126 29.2523
YES 46.0948 47.1244 108.6506 119.1684 24.9715 55.9904
[total] 61.1111 81.9457 157.2526 151.9638 74.4841 85.2428
children
0 2.1776 53.2782 55.6363 92.5938 32.663 32.6511
1 51.5497 26.7841 22.0968 1.9302 18.9418 19.6973
2 6.4264 2.3777 56.5523 25.7573 23.3335 25.5529
3 2.9574 1.5057 24.9671 33.6825 1.5458 9.3415
[total] 63.1111 83.9457 159.2526 153.9638 76.4841 87.2428
car
NO 29.7462 47.4075 89.7372 69.5918 34.7847 38.7326
YES 31.3649 34.5382 67.5154 82.372 39.6993 46.5101
[total] 61.1111 81.9457 157.2526 151.9638 74.4841 85.2428
save_act
NO 6.7118 58.9844 49.6095 39.7853 35.7784 1.1306
YES 54.3993 22.9613 107.6431 112.1785 38.7056 84.1121
[total] 61.1111 81.9457 157.2526 151.9638 74.4841 85.2428
current_act
NO 12.8656 21.8946 35.3337 46.1845 15.9243 18.7973
YES 48.2455 60.0511 121.9189 105.7792 58.5598 66.4455
[total] 61.1111 81.9457 157.2526 151.9638 74.4841 85.2428
mortgage
NO 34.2814 47.6791 108.1248 95.3628 54.1015 57.4504
YES 26.8297 34.2666 49.1278 56.601 20.3826 27.7924
[total] 61.1111 81.9457 157.2526 151.9638 74.4841 85.2428
pep
YES 59.0226 72.2592 18.5799 3.8416 68.4764 57.8202
NO 2.0885 9.6865 138.6727 148.1222 6.0076 27.4226
[total] 61.1111 81.9457 157.2526 151.9638 74.4841 85.2428
-8.773422954298614
第一行表明有6个簇,第一列指出属性及相应范围。比如,属性age划分为3 个区段:0~34、35~51、52~max。左侧列表示有多少个实例归入每个簇的特定范围,比如0~34 年龄组的客户大部分位于簇#2(122个实例)。
评估
可以使用对数似然度量(log likelihood measure)评估聚类算法的质量,即测量被识别的簇的 一致程度。数据集划分为多个折(folds),针对每个折运行聚类。这么做的动机是,如果聚类算 法为相似数据(该数据不用于拟合参数)给出高概率,那么它在捕获数据结构方面可能做得很好。
// 使用 10 折交叉验证评估模型的对数似然值
double logLikelihood = ClusterEvaluation.crossValidateModel(model, data, 10, new Random(1));
// 打印对数似然值
System.out.println(logLikelihood);
评估结果:-8.773422954298614
完整代码
private static String PATH = ClassUtils.getDefaultClassLoader().getResource("bank-data.arff").getPath();
public static void main(String[] args) throws Exception {
// 从文件中读取数据集
Instances data = new Instances(new BufferedReader(new FileReader(PATH)));
// 创建一个新的聚类器实例
EM model = new EM();
// 构建聚类模型
model.buildClusterer(data);
// 打印聚类模型的详细信息
System.out.println(model);
// 使用 10 折交叉验证评估模型的对数似然值
double logLikelihood = ClusterEvaluation.crossValidateModel(model, data, 10, new Random(1));
// 打印对数似然值
System.out.println(logLikelihood);
}
结论
1. 聚类数量: 交叉验证选择的最佳聚类数量为 6 个。
2. 迭代次数: 模型进行了 100 次迭代。
3. 聚类特征分布:
- **年龄(age)**:
- 年龄在 52 岁以上的个体在聚类 5 中有较高的比例。
- 年龄在 35-51 岁的个体在聚类 3 中有较高的比例。
- **性别(sex)**:
- 女性的比例在聚类 2、3 和 6 中较高。
- 男性的比例在聚类 1 和 4 中较高。
- **地区(region)**:
- 内城(INNER_CITY)和郊区(SUBURBAN)的个体在聚类 0 和 5 中较高。
- 农村和城镇的个体在聚类 2 和 3 中较高。
- **收入(income)**:
- 高收入个体(43759_max)在聚类 5 中比例较高。
- 中等收入个体(24387_43758)在聚类 3 中比例较高。
- **婚姻状况(married)**:
- 未婚个体在聚类 4 中比例较高。
- 已婚个体在聚类 3 和 6 中比例较高。
- **子女数量(children)**:
- 无子女的个体在聚类 3 中比例较高。
- 有多个子女的个体在聚类 0 和 5 中比例较高。
- **是否有车(car)**:
- 无车的个体在聚类 2 中比例较高。
- 有车的个体在聚类 3 和 4 中比例较高。
- **是否有储蓄账户(save_act)**:
- 有储蓄账户的个体在聚类 6 中比例较高。
- 无储蓄账户的个体在聚类 5 中比例较低。
- **是否有当前账户(current_act)**:
- 无当前账户的个体在聚类 0 和 5 中比例较低。
- 有当前账户的个体在聚类 3 和 4 中比例较高。
- **是否有抵押贷款(mortgage)**:
- 无抵押贷款的个体在聚类 3 和 4 中比例较高。
- 有抵押贷款的个体在聚类 6 中比例较低。
- **是否有个人养老计划(pep)**:
- 有个人养老计划的个体在聚类 1 和 4 中比例较高。
- 无个人养老计划的个体在聚类 2 和 3 中比例较高。
4. 目标变量:结果显示目标变量的得分(-8.773422954298614),这可能是一个对数似然值或某种损失函数的值,表示模型在训练数据上的拟合程度。