学习目标:
使用不同的聚类准则,产生的聚类结果不同。
聚类算法:是一种典型的无监督学习算法,主要用于将相似的样本自动归到一个类别中。
在聚类算法中根据样本之间的相似性,将样本划分到不同的类别中,使用不同的相似度计算方法,会得到不同的聚类结果,常用的相似度计算方法有欧式距离法。
聚类算法是 无监督 的学习算法,而分类算法属于 监督 的学习算法。
小结:
学习目标:
Q:为什么叫 K-means,K和means分别有什么含义?
A:K-means 聚类算法的名字中的 “K” 表示聚类的数量,而 “means” 表示每个聚类的中心是通过计算该聚类中所有样本的均值得到的。因此,K-means 聚类算法的目标是将给定数据集划分为 K 个簇,使得每个簇内部数据点之间的相似度尽可能高,而不同簇之间的相似度尽可能低。这种划分方法通过迭代寻找 K 个簇的一种划分方案,使得聚类结果对应的损失函数最小。
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 转换为簇距离空间。随机创建不同二维数据集作为训练集,并结合 K-means算法将其聚类,你可以尝试分别聚类不同数量的簇,并观察聚类效果:
聚类参数 n_cluster
传值不同,得到的聚类结果不同:
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 指标由分离度与紧密度的比值得到。这个指标越大,说明聚类效果越好。
小结:
sklearn.cluster.KMeans(n_clusters=8)
【知道】
n_clusters
:开始的聚类中心数量estimator.fit_predict(x)
:计算聚类中心并预测每个样本属于哪个类别。
fit(x)
,然后再调用predict(x)
学习目标:
K
:初始中心点个数(计划聚类的类数)means
:求中心点到其他数据点距离的平均值这个中心点不一定是数据集中已有的点,可以是一个新建的点。
通过下图解释实现流程:
动态图演示:
●点是样本,× 是聚类的中心,几个 × 就代表着我们要聚成几个类。
步骤一:随机设置 K K K 个特征空间内的点作为初始的聚类中心(本案例中初始聚类中心设置为 P1 和 P2)
步骤二:对于其他每个点计算到 K K K 个中心的距离,未知的点选择最近的一个聚类中心点作为标记类别。
步骤三:接着对着标记的聚类中心之后,重新计算出每个聚类的新中心点(平均值)
步骤四:如果计算得出的新中心点与原中心点一样(质心不再移动),那么结束;否则重新进行第二步过程【经过判断,需要重复上述步骤,开始新一轮迭代】
注意:当每次迭代结果不变时,认为算法收敛,聚类完成,K-means 一定会停下,不可能陷入一直选质心的过程。
小结:
学习目标:
由于聚类是一种无监督学习方法,因此评估聚类模型的效果并不像监督学习那样直接。常用的聚类模型评估指标包括 SSE(误差平方和)、“肘”部法、SC 系数(轮廓系数)和 CH 系数(Calinski-Harabasz Index)等。这些指标可以帮助我们评估聚类算法效果并选择最佳参数。
举例:(下图中数据 -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 算法内质心的选取时随机的,因此,在质心选取时,当两个质心初始距离较近时,可能产生不好的结果,因此 SSE 最后的结果是局部内最优解,而不是全局最优解。如下图所示:
如果质心的初始值选择不好,SSE 只会达到一个不怎么好的局部最优解
在决定什么时候停止训练时,肘形判据同样有效,数据通常有更多的噪音,在增加分类无法带来更多回报时,我们停止增加类别。
结合了聚类的凝聚度(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 ]之间的度量指标:
每次聚类后,每个样本都会得到一个轮廓系数:
从平均 SC 系数结果来看, K K K 取 3、5、6 是不好的,那么 2 和 4 呢?
K = 2 K=2 K=2 的情况:
K = 4 K=4 K=4 的情况:
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
其中:
迹(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 需要达到的目的:用尽量少的类别聚类尽量多的样本,同时获得较好的聚类效果。
小结:
学习目标:
K-means 算法小结:
N N N 为样本点个数, K K K 为中心商个数, I I I 为迭代次数
Canopy 算法是一种无监督的“粗”聚类算法,它通过设定两个阈值 T 1 T1 T1 和 T 2 T2 T2( T 1 > T 2 T1 > T2 T1>T2)来将数据点分为不同的簇。
Canopy 算法的基本思想是:对于每个数据点,计算它与其他所有数据点的距离:
Canopy 算法的优点是简单易实现,不需要提前确定簇的数目 K。但是 Canopy 算法只能进行粗聚类,聚类结果不够精确。因此,Canopy 算法通常用作其他聚类算法(如 K-means 算法)的预处理步骤,先进行粗聚类,再进行精细聚类。
Canopy 算法的步骤如下:
Canopy 算法可以用来进行“粗”聚类,得到 K 值以及大致的 K 个初始质心,再使用 K-means 进行进一步“细”聚类。这种 Canopy + K-means 的形式聚类算法聚类效果良好。
优点:
在 Canopy 算法中,NumPoint 指的是 Canopy 中包含点的数量。而 centerPoint 指的是 Canopy 中心点,即 Canopy 选择出来的每个 Canopy 的中心点。这些中心点可以作为 K-means 算法的初始质心,从而提高 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
其中:
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++ 算法流程如下:
标准 K-means 算法的流程如下:
K-means++ 算法通过改进初始聚类中心的选择方式,可以有效避免标准 K-means 算法有时发现的较弱聚类,从而提高聚类效果。
二分 K-means 算法是一种基于 K-means 算法改进的算法。它的主要思想是先从一个总簇开始,不断通过二分裂,直到分裂成 K 个簇为止。
二分 K-means 算法流程如下:
二分 K-means 算法可以有效地解决 K-means 算法收敛于局部最小值问题,提高聚类效果。
二分 K-means 隐含的一个原则:
因为聚类的误差平方和 SSE 能够衡量聚类性能,该值越小表示数据点越接近于他们的质心,聚类效果就越好。所以需要对误差平方和 SSE 最大的簇进行再一次划分,因为误差平方和越大,表示该簇聚类效果越不好,越有可能是多个簇被当成了一个簇,所以我们首先需要对这个簇进行划分。
二分 K-means 算法可以加速 K-means 算法的执行速度,因为它的相似度计算少了并且不受初始化问题的影响。二分 K-means 算法不存在随机点的选取,且每一步都保证了误差最小。
K-medoids 和 K-means 是有区别的,不一样的地方在于中心点的选取。
medoids:
/ˈmɛdɔɪdz/
中心点
Q:意思就是 K-means 算法通过计算该簇中所有数据点的平均值得到中心点,这个中心点是新建的,而 K-medoids 是选取当前簇中已有的点,对吗?
A:是的,这样的理解是正确的。
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-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 多。
简单来说:
Kernel K-means 算法是一种基于核方法的 K-means 算法,它可以处理非线性可分的数据。它通过将数据映射到高维空间,使得原本在低维空间中线性不可分的数据在高维空间中变得线性可分,从而提高聚类效果。
Kernel K-means 算法的流程与标准 K-means 算法类似,但在计算距离时使用了核函数来计算样本点之间的相似度,这样可以有效地解决标准 K-means 算法无法处理非线性可分数据的问题。
Kernel K-means 实际上就是将每个样本进行一个投射,投射到高维空间的处理,然后再将处理后的数据使用普通的 K-means 算法思想进行聚类。
ISODATA 算法(Iterative Self-Organizing Data Analysis Techniques Algorithm,迭代自组织数据分析技术算法)是一种改进的 K-means 算法。它在聚类过程中引入了对类别的评判标准,根据标准自动对某些类别进行合并或分裂,在一定程度上突破了对于给定类别数的限制。
该算法能够在聚类过程中根据各个类所包含样本的实际情况动态调整聚类中心的数目。如果某个类中样本分散程度较大(通过方差进行衡量)并且样本数量较大,则对其进行分裂操作;如果某两个类别靠得比较近(通过聚类中心的距离衡量),则对它们进行合并操作。
ISODATA 算法是一种重复自组织数据分析技术,计算数据空间中均匀分布的类均值,然后用最小距离技术将剩余像元进行迭代聚合,每次迭代都重新计算均值,且根据所得的新均值,对像元再进行分类。
特点:
Mini Batch K-means 算法是 K-means 算法的一种优化方案,它适合大数据的聚类算法。该算法采用小批量的数据子集来减少计算时间,同时仍然试图优化目标函数。这里所谓的小批量是指每次训练算法时所随机抽取的数据子集,采用这些随机产生的子集进行训练算法,大大减小了计算时间。与其他算法相比:
通常当样本量大于 1万 做聚类时,就需要考虑选用 Mini Batch K-means 算法。
该算法的迭代步骤有两步:
与 K-means 相比,数据的更新在每一个小的样本集上。对于每一个小批量,通过计算平均值得到更新质心,并把小批量里的数据分配给该质心。随着迭代次数的增加,这些质心的变化是逐渐减小的,直到质心稳定或者达到指定的迭代次数,停止计算。
小结:
优化方法 | 思路 | 提前确定 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 | 大数据集分批聚类,每次迭代只使用部分数据进行计算,减少计算量和时间开销 | 是 | 新建点 |
学习目标:
在机器学习和统计学领域,降维是指在某些限定条件下,降低随机变量个数,得到一组“不相关”主变量的过程。降维可进一步细分为变量选择和特征提取两大方法。
简单来说,降维就是采用某种映射方法,将原高维空间中的数据点映射到低维度的空间中。这样做的目的是为了减少冗余信息和噪声信息造成的误差,提高应用中的精度。常见的数据降维方法有: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):
正是因为在进行训练的时候,我们都是使用特征进行学习。如果特征本身存在问题或者特征之间相关性较强,对于算法学习预测会影响较大。
数据中包含冗余或无关变量(或称特征、属性、指标等),旨在从原有特征中找出主要特征。
方差是用来衡量一组数据离散程度的度量。它表示每一个变量(观察值)与总体均数之间的差异。方差越大,说明数据的波动越大;方差越小,说明数据的波动越小。
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
减少到所选特征。我们对某些股票的指标特征之间进行一个筛选,除去 '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]]
主要实现方式:
一、作用
皮尔森相关系数是一种统计指标,用于反映两个变量之间相关关系的密切程度。它的取值范围为 [ − 1 , 1 ] [-1,1] [−1,1]:
二、公式计算案例(了解,不用记忆)
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
其中:
举例:比如说我们计算年广告费投入与月均销售额。
那么之间的皮尔森相关系数怎么计算?
最终计算:
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。其性质如下:
四、皮尔森相关系 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
之间存在着显著的相关性。
一、作用:
斯皮尔曼等级相关系数(Spearman’s rank correlation coefficient,简称等级相关系数或秩相关系数)是一种衡量两个变量相关性的非参数指标。它利用单调函数评价两个统计变量的相关性。当数据中没有重复值,且当两变量完全单调相关时,斯皮尔曼相关系数为+1或−1。
二、公式(了解,不用记忆):
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]
最后,我们可以使用这些秩差来计算斯皮尔曼等级相关系数。
举例:
三、特点:
斯皮尔曼相关系数比皮尔森相关系数应用更加广泛
四、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] 的区间内取值,且具有相似的解释:
不过,皮尔森相关系数衡量的是两个变量之间的线性相关性,而斯皮尔曼相关系数衡量的是两个变量之间的单调相关性。因此,在处理非线性数据时,斯皮尔曼相关系数可能更为合适。
主成分分析(Principal Component Analysis,PCA)是一种常用的数据降维技术。它通过线性变换将一组可能相关的变量转换为一组线性不相关的变量,这些不相关的变量称为主成分。主成分分析可以通过保留低维主成分,忽略高维主成分来减少数据集的维数,同时保留数据集中对方差贡献最大的特征。
定义:高维数据转化为低维数据的过程,在此过程中可能会舍弃原有数据、创造新的变量。
作用:数据维数压缩,尽可能降低原数据的维数(复杂度),损失少量信息。
应用:回归分析或者聚类分析当中。
对于信息一词,在决策树中会进行介绍
那么如何更好的理解这个过程呢?我们来看一张图。
要想看到一个茶壶的全貌,我们可以很明显的看到,第四张图是最容易的正式茶壶的全貌的。虽然看不到所有的细节,但不影响我们主要因素的获取。
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’。
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)
:将数据降维。先拿个简单的数据计算一下:
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]]
sklearn.feature_selection.VarianceThreshold(threshold=0.0)
threshold
一定要进行值的指定from scipy.stats import pearsonr
from scipy.tats import spearmanr
sklearn.decomposition.PCA(n_components=None)
n_components
:
学习目标:
无论您是根据精心计划的购物清单购物,还是让自己的心情指导您的购物,我们独特的食物习惯都定义了我们是谁。Instacart 是一款杂货订购和送货应用程序,旨在使您在需要时轻松地用您个人喜欢的和主食填满冰箱和食品储藏室。在通过 Instacart 应用程序选择产品后,个人购物者会查看您的订单并为您进行店内购物和送货。
Instacart 的数据科学团队在提供愉悦的购物体验方面发挥着重要作用。目前,他们使用交易数据开发模型,预测用户将再次购买哪些产品,首次尝试哪些产品,或在会话期间下一次添加到购物车中的产品。最近,Instacart 开源了这些数据 - 请参阅他们关于 300 万 Instacart 订单的博客文章。
在这场比赛中,Instacart 挑战 Kaggle 社区使用这些匿名的客户订单数据来预测用户下一个订单中将包含哪些先前购买过的产品。他们不仅寻找最佳模型,Instacart 还在寻找机器学习工程师来壮大他们的团队。
本次比赛的获胜者将获得现金奖励和快速通过招聘流程的机会。有关 Instacart 的令人兴奋的机会的更多信息,请查看他们的招聘页面或直接发送电子邮件至 [email protected] 与他们的招聘团队联系。
数据集链接: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
sklearn.metrics.silhouette_score(X, labels)
X
:特征值labels
:被聚类标记的目标值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
# 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")
# 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"])
交叉表(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"有什么关系。
## 2.3 数据截取
table_clip = table[:1000]
table_clip.head()
# 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)
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])
轮廓系数(Silhouette Coefficient)是一种用于评估聚类效果的指标。它通过计算每个样本的轮廓系数来衡量聚类效果。轮廓系数是通过计算每个样本的平均簇内距离(a)和平均最近簇距离(b)来计算的。每个样本的轮廓系数为 (b - a) / max(a, b)
。其中,b 是样本与不属于该样本的最近簇之间的距离。注意,当标签数量为 2 <= n_labels <= n_samples - 1
时,才定义轮廓系数。此函数返回所有样本的平均轮廓系数。
轮廓系数的取值范围为 [ − 1 , 1 ] [-1, 1] [−1,1]:
负值通常表示样本被分配到了错误的簇,因为不同的簇更相似。
在 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%
可以看到,效果并不是很好,应该是我们使用的特征数量太少导致的。