第九章.聚类算法
以空间中k个点为中心进行聚类,对最靠近他们的对象归类,通过迭代的方法,逐次更新各据类中心值,直至得到最好的据类结果。
1).先从没有标签的元素集合A中随机取k个元素,作为k个子集各自的重心。
2).分别计算剩下的元素到k个子集重心的距离(可以使用欧氏距离),根据距离将这些元素分别划归到最近的子集
3).根据聚类结果,重新计算重心(重心的计算方式:计算子集中所有元素各个维度的算数平均数)
4).将集合A中所有元素按照新的重心重新聚类
5).重复步骤4,直至聚类结果不在发生变化。
·测试数据链接: kmeans.txt
·代码实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
# 绘制等高线图
def coutour(data, model, centers):
x_min, x_max = data[:, 0].min() - 1, data[:, 0].max() + 1
y_min, y_max = data[:, 1].min() - 1, data[:, 1].max() + 1
# 生成网格矩阵
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
np.arange(y_min, y_max, 0.02))
z = model.predict(np.c_[xx.ravel(), yy.ravel()]) ## ravel与flatten类似,多维数据转一维。flatten不会改变原始数据,ravel会改变原始数据
zz = z.reshape(xx.shape)
# 等高线图
contour = plt.contourf(xx, yy, zz)
# 画出各个数据点,用不同的颜色表示分类
mark = ['or', 'ob', 'og', 'ok']
for i, d in enumerate(data): # 用于for循环中得到计数,并获得索引和值
plt.plot(d[0], d[1], mark[result[i]])
mark = ['*r', '*b', '*g', '*k']
for i, center in enumerate(centers):
plt.plot(center[0], center[1], mark[i], markersize=20)
# 加载数据
data = np.genfromtxt('F:\\kmeans.txt', delimiter=' ')
# 设置k值
k = 4
# 训练模型
model = KMeans(n_clusters=k, n_init=4)
model.fit(data)
# 分类重心坐标
centers = model.cluster_centers_
print(centers)
# 预测结果
result = model.predict(data)#result = model.labels_
coutour(data, model, centers)
plt.show()
Mini Batch K-Means算法是K-Means算法的变种,采用小批量的数据子集减小计算时间。这里所谓的小批量是指每次训练算法时所随机抽取的数据子集,采用这些随机产生的子集进行训练算法,大大减小了计算时间,结果一般只略差于标准算法。
①.Mini Batch K-Means的数据更新是在每一个小的样本集上
②.Mini Batch K-Means比K-Means有更快的收敛速度,但同时也降低了聚类效果,但在实际项目中却表现得不明显。
①.从数据集中随机抽取一些数据形成小批量,把他们分配给最近的质心。
②.更新质心
·测试数据链接: kmeans.txt
·代码实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import MiniBatchKMeans
# 绘制图像
def Imageshow(data, model, centers):
x_min, x_max = data[:, 0].min() - 1, data[:, 0].max() + 1
y_min, y_max = data[:, 1].min() - 1, data[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
np.arange(y_min, y_max, 0.02))
z = model.predict(np.c_[xx.ravel(), yy.ravel()])
zz = z.reshape(xx.shape)
# 绘制等高线
contour = plt.contourf(xx, yy, zz)
# 预测结果
result = model.labels_
# 绘制散斑点
mark = ['or', 'og', 'ob', 'ok']
for i, d in enumerate(data):
plt.plot(d[0], d[1], mark[result[i]])
# 绘制分类重心
mark = ['*r', '*g', '*b', '*k']
for i, center in enumerate(centers):
plt.plot(center[0], center[1], mark[i], markersize=20)
# 载入数据
data = np.genfromtxt('F:\\kmeans.txt', delimiter=' ')
# 设置K值
k = 4
# 训练模型
model = MiniBatchKMeans(n_clusters=k, n_init=4)
model.fit(data)
# 分类重心坐标
centers = model.cluster_centers_
print(centers)
Imageshow(data, model, centers)
plt.show()
1).对k个初始质心的选择比较敏感,容易陷入局部最小值。
2).K值的选择是用户指定的,不同的k得到的结果会有挺大的不同
4).数据比较大的时候,收敛会比较慢(可以使用Mini Batch K-Means来可以解决这种问题)
1).使用多次的随机初始化,计算每一次建模得到的代价函数 的值,选取代价函数最小结果作为聚类结果。
2).使用肘部法则来选择k的值
不同的k值,对应不同的代价函数值,并且k值越大代价函数值越小,若存在一个肘部“Elbow”,则肘部所对对应的k值即为所选k值
第二幅图中的肘部不太明显,需要根据具体的需要具体分析。