![cover](https://img-blog.csdnimg.cn/dbe0219ceca44bbf8d70b89f7702bef7.png)
[学习笔记] [机器学习] 8. 聚类算法(聚类算法:K-means、K-means++;聚类算法评估;特征降维:特征选择(Pearson相关系数、Spearman相关系数)、PCA主成分分析)
聚类算法:K-means、K-means++;聚类算法评估;特征降维:特征选择(Pearson相关系数、Spearman相关系数)、PCA主成分分析
- 视频链接
- 数据集下载地址:无需下载
1. 聚类算法简介
学习目标:
- 掌握聚类算法实现过程
- 知道 K-means 算法原理
- 知道聚类算法中的评估模型
- 说明 K-means 的优缺点
- 了解聚类中的算法优化方式
- 知道特征降维的实现过程
- 应用 K-means 实现聚类任务
1.1 认识聚类算法
使用不同的聚类准则,产生的聚类结果不同。
1.2 聚类算法在现实中的应用
- 用户画像、广告推荐、Data Segmentation、搜索引擎的流量推荐、恶意流量识别
- 基于位置信息的商业推送、新闻聚类、筛选排序
- 图像分割、降维、识别;离群点检测;信用卡异常消费;发掘相同功能的基因片段
1.3 聚类算法的概念
聚类算法:是一种典型的无监督学习算法,主要用于将相似的样本自动归到一个类别中。
在聚类算法中根据样本之间的相似性,将样本划分到不同的类别中,使用不同的相似度计算方法,会得到不同的聚类结果,常用的相似度计算方法有欧式距离法。
1.4 聚类算法与分类算法最大的区别
聚类算法是 无监督 的学习算法,而分类算法属于 监督 的学习算法。
小结:
- 聚类算法分类【了解】
- 粗聚类
- 细聚类
- 聚类的定义【了解】
- 一种典型的无监督学习算法
- 主要用于将相似的样本自动归到一个类别中
- 计算样本和样本之间的相似性,一般使用欧式距离
2. K-means 聚类算法 API 的初步使用
学习目标:
- 知道聚类算法 API 的使用
Q:为什么叫 K-means,K和means分别有什么含义?
A:K-means 聚类算法的名字中的 “K” 表示聚类的数量,而 “means” 表示每个聚类的中心是通过计算该聚类中所有样本的均值得到的。因此,K-means 聚类算法的目标是将给定数据集划分为 K 个簇,使得每个簇内部数据点之间的相似度尽可能高,而不同簇之间的相似度尽可能低。这种划分方法通过迭代寻找 K 个簇的一种划分方案,使得聚类结果对应的损失函数最小。
2.1 API介绍
sklearn.cluster.KMeans(n_clusters=8)
sklearn.cluster.KMeans
是 scikit-learn 库中的一个类,用于执行 K-means 聚类算法。
- 主要参数:
n_clusters
:int 类型,默认值为 8。要形成的簇数以及要生成的质心数。init
:{‘k-means++’, ‘random’}、可调用对象或形状为 (n_clusters, n_features) 的数组, 默认值为 ‘k-means++’。初始化方法。n_init
:‘auto’ 或 int 类型,默认值为 10。使用不同质心种子运行 K-means 算法的次数。最终结果是 n_init 连续运行中惯性最好的输出。max_iter
:int 类型,默认值为 300。单次运行 K-means 算法的最大迭代次数。tol
:float 类型,默认值为 1e-4。两次连续迭代之间簇中心差异的 Frobenius 范数相对容差,用于声明收敛。verbose
:int 类型,默认值为 0。详细模式。random_state
:int、RandomState 实例或 None,默认值为 None。确定质心初始化的随机数生成。copy_x
:bool 类型,默认值为 True。预计算距离时,首先居中数据更具数值精度。algorithm
:{“lloyd”, “elkan”, “auto”, “full”},默认值为 “lloyd”。使用的 K-means 算法。
- 返回值:
- 该函数返回一个
KMeans
对象,可以使用其方法(如fit
、predict
等)对数据进行聚类分析。
- 该函数返回一个
- 方法:
fit(X[, y, sample_weight])
:计算 K-means 聚类。fit_predict(X[, y, sample_weight])
:计算聚类中心并预测每个样本所属的簇索引。fit_transform(X[, y, sample_weight])
:计算聚类中心并转换 X 以聚类距离。get_params([deep])
:获取此估计器的参数。predict(X)
:预测最近的簇中心每个样本所属的簇。score(X[, y, sample_weight])
:对给定数据 X 的 KMeans 模型进行评分。set_params(**params)
:设置此估计器的参数。transform(X)
:将 X 转换为簇距离空间。
2.2 案例
随机创建不同二维数据集作为训练集,并结合 K-means算法将其聚类,你可以尝试分别聚类不同数量的簇,并观察聚类效果:
聚类参数 n_cluster
传值不同,得到的聚类结果不同:
2.2.1 流程分析
- 导入工具库
- 创建数据集并显示
- 应用 K-means
- 显示结果
2.2.2 代码实现
import matplotlib.pyplot as plt
from sklearn.datasets._samples_generator import make_blobs
from sklearn.cluster import KMeans
from sklearn.metrics import calinski_harabasz_score
# 1. 创建数据集
# X为样本特征y为样本簇类别,共1000个样本,每个样本有4个特征,共4个簇
# 簇中心在[-1, -1], [0, 0], [1, 1], [2, 2],簇方差分别为[0.4, 0.2, 0.2, 0.2]
X, y = make_blobs(n_samples=1000, n_features=2, centers=[[-1, -1], [0, 0], [1, 1], [2, 2]],
cluster_std=[0.4, 0.2, 0.2, 0.2], random_state=9)
# 数据集可视化
plt.figure(dpi=300)
plt.scatter(X[:, 0], X[:, 1], marker='o')
plt.show()
# 2. 使用K-means进行聚类,并使用CH方法评估
y_pred = KMeans(n_clusters=2, random_state=9).fit_predict(X)
plt.figure(dpi=300)
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.show()
# 用CH方法评估聚类得分
print(calinski_harabasz_score(X=X, labels=y_pred))
分别尝试 n_clusters=2/3/4
,然后查看聚类效果:
fig, axes = plt.subplots(1, 3, figsize=(20, 5),dpi=300)
n_clusters_ls = [2, 3, 4]
for idx, val in enumerate(n_clusters_ls):
# 2. 使用K-means进行聚类,并使用CH方法评估
y_pred = KMeans(n_clusters=val, random_state=9).fit_predict(X)
axes[idx].scatter(X[:, 0], X[:, 1], c=y_pred)
axes[idx].set_title(f"n_cluster={val}")
# 用CH方法评估聚类得分
print(f"n_clusters为{val}时的CH评分为:", calinski_harabasz_score(X=X, labels=y_pred))
plt.savefig("./不同n_clusters的聚类结果.png")
plt.show()
n_clusters为2时的CH评分为: 3116.1706763322227
n_clusters为3时的CH评分为: 2931.625030199556
n_clusters为4时的CH评分为: 5924.050613480169
【补充】CH 方法是指 Calinski-Harabasz Index,它是一种用于评估聚类模型的指标。它通过计算类中各点与类中心的距离平方和来度量类内的紧密度,通过计算各类中心点与数据集中心点距离平方和来度量数据集的分离度,CH 指标由分离度与紧密度的比值得到。这个指标越大,说明聚类效果越好。
小结:
- API:
sklearn.cluster.KMeans(n_clusters=8)
【知道】- 参数:
n_clusters
:开始的聚类中心数量
- 方法:
estimator.fit_predict(x)
:计算聚类中心并预测每个样本属于哪个类别。- 相当于先调用
fit(x)
,然后再调用predict(x)
- 相当于先调用
- 参数:
3. K-means 聚类算法实现流程
学习目标:
- 掌握 K-means 聚类的实现步骤
- K-means 其实包含两层内容:
K
:初始中心点个数(计划聚类的类数)means
:求中心点到其他数据点距离的平均值
3.1 K-means 聚类的步骤
- 随机设置 K 个特征空间内的点作为初始的聚类中心
- 对于其他每个点计算到 K 个中心的距离,未知的点选择最近的一个聚类中心点作为标记类别
- 接着对着标记的聚类中心之后,重新计算出每个聚类的新中心点(平均值)
- 如果计算得出的新中心点与原中心点一样(质心不再移动),那么结束;否则重新进行第二步过程
这个中心点不一定是数据集中已有的点,可以是一个新建的点。
通过下图解释实现流程:
动态图演示:
●点是样本,× 是聚类的中心,几个 × 就代表着我们要聚成几个类。
3.2 案例练习
步骤一:随机设置 K K K 个特征空间内的点作为初始的聚类中心(本案例中初始聚类中心设置为 P1 和 P2)
步骤二:对于其他每个点计算到 K K K 个中心的距离,未知的点选择最近的一个聚类中心点作为标记类别。
步骤三:接着对着标记的聚类中心之后,重新计算出每个聚类的新中心点(平均值)
步骤四:如果计算得出的新中心点与原中心点一样(质心不再移动),那么结束;否则重新进行第二步过程【经过判断,需要重复上述步骤,开始新一轮迭代】
注意:当每次迭代结果不变时,认为算法收敛,聚类完成,K-means 一定会停下,不可能陷入一直选质心的过程。
小结:
- K-means 聚类实现流程【掌握】
- 事先确定常数 K K K,常数 K K K 意味着最终的聚类类别数
- 随机选定初始点为质心,并通过计算每一个样本与质心之间的相似度(这里为欧式距离),将样本点归到最相似的类中
- 接着,重新计算每个类的质心(即为类中心),重复这样的过程,直到质心不再改变,最终就确定了每个样本所属的类别以及每个类的质心。
- 注意:
- 由于每次都要计算所有的样本与每一个质心之间的相似度,故在大规模的数据集上,K-Means 算法的收敛速度比较慢。
4. 聚类模型评估
学习目标:
- 知道模型评估中的 SSE、“肘”部法、SC 系数和 CH 系数的实现原理
4. 聚类模型评估
由于聚类是一种无监督学习方法,因此评估聚类模型的效果并不像监督学习那样直接。常用的聚类模型评估指标包括 SSE(误差平方和)、“肘”部法、SC 系数(轮廓系数)和 CH 系数(Calinski-Harabasz Index)等。这些指标可以帮助我们评估聚类算法效果并选择最佳参数。
4.1 误差平方和(The sum of squares due to error,SSE)
举例:(下图中数据 -0.2, 0.4, -0.8, 1.3, -0.7 均为真实值和预测值的差)
在 K-means 中的应用:
S S E = ∑ i = 1 k ∑ p ∈ C i ∣ p − m i ∣ 2 \mathrm{SSE} = \sum^k_{i=1}\sum_{p \in C_i}|p-m_i|^2 SSE=i=1∑kp∈Ci∑∣p−mi∣2
公式各部分内容:
上图中: k = 2 k=2 k=2
- SSE 图最终的结果,对图松散度的衡量(eg:SSE(左图) < SSE(右图))
- SSE 随着聚类迭代,其值会越来越小,直到最后趋于稳定:
注意:SSE 算法内质心的选取时随机的,因此,在质心选取时,当两个质心初始距离较近时,可能产生不好的结果,因此 SSE 最后的结果是局部内最优解,而不是全局最优解。如下图所示:
如果质心的初始值选择不好,SSE 只会达到一个不怎么好的局部最优解
4.2 “肘”方法(Elbow method)—— K 值确定
- 对于 n n n 个点的数据集,迭代计算 k ∈ [ i , n ] k \in [i, n] k∈[i,n],每次聚类完成后计算每个点到其所属的簇中心的距离的平方和;
- 平方和是会逐渐变小的,直到 k = = n k==n k==n 时平方和为0,因为每个点都是它所在的簇中心本身。
- 在这个平方和变化过程中,会出现一个拐点也即“肘”点,下降率突然变缓时即认为是最佳的 k k k 值。
在决定什么时候停止训练时,肘形判据同样有效,数据通常有更多的噪音,在增加分类无法带来更多回报时,我们停止增加类别。
4.3 轮廓系数法(Silhouette Coefficient,SC)
结合了聚类的凝聚度(Cohesion)和分离度(Separation),用于评估聚类的效果:
目的:内部距离 a a a 最小化,外部距离 b b b 最大化。
S ∈ [ − 1 , 1 ] S \in [-1, 1] S∈[−1,1],其中 S S S 越大越好(接近于1),越小越差(接近于-1)
s ( i ) = b ( i ) − a ( i ) max { a ( i ) , b ( i ) } = { 1 − a ( i ) b ( i ) , a ( i ) < b ( i ) 0 , a ( i ) = b ( i ) b ( i ) a ( i ) − 1 , a ( i ) > b ( i ) \begin{aligned} s(i) & = \frac{b(i) - a(i)}{\max\{a(i), b(i)\}}\\ & = \begin{cases} 1 - \frac{a(i)}{b(i)}, & a(i) < b(i)\\ 0, & a(i) = b(i)\\ \frac{b(i)}{a(i)} - 1, & a(i) > b(i) \end{cases} \end{aligned} s(i)=max{a(i),b(i)}b(i)−a(i)=⎩ ⎨ ⎧1−b(i)a(i),0,a(i)b(i)−1,a(i)<b(i)a(i)=b(i)a(i)>b(i)
计算样本 i i i 到同簇其他样本的平均距离 a ( i ) a(i) a(i), a ( i ) a(i) a(i) 越小样本 i i i 的簇内不相似度越小,说明样本 i i i 越应该被聚类到该簇。
计算样本 i i i 到最近簇 C j C_j Cj 的所有样本的平均距离 b ( j ) b(j) b(j),称样本 i i i 与最近簇 C j C_j Cj 的不相似度,定义为样本 i i i 的簇间不相似度: b ( i ) = min { b ( i ) 1 , b ( i ) 2 , . . . , b ( i ) k } b(i) =\min\{b(i)_1, b(i)_2,..., b(i)_k\} b(i)=min{b(i)1,b(i)2,...,b(i)k}, b ( i ) b(i) b(i) 越大,说明样本 i i i 越不属于其他簇。
求出所有样本的轮廓系数后再求平均值就得到了平均轮廓系数。平均轮廓系数的取值范围为 [ − 1 , 1 ] [-1, 1] [−1,1],系数越大,聚类效果越好。
簇内样本的距离越近,簇间样本距离越远。
案例:
下图是 500 个样本含有 2 个 feature(特征)的数据分布情况,我们对它进行 SC 系数效果衡量:
n_clusters 分别为 2,3,4,5,6 时,SC 系数如下,是介于 [ − 1 , 1 [-1,1 [−1,1 ]之间的度量指标:
- n_clusters = 2 The average silhouette_score is : 0.7049787496083262
- n_clusters = 3 The average silhouette_score is : 0.5882004012129721
- n_clusters = 4 The average silhouette_score is : 0.6505186632729437
- n_clusters = 5 The average silhouette_score is : 0.56376469026194
- n_clusters = 6 The average silhouette_score is : 0.4504666294372765
每次聚类后,每个样本都会得到一个轮廓系数:
- 当它为 1 时,说明这个点与周围簇距离较远,结果非常好;
- 当它为 0,说明这个点可能处在两个簇的边界上;
- 当值为负时,暗示该点可能被误分了。
从平均 SC 系数结果来看, K K K 取 3、5、6 是不好的,那么 2 和 4 呢?
K = 2 K=2 K=2 的情况:
K = 4 K=4 K=4 的情况:
- n_clusters = 2 时,第 0 簇的宽度远宽于第 1 簇;
- n_clusters = 4 时,所聚的簇宽度相差不大,因此选择 K = 4 K=4 K=4 作为最终聚类个数。
4.4 CH 系数(Calinski-Harabasz Index)
CH 系数(Calinski-Harabasz Index)是一种用于评估聚类模型的指标。它通过计算类中各点与类中心的距离平方和来度量类内的紧密度,通过计算各类中心点与数据集中心点距离平方和来度量数据集的分离度,CH 指标由分离度与紧密度的比值得到。从而,CH 越大代表着类自身越紧密,类与类之间越分散,即更优的聚类结果。也就是说,类别内部数据的协方差越小越好,类别之间的协方差越大越好,这样的 Calinski-Harabasz 分数会高。
CH 指数的计算公式为:
s ( k ) = t r ( B k ) t r ( W k ) m − k k − 1 s(k) = \frac{tr(B_k)}{tr(W_k)} \frac{m-k}{k-1} s(k)=tr(Wk)tr(Bk)k−1m−k
其中:
- t r tr tr 为矩阵的
- B k B_k Bk 为类别之间的协方差矩阵
- W k W_k Wk 为类别内部数据的协方差矩阵
- m m m 为训练集样本数
- k k k 为类别数。
迹(trace),定义为主对角线数的和。对于一个矩阵: ( a 11 a 12 . . . a 1 n a 21 a 22 . . . a 2 n . . . . . . . . . . . . a n 1 a n 2 . . . a n n ) \begin{pmatrix} a_{11} & a_{12} & ... & a_{1n}\\ a_{21} & a_{22} & ... & a_{2n}\\ ... & ... & ... & ...\\ a_{n1} & a_{n2} & ... & a_{nn}\\ \end{pmatrix} a11a21...an1a12a22...an2............a1na2n...ann 则它的迹 t r tr tr 的定义为 t r = a 11 + a 22 + . . . + a n n tr = a_{11} + a_{22} + ... + a_{nn} tr=a11+a22+...+ann
使用矩阵的迹进行求解的理解:矩阵的对角线可以表示一个物体的相似性。
在机器学习里,主要为了获取数据的特征值,那么就是说,在任何一个矩阵计算出来之后,都可以简单化,只要获取矩阵的迹,就可以表示这一块数据的最重要的特征了,这样就可以把很多无关紧要的数据删除掉,达到简化数据,提高处理速度。
CH 需要达到的目的:用尽量少的类别聚类尽量多的样本,同时获得较好的聚类效果。
小结:
- SSE【知道】
- 误差平方和的值越小越好
- 肘部法【知道】
- 下降率突然变缓时即认为是最佳的 k k k 值
- SC系数【知道】
- 取值为 [ − 1 , 1 ] [-1,1] [−1,1],其值越大越好
- CH系数【知道】
- 分数 s s s 越高则聚类效果越好
- CH 需要达到的目的:用尽量少的类别聚类尽量多的样本,同时获得较好的聚类效果。
5. 算法优化
学习目标:
- 知道 K-means 算法的优缺点
- 知道 Canopy、K-means++、二分 K-means、K-medoids 的优化原理
- 了解 Kernel K-means、ISODATA、Mini-batch K-means 的优化原理
K-means 算法小结:
- 优点:
- 原理简单(靠近中心点),实现容易
- 聚类效果中上(依赖 K K K 的选择)
- 空间复杂度 O ( N ) O(N) O(N),时间复杂度 O ( I ∗ K ∗ N ) O(I*K*N) O(I∗K∗N)
N N N 为样本点个数, K K K 为中心商个数, I I I 为迭代次数
- 缺点:
- 对离群点,噪声敏感(中心点易偏移)
- 很难发现大小差别很大的簇及进行增量计算
- 结果不一定是全局最优,只能保证局部最优(与 K K K 的个数及初值选取有关)
5.1 Canopy 算法配合初始聚类
Canopy 算法是一种无监督的“粗”聚类算法,它通过设定两个阈值 T 1 T1 T1 和 T 2 T2 T2( T 1 > T 2 T1 > T2 T1>T2)来将数据点分为不同的簇。
Canopy 算法的基本思想是:对于每个数据点,计算它与其他所有数据点的距离:
- 如果距离小于 T 1 T1 T1,则将这两个数据点归为同一个簇;
- 如果距离小于 T 2 T2 T2,则将这两个数据点归为不同的簇。
Canopy 算法的优点是简单易实现,不需要提前确定簇的数目 K。但是 Canopy 算法只能进行粗聚类,聚类结果不够精确。因此,Canopy 算法通常用作其他聚类算法(如 K-means 算法)的预处理步骤,先进行粗聚类,再进行精细聚类。
5.1.1 Canopy 算法配合初始聚类实现流程
Canopy 算法的步骤如下:
- 给定样本列表 L = x 1 , x 2 , … , x m L=x_1,x_2,\dots,x_m L=x1,x2,…,xm 以及初始距离阈值为 T 1 T1 T1、 T 2 T2 T2,且( T 1 > T 2 T1>T2 T1>T2)( T 1 T1 T1、 T 2 T2 T2 可自己定义);
- 从列表 L L L 中任取一点 P P P,计算 P P P 到所有聚簇中心点的距离(如果不存在聚簇中心,那么就把点 P P P 作为一个新的聚簇),并选出与聚类中心最近的距离 D ( P , a j ) D(P,a_j) D(P,aj);
- 如果距离 D D D 小于 T 1 T1 T1,表示该节点属于该聚簇,添加到该聚簇列表中。
- 如果距离 D D D 小于 T 2 T2 T2,表示该节点不仅仅属于该聚簇,还表示和当前聚簇中心点非常近,所以将 P P P 从列表 L L L 中删除。
Canopy 算法可以用来进行“粗”聚类,得到 K 值以及大致的 K 个初始质心,再使用 K-means 进行进一步“细”聚类。这种 Canopy + K-means 的形式聚类算法聚类效果良好。
5.1.2 Canopy 算法的优缺点
优点:
- K-means 对噪声抗干扰较弱,通过 Canopy 对比,将较小的 NumPoint 的 Cluster 直接去掉有利于抗干扰。
- Canopy 选择出来的每个 Canopy 的 centerPoint 作为 K 会更精确。
- 只是针对每个 Canopy 的内做 K-means 聚类,减少相似计算的数量
在 Canopy 算法中,NumPoint 指的是 Canopy 中包含点的数量。而 centerPoint 指的是 Canopy 中心点,即 Canopy 选择出来的每个 Canopy 的中心点。这些中心点可以作为 K-means 算法的初始质心,从而提高 K-means 算法的聚类效果。
缺点:
- 算法中 T 1 T1 T1、 T 2 T2 T2 的确定问题,依旧可能落入局部最优解
- Canopy 算法得到的最终结果的值,聚簇之间是可能存在重叠的,但是不会存在某个对象不属于任何聚簇的情况。
5.2 K-means++ 算法
K-means++ 算法是一种为 K-means 聚类算法选择初始值(或“种子”)的算法。它是 NP-hard K-means 问题的一种近似算法,它是一种避免标准 K-means 算法有时发现的较弱聚类的方法。
K-means++ 算法仅仅只是在初始化簇中心的方式上做了改进,其它地方同 K-means 聚类算法一样。K-means++ 在初始化簇中心时的方法总结成一句话就是:逐个选取 K 个簇中心,且离其它簇中心越远的样本点越有可能被选为下一个簇中心。这样可以最大化避免初始簇中心在同一个簇中的情况,从而提高聚类效果。
在 K-means++ 算法的迭代过程中,每个簇的中心点仍然是通过计算该簇中所有数据点的平均值得到的,这个中心点不一定是数据集中已有的点,而是一个新建的点。
P = D ( x ) 2 ∑ x ∈ X D ( x ) 2 P = \frac{D(x)^2}{\sum_{x\in X}D(x)^2} P=∑x∈XD(x)2D(x)2
其中:
- P P P 表示每个样本点被选为下一个聚类中心的概率
- D ( x ) D(x) D(x) 表示样本点 x x x 与当前已有聚类中心之间的最短距离(距离现有簇中心越远的样本点,越可能被选为下一个簇中心)
- 在 K-means++ 算法中, D ( x ) D(x) D(x) 表示样本点 x x x 与当前已有聚类中心之间的最短距离。具体来说,假设当前已有 m m m 个聚类中心 c 1 , c 2 , … , c m c_1, c_2, \dots, c_m c1,c2,…,cm,则 D ( x ) D(x) D(x) 可以通过以下公式计算得到:
D ( x ) = min i = 1 m dist ( x , c i ) D(x) = \min_{i=1}^m \text{dist}(x, c_i) D(x)=i=1minmdist(x,ci)
其中 dist ( x , c i ) \text{dist}(x, c_i) dist(x,ci) 表示样本点 x x x 与聚类中心 c i c_i ci 之间的距离。距离的计算方式可以根据具体问题选择不同的距离度量方法,例如欧几里得距离、曼哈顿距离等。
为了方便后续计算,我们将 ∑ x ∈ X D ( x ) 2 \sum_{x\in X}D(x)^2 ∑x∈XD(x)2 记为 A A A。
首先我们选择 点2 作为质心,这样我们就可以求出不同点到质心的 P P P。然后我们根据不同点的概率 P P P 选择新的点作为质心。因为K-means++ 目的就是让选择的质心尽可能的分散。
如下图中,如果第一个质心选择在圆心,那么最优可能选择到的下一个点在 P ( A ) P(A) P(A) 这个区域(根据颜色进行划分)。
K-means++ 算法流程如下:
- 从数据集 X \mathcal{X} X 中随机(均匀分布)选取一个样本点作为第一个初始聚类中心 c i c_i ci。
- 接着计算每个样本与当前已有聚类中心之间的最短距离,用 D ( x ) D(x) D(x) 表示;然后计算每个样本点被选为下一个聚类中心的概率 P ( x ) P(x) P(x) ,最后选择最大概率值所对应的样本点作为下一个簇中心。
- 重复第 ② 步,直到选择出 K 个聚类中心。
- 最后再使用标准 K-means 算法进行聚类。
标准 K-means 算法的流程如下:
- 将每个样本点分配到离它最近的聚类中心所在的簇中。
- 计算每个簇的均值,并将其作为新的聚类中心。
- 重复第①、②步,直到聚类中心不再变化或达到最大迭代次数。
K-means++ 算法通过改进初始聚类中心的选择方式,可以有效避免标准 K-means 算法有时发现的较弱聚类,从而提高聚类效果。
5.3 二分 K-means 算法
二分 K-means 算法是一种基于 K-means 算法改进的算法。它的主要思想是先从一个总簇开始,不断通过二分裂,直到分裂成 K 个簇为止。
二分 K-means 算法流程如下:
- 将所有点看成一个簇;
- 对每个簇,进行如下操作:
- 计算总误差(SSE);
- 在给定的簇上进行 K-means 聚类(K = 2);
- 计算将该簇一分为二之后的总误差(SSE);
- 选择使得误差 SSE 最小的那个簇进行划分操作(也就是对误差较大的簇进行划分);
- 重复第 ②、③ 步操作,直到达到用户指定的簇数目为止。
二分 K-means 算法可以有效地解决 K-means 算法收敛于局部最小值问题,提高聚类效果。
二分 K-means 隐含的一个原则:
因为聚类的误差平方和 SSE 能够衡量聚类性能,该值越小表示数据点越接近于他们的质心,聚类效果就越好。所以需要对误差平方和 SSE 最大的簇进行再一次划分,因为误差平方和越大,表示该簇聚类效果越不好,越有可能是多个簇被当成了一个簇,所以我们首先需要对这个簇进行划分。
二分 K-means 算法可以加速 K-means 算法的执行速度,因为它的相似度计算少了并且不受初始化问题的影响。二分 K-means 算法不存在随机点的选取,且每一步都保证了误差最小。
5.4 K-medoids(K-中心聚类算法)
K-medoids 和 K-means 是有区别的,不一样的地方在于中心点的选取。
- K-means 中,将中心点取为当前 Cluster(簇)中所有数据点的平均值,所以对异常点很敏感。
- K-medoids 中,将从当前 Cluster(簇)中选取到其他所有(当前 Cluster 中的)点的距离之和最小的点作为中心点。
medoids:
/ˈmɛdɔɪdz/
中心点
Q:意思就是 K-means 算法通过计算该簇中所有数据点的平均值得到中心点,这个中心点是新建的,而 K-medoids 是选取当前簇中已有的点,对吗?
A:是的,这样的理解是正确的。
- 在 K-means 算法中,每个簇的中心点是通过计算该簇中所有数据点的平均值得到的。这个中心点不一定是数据集中已有的点,而是一个新建的点。
- 而在 K-medoids 算法中,每个簇的中心点是从该簇中选取到其他所有(当前簇中的)点的距离之和最小的点作为中心点。这个中心点一定是数据集中已有的点。
K-medoids 算法(也称为 K-中心聚类算法)是一种经典的划分聚类技术,它将 n n n 个对象的数据集划分为 K K K 个簇,其中 K K K 值(即簇的数量)在算法执行之前已知(这意味着程序员必须在执行 K-medoids 算法之前指定 K K K 值)。
与 K-means 算法不同,K-medoids 算法选择实际数据点作为中心(medoids 或 exemplars),从而比 K-means 允许更好地解释聚类中心。此外,K-medoids 可以与任意不相似度量一起使用,而 K-means 通常需要欧几里得距离才能获得有效解决方案。因为 K-medoids 最小化成对不相似度之和而不是平方欧几里得距离之和,所以它比 K-means 更能抵抗噪声和异常值。
簇的 medoid(中心点)定义为簇中与所有对象的平均不相似度最小的对象,即它是簇中最中心位置的点。
算法流程:
- 随机选择 K 个对象作为初始 medoids(中心点)。
- 将每个剩余对象分配到离它最近的 medoid(中心点)所代表的簇中。
- 对于每个簇,计算每个成员对象对应的准则函数值,并选择准则函数值最小时对应的对象作为新的 medoid(中心点)。
- 重复第 ②、③ 步操作,直到所有 medoid(中心点)对象不再发生变化或达到最大迭代次数。
其中,准则函数定义为一类中某个成员对象与其他成员对象之间距离之和。
【优点】相比 K-means 算法而言,K-medoids 算法对噪声鲁棒性好。
举例:当一个 Cluster 样本点只有少数几个,如 ( 1 , 1 ) , ( 1 , 2 ) , ( 2 , 1 ) , ( 1000 , 1000 ) (1, 1), (1, 2), (2, 1), (1000, 1000) (1,1),(1,2),(2,1),(1000,1000)。其中 ( 1000 , 1000 ) (1000, 1000) (1000,1000) 是噪声。
如果按照 K-means,质心大致会处在 ( 1 , 1 ) , ( 1000 , 1000 ) (1, 1), (1000, 1000) (1,1),(1000,1000) 中间。这显然不是我们想要的。
这时 K-medoids 就可以避免这种情况,他会在 ( 1 , 1 ) , ( 1 , 2 ) , ( 2 , 1 ) , ( 1000 , 1000 ) (1, 1), (1, 2), (2, 1), (1000, 1000) (1,1),(1,2),(2,1),(1000,1000) 中选出一个样本点(这个样本点一定是这四个点中的一个,不能是新建的)使 Cluster 的绝对误差最小,计算可知一定会在前三个点中选取。
【缺点】K-medoids 只能对小样本起作用:如果样本大,那么速度就太慢了。而且当样本多的时候,少数几个噪音对 K-means 的质心影响也没有想象中的那么重,所以 K-means 的应用明显比 K-medoids 多。
简单来说:
- 对于小数据集而言,可以使用 K-medoids,效果一般比 K-means 要好
- 但对于大数据集而言,还是要用 K-means 算法
5.5 Kernel K-means 算法(了解)
Kernel K-means 算法是一种基于核方法的 K-means 算法,它可以处理非线性可分的数据。它通过将数据映射到高维空间,使得原本在低维空间中线性不可分的数据在高维空间中变得线性可分,从而提高聚类效果。
Kernel K-means 算法的流程与标准 K-means 算法类似,但在计算距离时使用了核函数来计算样本点之间的相似度,这样可以有效地解决标准 K-means 算法无法处理非线性可分数据的问题。
Kernel K-means 实际上就是将每个样本进行一个投射,投射到高维空间的处理,然后再将处理后的数据使用普通的 K-means 算法思想进行聚类。
5.6 ISODATA 算法(了解)
ISODATA 算法(Iterative Self-Organizing Data Analysis Techniques Algorithm,迭代自组织数据分析技术算法)是一种改进的 K-means 算法。它在聚类过程中引入了对类别的评判标准,根据标准自动对某些类别进行合并或分裂,在一定程度上突破了对于给定类别数的限制。
该算法能够在聚类过程中根据各个类所包含样本的实际情况动态调整聚类中心的数目。如果某个类中样本分散程度较大(通过方差进行衡量)并且样本数量较大,则对其进行分裂操作;如果某两个类别靠得比较近(通过聚类中心的距离衡量),则对它们进行合并操作。
ISODATA 算法是一种重复自组织数据分析技术,计算数据空间中均匀分布的类均值,然后用最小距离技术将剩余像元进行迭代聚合,每次迭代都重新计算均值,且根据所得的新均值,对像元再进行分类。
特点:
- 类别数目随着聚类过程而变化
- 对类别数会进行合并、分裂:
- 合并:当聚类结果某一类中样本数太少,或两个类间的距离太近时
- 分裂:当聚类结果中某一类的类内方差太大,将该类进行分裂
5.7 Mini Batch K-means 算法(了解)
Mini Batch K-means 算法是 K-means 算法的一种优化方案,它适合大数据的聚类算法。该算法采用小批量的数据子集来减少计算时间,同时仍然试图优化目标函数。这里所谓的小批量是指每次训练算法时所随机抽取的数据子集,采用这些随机产生的子集进行训练算法,大大减小了计算时间。与其他算法相比:
- Mini Batch K-means 算法减少了 K-means 的收敛时间
- Mini Batch K-means 算法 产生的结果一般只略差于标准 K-means 算法。
通常当样本量大于 1万 做聚类时,就需要考虑选用 Mini Batch K-means 算法。
该算法的迭代步骤有两步:
- 从数据集中随机抽取一些数据形成小批量,把它们分配给最近的质心
- 更新质心
与 K-means 相比,数据的更新在每一个小的样本集上。对于每一个小批量,通过计算平均值得到更新质心,并把小批量里的数据分配给该质心。随着迭代次数的增加,这些质心的变化是逐渐减小的,直到质心稳定或者达到指定的迭代次数,停止计算。
小结:
- K-means 算法优缺点总结【知道】
- 优点:
- 原理简单(靠近中心点),实现容易
- 聚类效果中上(依赖 K 的选择)
- 空间复杂度 O ( N ) O(N) O(N),时间复杂度 O ( I × K × N ) O(I \times K \times N) O(I×K×N)
- 缺点:
- 对离群点,噪声敏感(中心点易偏移)
- 很难发现大小差别很大的簇及进行增量计算
- 结果不一定是全局最优,只能保证局部最优(与 K 的个数及初值选取有关)
- 优点:
- 优化方法【知道】
5.8 几种聚类方法对比
优化方法 | 思路 | 提前确定 K 值 | 迭代时使用已有点还是新建点 |
---|---|---|---|
K-means | 基于距离的聚类算法 | 是 | 新建点 |
Canopy | Canopy 粗聚类,通过设定两个阈值,将数据点分为不同的簇,不需要提前确定 K 值 | 否,不需要提前确定 K 值 | 已有点 |
Canopy + K-means | Canopy 粗聚类配合 K-means,先进行 Canopy 粗聚类,再进行 K-means 聚类 | 是 | 新建点 |
K-means++ | 距离越远越容易成为新的质心,改进了初始中心点的选择方法 | 是 | 新建点 |
二分 K-means | 拆除 SSE 最大的簇,每次将一个簇分成两个簇,直到达到预定的簇数目为止 | 是 | 新建点 |
K-medoids | 和 K-means 选取中心点的方式不同,选取当前簇中已有的点作为中心点,对异常点不太敏感 | 是 | 已有点 |
Kernel K-means | 映射到高维空间,通过核函数将数据映射到高维空间,再进行聚类操作 | 是 | 新建点 |
ISODATA | 动态聚类,可以更改 K 值的大小,根据一定规则动态调整簇的数目和簇的形态 | 否,可以动态调整 K 值的大小 | 新建点 |
Mini-batch K-means | 大数据集分批聚类,每次迭代只使用部分数据进行计算,减少计算量和时间开销 | 是 | 新建点 |
6. 特征工程 —— 特征降维
学习目标:
- 了解降维的定义
- 知道通过低方差过滤实现降维过程
- 知道相关系数实现降维的过程
- 知道主成分分析法实现过程
6.1 降维
6.1.1 定义
在机器学习和统计学领域,降维是指在某些限定条件下,降低随机变量个数,得到一组“不相关”主变量的过程。降维可进一步细分为变量选择和特征提取两大方法。
简单来说,降维就是采用某种映射方法,将原高维空间中的数据点映射到低维度的空间中。这样做的目的是为了减少冗余信息和噪声信息造成的误差,提高应用中的精度。常见的数据降维方法有:PCA、LDA、MDS、ISOMAP、SNE、T-SNE、AutoEncoder等。
简而言之,降维是指在某些限定条件下,降低随机变量(特征)个数,得到一组“不相关”主变量的过程。
关键在于:降低相关变量的个数
Q:比如对于一个数据集,有 ABCDEFG 这些特征,假如 BCD 这三个特征的相关性很高,那么是不是可以从 BCD 中选择一个特征(这里选择 C)代替其他两个相似的特征(B 和 D),即数据集特征从原来的 ABCDEFG 变为了 ACEFG。这样的理解正确吗?
A:这样的理解是正确的。在这个例子中,如果 BCD 三个特征的相关性很高,那么它们可能包含了大量重复的信息。在这种情况下,我们可以使用变量选择方法,从 BCD 中选择一个特征(例如 C),并删除其他两个特征(B 和 D),以减少数据集中的冗余信息。这样,数据集中的特征就从原来的 ABCDEFG 变为了 ACEFG。
当然,这只是降维的一种方法。另一种常用的降维方法是特征提取,它通过对原始特征进行某种变换,来生成新的、更少的特征。例如,在您提供的例子中,我们可以使用 PCA 等方法,将 BCD 三个特征转换为一个新的特征 H,然后用 H 代替原来的 BCD 三个特征。这样,数据集中的特征就从原来的 ABCDEFG 变为了 AEFGH。
总之,降维旨在减少数据集中的冗余信息和噪声信息,以提高模型在应用中的精度。
相关特征(Correlated Features):
- 相对湿度与降雨量之间的相关
- 等等
正是因为在进行训练的时候,我们都是使用特征进行学习。如果特征本身存在问题或者特征之间相关性较强,对于算法学习预测会影响较大。
6.1.2 降维的两种方式
- 特征选择(Feature Selection,FS)是指从原始特征中选择出一部分最有用的特征,以提高模型的性能和准确性。
- 主成分分析(Principal Component Analysis,PCA)是一种常用的特征提取方法,它通过线性变换将原始数据映射到新的坐标系中,使得数据在新坐标系中的方差最大化,从而实现数据降维和特征提取。
6.2 特征选择(Feature Selection)
6.2.1 定义
数据中包含冗余或无关变量(或称特征、属性、指标等),旨在从原有特征中找出主要特征。
6.2.2 方法
- Filter(过滤式):主要探究特征本身特点、特征与特征和目标值之间关联。
- 方差选择法(Variance Threshold):认为方差越大对于标签的可区分性越高;否则,即低方差的特征认为其具有较低的区分度。
- 相关系数(Correlation Coefficient):是一种用来衡量两个变量之间线性相关程度的统计量。常用的相关系数包括皮尔森相关系数(Pearson Correlation Coefficient)和斯皮尔曼相关系数(Spearman Correlation Coefficient)等。
- Embedded(嵌入式):在模型训练过程中自动选择特征(特征与目标值之间的关联)
- 决策树(Decision Tree):决策树算法在构建树的过程中,会计算每个特征的信息增益(Information Gain),并选择信息增益最大的特征进行分裂。因此,我们可以根据特征的信息增益来判断特征的重要性。
- 正则化(Regularization):正则化方法通过在目标函数中添加正则项来实现特征选择。例如,在线性回归模型中,我们可以使用 L1 正则化(Lasso)或 L2 正则化(Ridge)来实现特征选择。L1 正则化会使得部分特征的系数变为 0,从而实现特征选择;L2 正则化会使得特征的系数变小,但不为 0,因此可以用来判断特征的重要性。
- 深度学习(Deep Learning):在深度学习模型中,我们可以使用类似于决策树和正则化的方法来实现特征选择。例如,我们可以计算每个输入神经元对输出神经元的贡献度来判断特征的重要性;或者在目标函数中添加正则项来实现特征选择。
6.2.3 方法一:方差选择法(Variance Threshold)—— 低方差特征过滤
- 特征方差小:某个特征大多样本的值比较相近
- 特征方差大:某个特征很多样本的值都有差别
方差是用来衡量一组数据离散程度的度量。它表示每一个变量(观察值)与总体均数之间的差异。方差越大,说明数据的波动越大;方差越小,说明数据的波动越小。
6.2.3.1 API
sklearn.feature_selection.VarianceThreshold(threshold=0.0)
- 作用:
sklearn.feature_selection.VarianceThreshold
是一个特征选择器,它可以移除所有低方差特征。这个特征选择算法只关注特征(X
),而不关注期望的输出(y
),因此可以用于无监督学习。 - 参数:
threshold
:float, 默认值为 0。训练集方差低于此阈值的特征将被移除。默认情况下,保留所有非零方差的特征,即移除所有样本中具有相同值的特征(但凡有一点不相同就保留)。
- 属性:
variances_
:数组,形状为(n_features,)
。各个特征的方差。n_features_in_
:int。fit 期间看到的特征数。feature_names_in_
:ndarray,形状为(n_features_in_,)
。fit 期间看到的特征名称。仅当X
具有全部为字符串的特征名称时定义。
- 方法:
fit(X, y=None)
:从X
中学习经验方差。fit_transform(X, y=None, **fit_params)
:拟合数据,然后转换它。get_feature_names_out(input_features=None)
:根据所选特征掩码特征名称。get_params(deep=True)
:获取此估计器的参数。get_support(indices=False)
:获取所选特征的掩码或整数索引。inverse_transform(X)
:反转转换操作。set_params(**params)
:设置此估计器的参数。transform(X)
:将X
减少到所选特征。
6.2.3.2 数据计算
我们对某些股票的指标特征之间进行一个筛选,除去 'index'
,'date'
,'return'
列不考虑(这些类型不匹配,也不是所需要指标)。
一共有如下这些特征:
'pe_ratio', 'pb_ratio', 'market_cap', 'return_on_asset_net_profit', 'du_return_on_equity', 'ev', 'earnings_per_share', 'revenue', 'total_expense'
- 分析:
- 初始化
VarianceThreshold
,指定阀值方差 - 调用
fit_transform
方法
- 初始化
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.feature_selection import VarianceThreshold
data = pd.read_csv("./data/factor_returns.csv")
print("删除低方差特征前的形状为:", data.shape)
# 1. 实例化一个转换器类
transfer = VarianceThreshold(threshold=1)
# 2. 调用fit_transform方法
data = transfer.fit_transform(data.iloc[:, 1:10])
print("删除低方差特征后的形状为:", data.shape)
print("删除低方差特征的结果为:\r\n", data)
删除低方差特征前的形状为: (2318, 12)
删除低方差特征后的形状为: (2318, 8)
删除低方差特征的结果为:
[[ 5.95720000e+00 1.18180000e+00 8.52525509e+10 ... 1.21144486e+12
2.07014010e+10 1.08825400e+10]
[ 7.02890000e+00 1.58800000e+00 8.41133582e+10 ... 3.00252062e+11
2.93083692e+10 2.37834769e+10]
[-2.62746100e+02 7.00030000e+00 5.17045520e+08 ... 7.70517753e+08
1.16798290e+07 1.20300800e+07]
...
[ 3.95523000e+01 4.00520000e+00 1.70243430e+10 ... 2.42081699e+10
1.78908166e+10 1.74929478e+10]
[ 5.25408000e+01 2.46460000e+00 3.28790988e+10 ... 3.88380258e+10
6.46539204e+09 6.00900728e+09]
[ 1.42203000e+01 1.41030000e+00 5.91108572e+10 ... 2.02066110e+11
4.50987171e+10 4.13284212e+10]]
6.2.4 方法二:相关系数(Correlation Coefficient)
主要实现方式:
- 皮尔森相关系数(Pearson Correlation Coefficient)
- 斯皮尔曼相关系数(Spearman’s rank correlation coefficient,Rank IC)
6.2.4.1 皮尔森相关系数(Pearson Correlation Coefficient)
一、作用
皮尔森相关系数是一种统计指标,用于反映两个变量之间相关关系的密切程度。它的取值范围为 [ − 1 , 1 ] [-1,1] [−1,1]:
- 当系数接近 1 时,说明两个变量呈正相关关系,即一个变量增加,另一个也随之增加;
- 当系数接近 -1 时,说明两个变量呈负相关关系,即一个变量增加,另一个会减少;
- 当系数接近 0 时,说明两个变量之间没有线性关系。
二、公式计算案例(了解,不用记忆)
r = n ∑ x y − ∑ x ∑ y n ∑ x 2 − ( ∑ x ) 2 n ∑ y 2 − ( ∑ y ) 2 r = \frac{n\sum{xy} - \sum{x}\sum{y}}{\sqrt{n\sum{x^2} -(\sum{x})^2}\sqrt{n\sum{y^2} - (\sum{y})^2}} r=n∑x2−(∑x)2n∑y2−(∑y)2n∑xy−∑x∑y
其中:
- r r r:皮尔森相关系数,用于衡量两个变量之间的线性关系。
- n n n:样本数量。
- x x x 和 y y y:两个变量的值。
- Σ x y Σxy Σxy:所有样本中 x x x 和 y y y 的乘积之和。
- Σ x Σx Σx 和 Σ y Σy Σy:所有样本中 x x x 和 y y y 的总和。
- Σ x 2 Σx^2 Σx2 和 Σ y 2 Σy^2 Σy2:所有样本中 x 2 x^2 x2 和 y 2 y^2 y2 的总和。
举例:比如说我们计算年广告费投入与月均销售额。
那么之间的皮尔森相关系数怎么计算?
最终计算:
10 × 16679.09 − 346.2 × 422.5 10 × 14304.52 − 346. 2 2 10 × 19687.81 − 422. 5 2 = 0.9942 \frac{10\times 16679.09 - 346.2 \times 422.5}{\sqrt{10 \times 14304.52 - 346.2^2} \sqrt{10 \times 19687.81 - 422.5^2}} = 0.9942 10×14304.52−346.2210×19687.81−422.5210×16679.09−346.2×422.5=0.9942
所以我们最终得出结论是:广告投入费与月平均销售额之间有高度的正相关关系。
皮尔森相关系数的取值范围为 [ − 1 , 1 ] [-1,1] [−1,1]
三、特点
相关系数的值介于 [ − 1 , 1 ] [-1, 1] [−1,1] 之间,即 − 1 ≤ r ≤ 1 -1 \le r \le 1 −1≤r≤1。其性质如下:
- 当 r > 0 r > 0 r>0 时,表示两变量正相关; r < 0 r < 0 r<0 时,两变量为负相关
- 当 ∣ r ∣ = 1 |r| = 1 ∣r∣=1 时,表示两变量为完全相关,当 r = 0 r = 0 r=0时,表示两变量间无相关关系
- 当
0
<
∣
r
∣
<
1
0<|r|<1
0<∣r∣<1 时,表示两变量存在一定程度的相关。且
∣
r
∣
|r|
∣r∣ 越接近1,两变量间线性关系越密切;
∣
r
∣
|r|
∣r∣ 越接近于0,表示两变量的线性相关越弱。一般可按三级划分:
- ∣ r ∣ < 0.4 |r| < 0.4 ∣r∣<0.4 为低度相关
- 0.4 ≤ ∣ r ∣ < 0.7 0.4 \le |r| < 0.7 0.4≤∣r∣<0.7 为显著性相关
- 0.7 ≤ ∣ r ∣ < 1 0.7 \le |r| < 1 0.7≤∣r∣<1 为高度线性相关
四、皮尔森相关系 API
from scipy.stats import pearsonr
- 作用:
scipy.stats.pearsonr
是一个用于计算皮尔森相关系数的函数,它可以衡量两个变量之间的线性关系。它还提供了用于检验非相关性的 p 值。 - 参数:
x
:(N,) array_like,输入数组。y
:(N,) array_like,输入数组。
- 返回值:
r
:float,皮尔森相关系数,取值范围为 [ − 1 , 1 ] [-1, 1] [−1,1]。p-value
:float,双尾 p 值。
五、案例
from scipy.stats import pearsonr
x1 = [12.5, 15.3, 23.2, 26.4, 33.5, 34.4, 39.4, 45.2, 55.4, 60.9]
x2 = [21.2, 23.9, 32.9, 34.1, 42.5, 43.2, 49.0, 52.8, 59.4, 63.5]
r, p_value = pearsonr(x1, x2)
print("r:", r)
print("p-value:", p_value)
r: 0.9941983762371884
p-value: 4.922089955456964e-09
根据结果可知,x1
和 x2
之间的皮尔森相关系数为 0.9941983762371884
,这说明两个变量之间存在着非常强的正相关关系。也就是说,当 x1
增加时,x2
也会随之增加。
双尾 p 值为 4.922089955456964e-09
,这个值非常接近于 0。通常情况下,如果 p 值小于显著性水平(例如 0.05),则我们可以拒绝原假设(两个变量之间没有相关性),并认为两个变量之间存在着显著的相关性。在这种情况下,p 值非常小,因此我们可以认为 x1
和 x2
之间存在着显著的相关性。
6.2.4.2 斯皮尔曼相关系数(Spearman’s rank correlation coefficient,Rank IC)
一、作用:
斯皮尔曼等级相关系数(Spearman’s rank correlation coefficient,简称等级相关系数或秩相关系数)是一种衡量两个变量相关性的非参数指标。它利用单调函数评价两个统计变量的相关性。当数据中没有重复值,且当两变量完全单调相关时,斯皮尔曼相关系数为+1或−1。
- 正的斯皮尔曼相关系数反映两个变量 X 和 Y 之间单调递增的趋势。
- 负的斯皮尔曼相关系数反映两个变量 X 和 Y 之间单调递减的趋势。
二、公式(了解,不用记忆):
R a n k I C = 1 − 6 ∑ d i 2 n ( n 2 = 1 ) \mathrm{RankIC} = 1 - \frac{6\sum{d_i^2}}{n(n^2 = 1)} RankIC=1−n(n2=1)6∑di2
其中:
RankIC
:斯皮尔曼等级相关系数,用于衡量两个变量之间的单调关系。d_i
:第i
个观测值的秩差,即两个变量的秩次之差。n
:样本数量。
Q:秩差是什么?
A:秩差(Rank Difference)是指在斯皮尔曼等级相关系数(Spearman’s rank correlation coefficient)的计算中,每个观测值的秩次之差。例如,如果您有两个变量 x
和 y
,并且对每个变量的值进行排序,那么每个观测值的秩差就是它在 x
中的秩次与它在 y
中的秩次之差。秩差用于计算斯皮尔曼等级相关系数,用于衡量两个变量之间的单调关系。
举个例子,假设有两组数据:
x = [1, 2, 3, 4]
y = [2, 3, 1, 4]
首先,我们需要对每组数据进行排序,并为每个数据分配一个秩次:
x_sorted = [1, 2, 3, 4]
x_ranks = [1, 2, 3, 4]
y_sorted = [1, 2, 3, 4]
y_ranks = [3, 1, 2, 4]
然后,我们可以计算每个观测值的秩差:
rank_differences = [2, -1, -1, 0]
最后,我们可以使用这些秩差来计算斯皮尔曼等级相关系数。
举例:
三、特点:
- 斯皮尔曼相关系数表明 X(自变量)和 Y(因变量)的相关方向。如果当 X 增加时,Y 趋向于增加,斯皮尔曼相关系数则为正
- 与之前的皮尔森相关系数大小性质一样,取值仍然为 [ − 1 , 1 ] [-1,1] [−1,1] 之间
斯皮尔曼相关系数比皮尔森相关系数应用更加广泛
四、API:
from scipy.stats import spearmanr
- 作用:
scipy.stats.spearmanr
是一个用于计算斯皮尔曼等级相关系数的函数,它可以衡量两个变量之间的单调关系。它还提供了用于检验非相关性的 p 值。 - 参数:
a
:(N,) array_like,输入数组。b
:(N,) array_like,输入数组,可选。axis
:int 或 None,可选。如果 axis=0(默认),则每列表示一个变量,行中包含观测值。如果 axis=1,则关系转置:每行表示一个变量,而列中包含观测值。如果 axis=None,则两个数组都将被展开。nan_policy
:{‘propagate’, ‘raise’, ‘omit’},可选。定义当输入包含 nan 时如何处理。可用的选项有(默认为 ‘propagate’):‘propagate’:返回 nan;‘raise’:抛出错误;‘omit’:忽略 nan 值进行计算。alternative
:{‘two-sided’, ‘less’, ‘greater’},可选。定义备择假设。默认为 ‘two-sided’。可用的选项有:‘two-sided’:相关性不为零;‘less’:相关性为负(小于零);‘greater’:相关性为正(大于零)。
- 返回值:
correlation
:float 或 ndarray (2-D square)。斯皮尔曼相关矩阵或相关系数(如果只给出 2 个变量作为参数)。相关矩阵是正方形的,长度等于 a 和 b 组合在一起的总变量数(列或行)。pvalue
:float 或 ndarray (2-D square)。双尾 p 值。
五、案例:
from scipy.stats import spearmanr
x1 = [12.5, 15.3, 23.2, 26.4, 33.5, 34.4, 39.4, 45.2, 55.4, 60.9]
x2 = [21.2, 23.9, 32.9, 34.1, 42.5, 43.2, 49.0, 52.8, 59.4, 63.5]
r, p_value = spearmanr(x1, x2)
print("r:", r)
print("p-value:", p_value)
r: 0.9999999999999999
p-value: 6.646897422032013e-64
根据结果可知,x1
和 x2
之间的斯皮尔曼等级相关系数为 0.9999999999999999
,这说明两个变量之间存在着非常强的正相关关系。也就是说,当 x1
增加时,x2
也会随之增加。
双尾 p 值为 6.646897422032013e-64
,这个值非常接近于 0。通常情况下,如果 p 值小于显著性水平(例如 0.05),则我们可以拒绝原假设(两个变量之间没有相关性),并认为两个变量之间存在着显著的相关性。在这种情况下,p 值非常小,因此我们可以认为 x1
和 x2
之间存在着显著的相关性。
总结:皮尔森相关系数(Pearson correlation coefficient)和斯皮尔曼相关系数(Spearman’s rank correlation coefficient)都是用来衡量两个变量之间相关性的统计指标。它们都在 [ − 1 , 1 ] [-1,1] [−1,1] 的区间内取值,且具有相似的解释:
- 当系数接近 1 时,说明两个变量呈正相关关系,即一个变量增加,另一个也随之增加;
- 当系数接近 -1 时,说明两个变量呈负相关关系,即一个变量增加,另一个会减少;
- 当系数接近 0 时,说明两个变量之间没有线性关系。
不过,皮尔森相关系数衡量的是两个变量之间的线性相关性,而斯皮尔曼相关系数衡量的是两个变量之间的单调相关性。因此,在处理非线性数据时,斯皮尔曼相关系数可能更为合适。
6.3 主成分分析(Principal Component Analysis,PCA)
6.3.1 什么是主成分分析(PCA)
主成分分析(Principal Component Analysis,PCA)是一种常用的数据降维技术。它通过线性变换将一组可能相关的变量转换为一组线性不相关的变量,这些不相关的变量称为主成分。主成分分析可以通过保留低维主成分,忽略高维主成分来减少数据集的维数,同时保留数据集中对方差贡献最大的特征。
定义:高维数据转化为低维数据的过程,在此过程中可能会舍弃原有数据、创造新的变量。
作用:数据维数压缩,尽可能降低原数据的维数(复杂度),损失少量信息。
应用:回归分析或者聚类分析当中。
对于信息一词,在决策树中会进行介绍
那么如何更好的理解这个过程呢?我们来看一张图。
要想看到一个茶壶的全貌,我们可以很明显的看到,第四张图是最容易的正式茶壶的全貌的。虽然看不到所有的细节,但不影响我们主要因素的获取。
6.3.2 API
sklearn.decomposition.PCA(n_components=None)
-
作用:
sklearn.decomposition.PCA
是 scikit-learn 库中实现主成分分析(PCA)的类。它可以通过线性变换将一组可能相关的变量转换为一组线性不相关的变量,这些不相关的变量称为主成分。PCA 可以通过保留低维主成分,忽略高维主成分来减少数据集的维数,同时保留数据集中对方差贡献最大的特征。 -
参数:
n_components
:int, float, None 或 str,默认值为 None。要保留的成分数。- 小数:表示保留百分之多少的信息
- 整数:减少到多少特征
- 如果
n_components
未设置,则保留所有成分:n_components == min(n_samples, n_features)
。 - 如果
n_components == 'mle'
并且svd_solver == 'full'
,则使用 Minka 的 MLE 来猜测维数。使用n_components == 'mle'
将解释svd_solver == 'auto'
为svd_solver == 'full'
。 - 如果
0 < n_components < 1
并且svd_solver == 'full'
,则选择使需要解释的方差量大于n_components
指定的百分比的成分数。 - 如果
svd_solver == 'arpack'
,则组件数必须严格小于n_features
和n_samples
的最小值。因此,None 情况下的结果为:n_components == min(n_samples, n_features) - 1
。
copy
:bool,默认值为 True。如果为 False,则传递给 fit 的数据将被覆盖,并且运行 fit(X).transform(X) 将无法获得预期结果,而应使用 fit_transform(X)。whiten
:bool,默认值为 False。当为 True(默认为 False)时,components_ 向量乘以 n_samples 的平方根,然后除以奇异值,以确保输出不相关且具有单位逐分量方差。白化将从转换信号中删除一些信息(组件的相对方差比例),但有时可以通过使其数据遵守硬连线假设来提高下游估计器的预测精度。svd_solver
:{‘auto’, ‘full’, ‘arpack’, ‘randomized’},默认值为 ‘auto’。- 如果 auto:根据 X.shape 和 n_components 选择求解器的默认策略:
- 如果输入数据大于 500x500 并且要提取的组件数低于数据最小维度的 80%,则启用更高效的“随机化”方法。
- 否则计算精确全 SVD 并在之后可选地截断。
- 如果 full:运行精确全 SVD 调用标准 LAPACK 求解器通过 scipy.linalg.svd 并通过后处理选择组件。
- 如果 auto:根据 X.shape 和 n_components 选择求解器的默认策略:
tol
:float,默认值为 0.0。svd_solver == ‘arpack’ 的收敛参数。iterated_power
:int 或 ‘auto’,默认值为 ‘auto’。svd_solver == ‘randomized’ 的幂迭代次数。random_state
:int, RandomState 实例或 None,默认值为 None。控制随机数生成器的种子;在选择随机化 svd 求解器时传递给 arpack 或 random_state。
-
方法:
fit(X[, y])
:拟合模型。fit_transform(X[, y])
:拟合模型并执行转换。get_covariance()
:计算数据协方差。get_params([deep])
:获取此估计器的参数。get_precision()
:计算精度矩阵。inverse_transform(X)
:将数据转换回原始空间。score(X[, y])
:返回平均对数似然。score_samples(X)
:返回样本对数似然数组。set_params(**params)
:设置此估计器的参数。transform(X)
:将数据降维。
6.3.3 数据计算
先拿个简单的数据计算一下:
from sklearn.decomposition import PCA
data = [[2, 8, 4, 5], [6, 3, 0, 8], [5, 4, 9, 1]]
print(f"降维前数据形状为:{np.array(data).shape}")
# 1. 实例化PCA,小数:保留多少信息
transfer = PCA(n_components=0.9)
# 2. 调用fit_transform方法
data_PCA = transfer.fit_transform(data)
print(f"降维后数据形状为:{data_PCA.shape}")
print(f"保留90%的信息后,降维的结果为:\r\n{data_PCA}")
降维前数据形状为:(3, 4)
降维后数据形状为:(3, 2)
保留90%的信息后,降维的结果为:
[[ 1.28620952e-15 3.82970843e+00]
[ 5.74456265e+00 -1.91485422e+00]
[-5.74456265e+00 -1.91485422e+00]]
from sklearn.decomposition import PCA
data = [[2, 8, 4, 5], [6, 3, 0, 8], [5, 4, 9, 1]]
print(f"降维前数据形状为:{np.array(data).shape}")
# 1. 实例化PCA,小数:保留多少信息
transfer = PCA(n_components=2)
# 2. 调用fit_transform方法
data_PCA = transfer.fit_transform(data)
print(f"降维后数据形状为:{data_PCA.shape}")
print(f"降维到2维后的结果为:\r\n{data_PCA}")
降维前数据形状为:(3, 4)
降维后数据形状为:(3, 2)
降维到2维后的结果为:
[[ 1.28620952e-15 3.82970843e+00]
[ 5.74456265e+00 -1.91485422e+00]
[-5.74456265e+00 -1.91485422e+00]]
- 降维的定义【了解】
- 就是改变特征值,选择哪列保留,哪列删除。
- 目标是得到一组“不相关”的主变量
- 降维的两种方式【了解】
- 特征选择
- 主成分分析(可以理解一种特征提取的方式)
- 特征选择【知道】
- 定义:剔除数据中的冗余变量
- 方法:
- Filter(过滤式):主要探究特征本身特点、特征与特征和目标值之间关联
- 方差选择法:低方差特征过滤(低方差意味着区别度低)
- 相关系数
- Embedded(嵌入式):算法自动选择特征(特征与目标值之间的关联)
- 决策树:信息熵、信息增益
- 正则化:L1、L2
- Filter(过滤式):主要探究特征本身特点、特征与特征和目标值之间关联
- 低方差特征过滤【知道】
- 把方差比较小的某一列进行剔除
- API:
sklearn.feature_selection.VarianceThreshold(threshold=0.0)
- 删除所有低方差特征
- 注意:参数
threshold
一定要进行值的指定
- 相关系数【掌握】
- 主要实现方式:
- 皮尔森相关系数
- 斯皮尔曼相关系数
- 皮尔森相关系数
- 通过具体值的大小进行计算
- 相对复杂
- API:
from scipy.stats import pearsonr
- 返回值越接近1,相关性越强
- 返回值越接近0,相关性越弱
- 斯皮尔曼相关系数
- 通过等级差进行计算
- 比上一个(皮尔森相关系数)简单
- API:
from scipy.tats import spearmanr
- 返回值越接近 1,相关性越强
- 返回值越接近 0,相关性越弱
- 主要实现方式:
- PCA【知道】
- 定义:高维数据转换为低维数据,然后产生了新的变量
- API:
sklearn.decomposition.PCA(n_components=None)
n_components
:- 小数:保留百分之多少的信息
- 整数:表示降低到几维
7. 案例:探究用户对物品类别的喜好细分
学习目标:
- 应用 PCA 和 K-means 实现用户对物品类别的喜好细分划分
7.1 需求
无论您是根据精心计划的购物清单购物,还是让自己的心情指导您的购物,我们独特的食物习惯都定义了我们是谁。Instacart 是一款杂货订购和送货应用程序,旨在使您在需要时轻松地用您个人喜欢的和主食填满冰箱和食品储藏室。在通过 Instacart 应用程序选择产品后,个人购物者会查看您的订单并为您进行店内购物和送货。
Instacart 的数据科学团队在提供愉悦的购物体验方面发挥着重要作用。目前,他们使用交易数据开发模型,预测用户将再次购买哪些产品,首次尝试哪些产品,或在会话期间下一次添加到购物车中的产品。最近,Instacart 开源了这些数据 - 请参阅他们关于 300 万 Instacart 订单的博客文章。
在这场比赛中,Instacart 挑战 Kaggle 社区使用这些匿名的客户订单数据来预测用户下一个订单中将包含哪些先前购买过的产品。他们不仅寻找最佳模型,Instacart 还在寻找机器学习工程师来壮大他们的团队。
本次比赛的获胜者将获得现金奖励和快速通过招聘流程的机会。有关 Instacart 的令人兴奋的机会的更多信息,请查看他们的招聘页面或直接发送电子邮件至 ml.jobs@instacart.com 与他们的招聘团队联系。
数据集链接:Instacart Market Basket Analysis
数据如下:
order_products_prior.csv
:订单与商品信息- 字段:
order_id
,product_id
,add_to_cart_order
,reordered
- 字段:
products.csv
:商品信息- 字段:
product_id
,product_name
,aisle_id
,department_id
- 字段:
orders.csv
:用户的订单信息- 字段:
order_id
,user_id
,eval_set
,order_number
, …
- 字段:
aisles.csv
:商品所属具体物品类别- 字段:
aisle_id
,aisle
- 字段:
7.2 分析
- 获取数据
- 数据基本处理
- 合并表格
- 交叉表合并
- 数据截取
- 特征工程:PCA
- 机器学习(K-means)
- 模型评估
sklearn.metrics.silhouette_score(X, labels)
- 计算所有样本的平均轮廓系数
X
:特征值labels
:被聚类标记的目标值
7.3 代码实现
7.3.0 导入库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.feature_selection import VarianceThreshold
from sklearn.decomposition import PCA
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
7.3.1 获取数据
# 1. 读取数据
order_product = pd.read_csv("./data/instacart-market-basket-analysis/order_products__prior.csv")
products = pd.read_csv("./data/instacart-market-basket-analysis/products.csv")
orders = pd.read_csv("./data/instacart-market-basket-analysis/orders.csv")
aisles = pd.read_csv("./data/instacart-market-basket-analysis/aisles.csv")
7.3.2 数据基本处理
7.3.2.1 合并表格
# 2. 数据基本处理
## 2.1 合并表格
# on:标签或列表。要连接的列或索引级别名称。这些必须在两个 DataFrame 中都能找到。如果 on 为 None 并且未在索引上合并,则默认为两个 DataFrame 中列的交集。
table_1 = pd.merge(order_product, products, on=["product_id", "product_id"])
table_2 = pd.merge(table_1, orders, on=["order_id", "order_id"])
table = pd.merge(table_2, aisles, on=["aisle_id", "aisle_id"])
7.3.2.2 交叉表合并
交叉表(Cross Tabulations)是一种常用的分类汇总表格,用于频数分布统计,主要价值在于描述了变量间关系的深刻含义。它可以计算两个(或更多)因子的简单交叉表。默认情况下,它会计算因子的频率表,除非传递了值数组和聚合函数。
例如,我们可以使用 pd.crosstab
函数来计算两个分类变量之间的交叉表。结果显示了每个变量中每个值与另一个变量中每个值的组合出现的次数。
下面是一个简单的例子,说明如何使用 pd.crosstab
函数来计算交叉表:
import pandas as pd
# 创建示例数据
data = {'性别': ['男', '女', '男', '女', '男', '女', '男', '男'],
'喜欢的颜色': ['红', '红', '蓝', '绿', '蓝', '蓝', '红', '绿'],
'数量': [1, 2, 3, 4, 5, 6, 7, 8]}
df = pd.DataFrame(data)
# 计算交叉表
ct = pd.crosstab(df['性别'], df['喜欢的颜色'])
print(ct)
df.head()
ct.head()
这段代码会输出以下结果:
喜欢的颜色 绿 红 蓝
性别
女 1 1 1
男 1 2 2
在这个例子中,我们使用 pd.crosstab
函数计算了 性别
和 喜欢的颜色
列的交叉表。结果显示了 性别
列中每个值与 喜欢的颜色
列中每个值的组合出现的次数。
推荐视频:Pandas_透视表和交叉表
透视表(Pivot Table)是一种用于汇总和分析数据的工具。它可以根据一个或多个键对数据进行聚合,生成一个新的 DataFrame。透视表中的级别将存储在结果 DataFrame 的索引和列的 MultiIndex 对象(分层索引)中。透视表可以通过一个或多个键分组聚合 DataFrame 中的数据,通过 aggfunc 参数决定聚合类型,是 groupby 的高级功能。
交叉表(Cross Tabulations)是一种常用的分类汇总表格,用于频数分布统计,主要价值在于描述了变量间关系的深刻含义。默认情况下,它会计算因子的频率表,除非传递了值数组和聚合函数。交叉表用于计算一列数据对于另一列数据的分组个数(用于统计分组频率的特殊透视表)。
简而言之,透视表是一种进行分组统计的函数,而交叉表是特殊的透视表,当只统计分组频率时更方便。
## 2.2 交叉表合并
table = pd.crosstab(table["user_id"], table["aisle_id"])
table.head()
这里我们使用交叉表合并是因为我们想要看一下"user_id"和商品类别"aisle_id"有什么关系。
7.3.2.3 数据截取
## 2.3 数据截取
table_clip = table[:1000]
table_clip.head()
7.3.3 特征工程:PCA主成分分析
# 3. 特征工程:PCA主成分分析
transfer = PCA(n_components=0.9) # 保留90%的信息
data = transfer.fit_transform(table_clip)
data
array([[-2.27452872e+01, -7.32942365e-01, -2.48945893e+00, ...,
-4.78491473e+00, -3.10742945e+00, -2.45192316e+00],
[ 5.28638801e+00, -3.00176267e+01, -1.11226906e+00, ...,
9.24145693e+00, -3.11309382e+00, 2.20144174e+00],
[-6.52593099e+00, -3.87333123e+00, -9.23859508e+00, ...,
-1.33929081e+00, 1.25062993e+00, 6.12717485e-01],
...,
[ 1.31226615e+01, -2.77296885e+01, -4.62403246e+00, ...,
7.40793534e+00, 1.03829352e+00, -1.39058393e+01],
[ 1.64905900e+02, -8.54916188e+01, 1.90577481e-02, ...,
-5.62014943e+00, -1.38488891e+01, -7.11424774e+00],
[-1.60244724e+00, 1.82037661e+00, 8.55756408e+00, ...,
3.69860152e+00, 2.82248188e+00, -3.79491023e+00]])
print("降维前特征数量为:", table_clip.shape)
print("降维后特征数量为:", data.shape)
降维前特征数量为: (1000, 134)
降维后特征数量为: (1000, 22)
7.3.4 机器学习:K-means 聚类算法
import os
os.environ["OMP_NUM_THREADS"] = "4"
# 4. 机器学习:K-means聚类
estimator = KMeans(n_clusters=8, random_state=22) # 分为8类
pred = estimator.fit_predict(data)
pred
array([0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 7, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 7, 1, 0,
1, 6, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 7,
0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 2, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 3, 7, 1,
1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 7, 0,
0, 0, 0, 1, 0, 7, 0, 1, 0, 0, 6, 4, 0, 0, 0, 7, 0, 1, 0, 0, 1, 1,
1, 1, 3, 0, 0, 1, 7, 0, 1, 0, 0, 7, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
7, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 3,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 7, 0, 0, 1, 0, 0,
0, 0, 4, 5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0,
7, 0, 0, 0, 4, 0, 0, 1, 0, 0, 0, 0, 7, 1, 3, 0, 0, 0, 3, 0, 0, 0,
0, 1, 0, 7, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 4, 0,
0, 0, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1,
0, 7, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 2, 1, 0, 0, 1, 0, 0, 0, 0, 1,
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 4, 0, 0, 0, 1, 0, 1, 1, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2,
0, 7, 1, 7, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 7, 0, 0, 0,
0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
0, 1, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 7,
1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 4, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 7, 1, 0, 0, 1,
0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 7, 0, 0, 0, 1, 7, 0, 0, 3, 1, 1, 1, 1, 0, 3, 0, 1, 3, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 0, 3, 0, 0, 0, 0, 0, 1, 0, 0, 3, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 7, 1, 1, 0, 1, 0, 0, 0,
1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 7, 0, 0, 0, 0, 1, 7, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 3, 0, 0,
0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0,
0, 0, 7, 0, 1, 1, 0, 0, 1, 0, 2, 1, 0, 0, 0, 7, 0, 7, 1, 0, 1, 0,
0, 1, 0, 0, 1, 1, 0, 1, 0, 7, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 7, 7,
1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 2, 0, 7, 0, 1, 0, 1, 0, 0,
0, 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 1, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 0, 1, 1, 0, 3, 0, 0, 0, 3,
1, 0, 0, 1, 7, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 1, 2, 0])
7.3.5 模型评估
轮廓系数(Silhouette Coefficient)是一种用于评估聚类效果的指标。它通过计算每个样本的轮廓系数来衡量聚类效果。轮廓系数是通过计算每个样本的平均簇内距离(a)和平均最近簇距离(b)来计算的。每个样本的轮廓系数为 (b - a) / max(a, b)
。其中,b 是样本与不属于该样本的最近簇之间的距离。注意,当标签数量为 2 <= n_labels <= n_samples - 1
时,才定义轮廓系数。此函数返回所有样本的平均轮廓系数。
轮廓系数的取值范围为 [ − 1 , 1 ] [-1, 1] [−1,1]:
- 当系数为 1 时,说明聚类效果很好;
- 当系数为 -1 时,说明聚类效果很差;
- 当系数接近 0 时,说明簇之间有重叠。
负值通常表示样本被分配到了错误的簇,因为不同的簇更相似。
在 scikit-learn 库中,可以使用 sklearn.metrics.silhouette_score
函数来计算轮廓系数。该函数需要提供数据矩阵 X
和标签数组 labels
,并返回所有样本的平均轮廓系数。
# 5. 模型评估
score = silhouette_score(data, pred)
score
0.46400567259894415
我们看一下截取不同数量数据后的效果:
clip_num = [10, 50, 100, 500, 1000, 1500, 5000, 10000]
for clip_n in clip_num:
## 2.3 数据截取
table_clip = table[:clip_n]
# 3. 特征工程:PCA主成分分析
transfer = PCA(n_components=0.9) # 保留90%的信息
data = transfer.fit_transform(table_clip)
# 4. 机器学习:K-means聚类
estimator = KMeans(n_clusters=8, random_state=22) # 分为8类
pred = estimator.fit_predict(data)
# 5. 模型评估
score = silhouette_score(data, pred)
print(f"[数据量: {clip_n}] 分数为:{score*100:.4f}%")
[数据量: 10] 分数为:13.2716%
[数据量: 50] 分数为:33.6469%
[数据量: 100] 分数为:31.4929%
[数据量: 500] 分数为:44.9804%
[数据量: 1000] 分数为:46.4006%
[数据量: 1500] 分数为:38.5747%
[数据量: 5000] 分数为:38.0150%
[数据量: 10000] 分数为:37.5044%
可以看到,效果并不是很好,应该是我们使用的特征数量太少导致的。
![Logo](https://devpress.csdnimg.cn/79de2bf0b7994defa4242ef90d5513fa.jpg)
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)