kmeans设置中心_基于kmeans的聚类算法—机器学习(四)

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 pdimport numpy as npimport matplotlib.pyplot as plt%matplotlib inlinedf = 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()
eff376ef3f94148b202dd3a6807e4215.png

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 dfprint(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()
c7a0f9ebf9360000c306063ff874ce51.png

3.3 更新–群集的质心成为新的均值

import copyold_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 kcentroids = 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()
a37702ae27aa408b899f4adf745b4f34.png

3.4 重复分配阶段:重复分配和更新

df = assignment(df, centroids)# Plot resultsfig = 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()
f7d42d127a7194311c8c33b84d9f1cc7.png

3.5 重复进行直到所有集群都没有变化为止

n = 0while 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']):        breakfig = 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()
1eb5d7aeaf1be088a9f9e37dba30e028.png

到此可以看到有3个清晰的群集,在这些群集的中心有3个均值

4 使用scikit-learn进行k-means算法

scikit-learn封装有k-means算法,可以直接调用实现k-means算法功能。

import numpy as npimport pandas as pd import matplotlib.pyplot as pltfrom sklearn.cluster import KMeansdf = 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()

b61b124db712de64db4663879c8cb068.png使用scikit-learn封装的API得到的结果与按算法步骤执行的结果完全相同。

5 小结

今天总结了机器学习的k-means算法的思想原理和实现方法:

  • k-means算法属于应用广泛的聚类算法,聚类属于无监督算法(Unsupervied learning),即没有明确的类别,没有明确的label,通过算法把相似的东西分到一个组,来寻找其中的规律;
  • k-means算法优点在于原理简单,容易实现,聚类效果好;
  • k-means算法缺点:K值、初始点的选取不好确定,得到的结果只是局部最优,受离群值影响大。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值