K-Means
无监督学习与聚类算法
机器学习当中,还有相当一部分算法属于“无监督学习”。
无监督的算法在训练的时候只需要特征矩阵X,不需要标签。
聚类和分类
区别 | 函数 | 描述 |
---|---|---|
核心 | 将数据分成多个组,探索每个组数据是否有联系 | 从已经分组的数据中去学习,把新数据放到已经分好的组中去 |
学习类型 | 无监督,无需标签进行训练 | 有监督,需要标签进行训练 |
典型算法 | K-Means,DBSCAN,层次聚类,光谱聚类 | 决策树,贝叶斯,逻辑回归 |
算法输出 | 聚类结果是不确定的,不一定总是能够反映数据的真实分类 | 分类结果是确定的,分类的优劣是客观的 |
KMeans是如何工作的
作为聚类算法的典型代表,KMeans可以说是最简单的聚类算法没有之一,那它是怎么完成聚类的呢?先看以下这两个概念
簇
- KMeans算法将一组N个样本的特征矩阵X划分为K个无交集的簇,直观上来看是簇是一组一组
聚集在一起的数据,在一个簇中的数据就认为是同一类。簇就是聚类的结果表现。 - 聚类之后产生的集合
质心
- 簇中所有数据的均值 通常被称为这个簇的“质心”(centroids)。
在一个二维平面中,一簇数据点的质心的横坐标就是这一簇数据点的横坐标的均值,
质心的纵坐标就是这一簇数据点的纵坐标的均值。同理可推广至高维空间。 - 聚类之后产生的集合的“中心”
算法思路
则该样本点到质心的距离可以由以下距离来度量:
采用欧几里得距离,则一个簇中所有样本点到质心的距离的平方和为:
其中,m为一个簇中样本的个数,j是每个样本的编号。这个公式被称为簇内平方和,而将一个数据集中的所有簇的簇内平方和相加,就得到了整体平方和。
- 在KMeans算法中,簇的个数K是一个超参数。KMeans的核心任务就是根据我们设定好
的K,找出K个最优的质心,并将离这些质心最近的数据分别分配到这些质心代表的簇中去 -
簇内误差平方和聚类算法追求“簇内差异小,簇外差异大”
而这个“差异“,由样本点到其所在簇的质心的距离来衡量。 -
对于一个簇来说,所有样本点到质心的距离之和越小,我们就认为这个簇中的样本越相似,簇内差异就越小。而距离的衡量方法
有多种,令表示簇中的一个样本点,表示该簇中的质心,n表示每个样本点中的特征数目,i表示组成点的每个特征
展示数据集分布
In [1]:
# 从dataset包中导入数据 from sklearn.datasets import make_blobs import matplotlib.pyplot as plt # make_blobs函数参数详解 # n_samples:待生成的样本的总数 # n_features:每个样本的特征数 # centers:要生成的样本中心数 # random_state:随机的状态,保证随机固定 # X:生成的样本数据集 # y:样本数据集的标签 4 类别 X, y = make_blobs(n_samples=500,n_features=2,centers=4,random_state=1) # 定义圆点的颜色 color = ["red","pink","orange","gray"] # 遍历标签,绘制图像 for i in range(4): # 将样本的第一个特征作为x轴,第一个特征作为y轴 plt.scatter(X[y==i, 0], X[y==i, 1] ,marker='o' #点的形状 ,s=8 #点的大小 ,c=color[i] # 圆点颜色 ) plt.show()
sklearn中的聚类算法
聚类算法在sklearn中有两种表现形式,一种是类,需要实例化,训练并使用接口和属性来调用结果。
另一种是函数(function),只需要输入特征矩阵和超参数,即可返回聚类的结果和各种指标。
类/函数 | 含义 | 输入([]表示可选输入) |
---|---|---|
cluster.KMeans | K均值聚类 | [n_clusters,init,n_init] |
cluster.kmeans | K均值函数 | X,n_cluster[,...] |
使用KMeans分类
In [2]:
from sklearn.cluster import KMeans import numpy as np # 定义质心个数,表示将全部样本分为3个簇 n_clusters = 3 # KMeans参数解释aa # n_clusters:表示要分的簇数量,默认为8个 # random_state:质心初始随机生成,让随机具有确定性 cluster = KMeans(n_clusters=n_clusters, random_state=0).fit(X) # 查看标签,发现标签已经分为三类 y_pred = cluster.labels_ print("标签去重后的结果:\n",np.unique(y_pred))
标签去重后的结果: [0 1 2]
查看质心点
In [3]:
centroid = cluster.cluster_centers_ centroid
Out[3]:
array([[-8.09286791, -3.50997357], [-1.54234022, 4.43517599], [-7.0877462 , -8.08923534]])
查看簇内平方和
In [4]:
inertia = cluster.inertia_ inertia
Out[4]:
1903.5342237665059
绘制分类后图像
In [5]:
color = ["red","pink","orange","gray"] for i in range(n_clusters): plt.scatter(X[y_pred==i, 0], X[y_pred==i, 1] ,marker='o' ,s=8 ,c=color[i] ) plt.scatter(centroid[:,0],centroid[:,1] ,marker="x" ,s=15 ,c="black") plt.show()