有监督学习&无监督学习:
决策树,随机森林,PCA和逻辑回归,他们虽然有着不同的功能,但却都属于“有监督学习”的一部分,即是说,模型在训练的时候,即需要特征矩阵X,也需要真实标签y。
机器学习当中,还有相当一部分算法属于“无监督学习”,无监督的算法在训练的时候只需要特征矩阵X,不需要标签。而聚类算法,就是无监督学习的代表算法。
K-Means的定义:
作为聚类算法的典型代表,KMeans可以说是最简单的聚类算法没有之一,那它是怎么完成聚类的呢?
答:
KMeans算法将一组N个样本的特征矩阵X划分为K个无交集的簇,直观上来看是簇是一组一组聚集在一起的数据,在一个簇中的数据就认为是同一类。簇就是聚类的结果表现。
簇中所有数据的均值通常被称为这个簇的“质心”(centroids)。
在一个二维平面中,一簇数据点的质心的横坐标就是这一簇数据点的横坐标的均值,质心的纵坐标就是这一簇数据点的纵坐标的均值。同理可推广至高维空间。
簇的个数K是一个超参数,需要我们人为输入来确定。KMeans的核心任务就是根据我们设定好的K,找出K个最优的质心,并将离这些质心最近的数据分别分配到这些质心代表的簇中去。
K-Means的过程:
1 随机抽取K个样本作为最初的质心
2 开始循环:
2.1 将每个样本点分配到离他们最近的质心,生成K个簇
2.2 对于每个簇,计算所有被分到该簇的样本点的平均值作为新的质心
3 当质心的位置不再发生变化,迭代停止,聚类完成
评估指标:
被分在同一个簇中的数据是有相似性的,而不同簇中的数据是不同的,当聚类完毕之后,我们就要分别去研究每个簇中的样本都有什么样的性质,从而根据业务需求制定不同的商业或者科技策略。
簇内平方和(cluster Sum of Square), 又叫做Inertia。
而将一个数据集中的所有簇的簇内平方和相加,就得到了整体平方和(Total Cluster Sum of Square),又叫做total inertia。
Total Inertia越小,代表着每个簇内样本越相似,聚类的效果就越好。
因此,KMeans追求的是,求解能够让Inertia最小化的质心。
实际上,在质心不断变化不断迭代的过程中,总体平方和是越来越小的。我们可以使用数学来证明,当整体平方和最小的时候,质心就不再发生变化了。
如此,K-Means的求解过程,就变成了一个最优化问题。
轮廓系数也可以。
聚类的实例:
# 计算机生成的数据集:sklearn.datasets.make_<name>
# blobs 一点 一小片
# 自己创建数据集
# make_blobs会根据用户指定的样本个数、特征数量、中心点数量、范围等
# n_features<=3 才能被可视化
# 来生成几类数据,这些数据可用于测试聚类算法的效果
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
x,y=make_blobs(n_samples=500,n_features=2,
centers=4,random_state=1)
fig,ax1=plt.subplots(1)
# fig一个画布,ax1一个子图。subplot(1)一个子图,这段代码相当于:
# fig=plt.figure()
# ax1=fig.subplots(1)
ax1.scatter(x[:,0],x[:,1],marker='o',s=8)
# x的所有行和第0列为横坐标,x的所有行和第一列为纵坐标
# marker点的形状 s点的大小
plt.show()
基于这个分布,我们来使用Kmeans进行聚类。
假设在不知道上面的数据是几簇的条件下,确定分几簇好?
(真实答案在文章末尾,但实际生活中的聚类往往是没有答案的,只有通过聚多类找相对好的或者适合业务的。)
首先,我们要猜测一下,这个数据中有几簇?
若分三簇:
from sklearn.cluster import KMeans
n_clusters=3
# 实例化
cluster=KMeans(n_clusters=n_clusters,random_state=0).fit(x)
# 重要属性labels_,用来查看聚好的类别,每个样本对应的类
y_pred=cluster.labels_
y_pred
# KMeans因为不需要建立模型或者预测结果,因此我们只需要fit就能得到聚类的结果了。
# 但是KMeans也有接口predict和fit_predict,表示学习数据x并对x的类进行预测
# 但是fit_predict所得到的结果和直接调用labels_的结果一模一样。
pre=cluster.fit_predict(x)
pre
# 重要属性cluster_centers_,用来查看质心(横坐标,纵坐标)
# 因为聚了3类,所以这里有3个坐标
centroid=cluster.cluster_centers_
centroid
# 分三簇时聚类的图形
color=["red","pink","orange"]
fig,ax1=plt.subplots(1)
for i in range(n_clusters):
ax1.scatter(x[y_pred==i,0],x[y_pred==i,1],marker='o',s=8,c=color[i])
ax1.scatter(centroid[:,0],centroid[:,1],marker="x",s=100,c="black")
plt.show()
# 重要属性inertia_,查看总距离平方和
# 聚类效果越好,inertia越低
# 分3簇时的总距离平方和:
inertia=cluster.inertia_
inertia
1903.4503741659223
# 重要属性轮廓系数silhouette_score,
# 分3簇时的轮廓系数:
from sklearn.metrics import silhouette_score
silhouette_score(x,cluster.labels_)
0.5882004012129721
# 每个样本点的轮廓系数:
from sklearn.metrics import silhouette_samples
silhouette_samples(x,cluster.labels_)
分好多簇时的总距离平方和inertia和轮廓系数silhouette_score:
# 分2,3,4,5,6,7,8簇时的总距离平方和inertia
# 和轮廓系数silhouette_score:
# 聚类效果越好,inertia越低
# 聚类效果越好,silhouette_score越接近1
sc=[]
inertia=[]
for i in range(2,9):
cluster= KMeans(n_clusters=i,random_state=0).fit(x)
s_=silhouette_score(x,cluster.labels_)
sc.append(s_)
inertia_=cluster.inertia_
inertia.append(inertia_)
可见,随着分的簇越多,inertia越小,这说明inertia并不能作为衡量KMeans的标准,有很多缺点:
首先,它不是有界的。我们只知道,Inertia是越小越好,是0最好,但我们不知道,一个较小的Inertia究竟有没有达到模型的极限,能否继续提高。
第二,它的计算太容易受到特征数目的影响,数据维度很大的时候,Inertia的计算量会陷入维度诅咒之中,计算量会爆炸,不适合用来一次次评估模型。
第三,Inertia对数据的分布有假设,它假设数据满足凸分布(即数据在二维平面图像上看起来是一个凸函数的样 子),并且它假设数据是各向同性的(isotropic),即是说数据的属性在不同方向上代表着相同的含义。但是现实 中的数据往往不是这样。所以使用Inertia作为评估指标,会让聚类算法在一些细长簇,环形簇,或者不规则形状的流形时表现不佳。
那用什么指标好呢?
答:
轮廓系数silhoutte_score
轮廓系数范围是(-1,1),其中值越接近1表示样本与自己所在的簇中的样本很相似,并且与其他簇中的样本不相似;
当样本点与簇外的样本更相似的时候,轮廓系数就为负;
当轮廓系数为0时,则代表两个簇中的样本相似度一致,两个簇本应该是一个簇。
谜底:
# 画出生成的图真实的样子。因为我一开始就分了4个feature。
color=['red','pink','orange','gray']
fig,ax1=plt.subplots(1)
for i in range(4):
ax1.scatter(x[y==i,0],x[y==i,1],marker='o',s=8,c=color[i])
# scatter(x轴,y轴,点的形状,点的大小,点的颜色)
plt.show()
来源:CSDN
作者:海边的渡边彻
链接:https://blog.csdn.net/weixin_37856444/article/details/103791647