基于k-means的聚类算法—机器学习
Posted python万能实验室
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于k-means的聚类算法—机器学习相关的知识,希望对你有一定的参考价值。
1. k-means算法思想
k-means算法中文名叫做k均值。它是一种非监督聚类算法,如有一堆数据,但是知道这些数据有k个类,具体每一个数据点所属分类不知道。此时就需要用k-means聚类算法,它可以把原先的数据分成k个部分,相似的数据就聚在一起。
2. k-means算法步骤
共有3个步骤:
-
初始化–随机生成K个初始“均值”(质心); -
分配–通过将每个观测值与最近的质心相关联来创建K个聚类,遍历所有点计算该点到那k个聚类中心点的距离。此时有k个距离,哪个距离最短,就认为当前这个点是属于这个聚类; -
更新–群集的质心成为新的均值,得到了k个聚类。到这一步需要重新计算聚类中心。此时聚类中心就是当前这个聚类的包含的点的平均值。也就是说各个点加起来取平均作为当前聚类的中心. -
迭代地重复分配和更新,直到收敛为止,最终结果是,点与它们各自的质心之间的平方误差之和最小。
3 使用Python实现k-means算法
3.1 数据初始化:生成随机样本数据,并生成3个初始"质心"
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
df = pd.DataFrame({
'x': [12, 20, 28, 18, 29, 33, 24, 45, 45, 52, 51, 52, 55, 53, 55, 61, 64, 69, 72],
'y': [39, 36, 30, 52, 54, 46, 55, 59, 63, 70, 66, 63, 58, 23, 14, 8, 19, 7, 24]
})
np.random.seed(200) #可以使多次生成的随机数相同
k = 3
# centroids[i] = [x, y]
centroids = {
i+1: [np.random.randint(0, 80), np.random.randint(0, 80)]
for i in range(k)
}
print(centroids)
fig = plt.figure(figsize=(5, 5))#【绘图】plt.figure()的使用
plt.scatter(df['x'], df['y'], color='k')
colmap = {1: 'r', 2: 'g', 3: 'b'}
for i in centroids.keys():
plt.scatter(*centroids[i], color=colmap[i])
plt.xlim(0, 80)
plt.ylim(0, 80)
plt.show()
3.2 分配数据:通过将每个观测值与最近的质心相关联来创建K个聚类
def assignment(df, centroids):
for i in centroids.keys():
# sqrt((x1 - x2)^2 - (y1 - y2)^2) 欧式距离
df['distance_from_{}'.format(i)] = (
np.sqrt(
(df['x'] - centroids[i][0]) ** 2
+ (df['y'] - centroids[i][1]) ** 2
)
)
centroid_distance_cols = ['distance_from_{}'.format(i) for i in centroids.keys()]
df['closest'] = df.loc[:, centroid_distance_cols].idxmin(axis=1)
df['closest'] = df['closest'].map(lambda x: int(x.lstrip('distance_from_')))
df['color'] = df['closest'].map(lambda x: colmap[x])
return df
print(centroids)
df = assignment(df, centroids)
print(df.head())
fig = plt.figure(figsize=(5, 5))
plt.scatter(df['x'], df['y'], color=df['color'], alpha=0.5, edgecolor='k')
for i in centroids.keys():
plt.scatter(*centroids[i], color=colmap[i])
plt.xlim(0, 80)
plt.ylim(0, 80)
plt.show()
3.3 更新–群集的质心成为新的均值
import copy
old_centroids = copy.deepcopy(centroids) #【绘图】plt.figure()的使用
print(old_centroids)
def update(k):
for i in centroids.keys():
centroids[i][0] = np.mean(df[df['closest'] == i]['x'])
centroids[i][1] = np.mean(df[df['closest'] == i]['y'])
return k
centroids = update(centroids)
print(centroids)
fig = plt.figure(figsize=(5, 5))
ax = plt.axes() #设置你的轴域 ax1 = plt.Axes(fig1,[0.2, 0.2, 0.4, 0.4]) 将轴域添加至figurefig1.add_axes(ax1)
plt.scatter(df['x'], df['y'], color=df['color'], alpha=0.5, edgecolor='k')
for i in centroids.keys():
plt.scatter(*centroids[i], color=colmap[i])
plt.xlim(0, 80)
plt.ylim(0, 80)
for i in old_centroids.keys():
old_x = old_centroids[i][0]
old_y = old_centroids[i][1]
dx = (centroids[i][0] - old_centroids[i][0]) * 0.75
print(dx)
dy = (centroids[i][1] - old_centroids[i][1]) * 0.75
print(dy)
ax.arrow(old_x, old_y, dx, dy, head_width=2, head_length=3, fc=colmap[i], ec=colmap[i]) #matplotlib 画箭头的
plt.show()
3.4 重复分配阶段:重复分配和更新
df = assignment(df, centroids)
# Plot results
fig = plt.figure(figsize=(5, 5))
plt.scatter(df['x'], df['y'], color=df['color'], alpha=0.5, edgecolor='k')
for i in centroids.keys():
plt.scatter(*centroids[i], color=colmap[i])
plt.xlim(0, 80)
plt.ylim(0, 80)
plt.show()
3.5 重复进行直到所有集群都没有变化为止
n = 0
while True:
n += 1
print(f'第{n}次迭代.............')
closest_centroids = df['closest'].copy(deep=True)
centroids = update(centroids)
df = assignment(df, centroids)
if closest_centroids.equals(df['closest']):
break
fig = plt.figure(figsize=(5, 5))
plt.scatter(df['x'], df['y'], color=df['color'], alpha=0.5, edgecolor='k')
for i in centroids.keys():
plt.scatter(*centroids[i], color=colmap[i])
plt.xlim(0, 80)
plt.ylim(0, 80)
plt.show()
到此可以看到有3个清晰的群集,在这些群集的中心有3个均值
4 使用scikit-learn进行k-means算法
scikit-learn封装有k-means算法,可以直接调用实现k-means算法功能。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
df = pd.DataFrame({
'x': [12, 20, 28, 18, 29, 33, 24, 45, 45, 52, 51, 52, 55, 53, 55, 61, 64, 69, 72],
'y': [39, 36, 30, 52, 54, 46, 55, 59, 63, 70, 66, 63, 58, 23, 14, 8, 19, 7, 24]
})
kmeans = KMeans(n_clusters=3)
kmeans.fit(df)
labels = kmeans.predict(df) # 使用这个数据进行训练
print(type(labels))
d = kmeans.labels_
print(d) # 我们可以看到每个样本点的聚类标签
centroids = kmeans.cluster_centers_ ## 我们可以看到每个样本点的聚类标签
fig = plt.figure(figsize=(5, 5))
print(labels)
colmap = {1: 'r', 2: 'g', 3: 'b'}
colors = list(map(lambda x:colmap[x+1], labels)) #map(lambda x: x ** 2, [1, 2, 3, 4, 5]) # 使用 lambda 匿名函数 [1, 4, 9, 16, 25]
print(colors)
plt.scatter(df['x'], df['y'], color=colors, alpha=0.5, edgecolor='k')
for idx, centroid in enumerate(centroids):
plt.scatter(*centroid, color=colmap[idx+1])
plt.xlim(0, 80)
plt.ylim(0, 80)
plt.show()
使用scikit-learn封装的API得到的结果与按算法步骤执行的结果完全相同。
5 小结
今天总结了机器学习的k-means算法的思想原理和实现方法:
-
k-means算法属于应用广泛的聚类算法,聚类属于无监督算法(Unsupervied learning),即没有明确的类别,没有明确的label,通过算法把相似的东西分到一个组,来寻找其中的规律; -
k-means算法优点在于原理简单,容易实现,聚类效果好; -
k-means算法缺点:K值、初始点的选取不好确定,得到的结果只是局部最优,受离群值影响大。
以上是关于基于k-means的聚类算法—机器学习的主要内容,如果未能解决你的问题,请参考以下文章