机器学习之K均值算法(K-means)聚类

K均值算法(K-means)聚类

【关键词】K个种子,均值

一、K-means算法原理

聚类的概念:一种无监督的学习,事先不知道类别,自动将相似的对象归到同一个簇中。

K-Means算法是一种聚类分析(cluster analysis)的算法,其主要是来计算数据聚集的算法,主要通过不断地取离种子点最近均值的算法。

K-Means算法主要解决的问题如下图所示。我们可以看到,在图的左边有一些点,我们用肉眼可以看出来有四个点群,但是我们怎么通过计算机程序找出这几个点群来呢?于是就出现了我们的K-Means算法

这里写图片描述

这个算法其实很简单,如下图所示:

这里写图片描述

从上图中,我们可以看到,A,B,C,D,E是五个在图中点。而灰色的点是我们的种子点,也就是我们用来找点群的点。有两个种子点,所以K=2。

然后,K-Means的算法如下:

  1. 随机在图中取K(这里K=2)个种子点。
  2. 然后对图中的所有点求到这K个种子点的距离,假如点Pi离种子点Si最近,那么Pi属于Si点群。(上图中,我们可以看到A,B属于上面的种子点,C,D,E属于下面中部的种子点)
  3. 接下来,我们要移动种子点到属于他的“点群”的中心。(见图上的第三步)
  4. 然后重复第2)和第3)步,直到,种子点没有移动(我们可以看到图中的第四步上面的种子点聚合了A,B,C,下面的种子点聚合了D,E)。

这个算法很简单,重点说一下“求点群中心的算法”:欧氏距离(Euclidean Distance):差的平方和的平方根

这里写图片描述

K-Means主要最重大的缺陷——都和初始值有关:

K是事先给定的,这个K值的选定是非常难以估计的。很多时候,事先并不知道给定的数据集应该分成多少个类别才最合适。(ISODATA算法通过类的自动合并和分裂,得到较为合理的类型数目K)

K-Means算法需要用初始随机种子点来搞,这个随机种子点太重要,不同的随机种子点会有得到完全不同的结果。(K-Means++算法可以用来解决这个问题,其可以有效地选择初始点)

总结:K-Means算法步骤:

  1. 从数据中选择k个对象作为初始聚类中心;
  2. 计算每个聚类对象到聚类中心的距离来划分;
  3. 再次计算每个聚类中心
  4. 计算标准测度函数,直到达到最大迭代次数,则停止,否则,继续操作。
  5. 确定最优的聚类中心

K-Means算法应用

看到这里,你会说,K-Means算法看来很简单,而且好像就是在玩坐标点,没什么真实用处。而且,这个算法缺陷很多,还不如人工呢。是的,前面的例子只是玩二维坐标点,的确没什么意思。但是你想一下下面的几个问题:

1)如果不是二维的,是多维的,如5维的,那么,就只能用计算机来计算了。

2)二维坐标点的X,Y 坐标,其实是一种向量,是一种数学抽象。现实世界中很多属性是可以抽象成向量的,比如,我们的年龄,我们的喜好,我们的商品,等等,能抽象成向量的目的就是可以让计算机知道某两个属性间的距离。如:我们认为,18岁的人离24岁的人的距离要比离12岁的距离要近,鞋子这个商品离衣服这个商品的距离要比电脑要近,等等。

二、实战

重要参数:

  • n_clusters:聚类的个数

重要属性:

  • cluster*centers* : [n_clusters, n_features]的数组,表示聚类中心点的坐标
  • labels_ : 每个样本点的标签

1、聚类实例

导包,使用make_blobs生成随机点cluster_std

from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

获取数据

#获取数据
#centers=3 默认值,生成3个聚类点集
X,y = make_blobs()
plt.scatter(X[:,0],X[:,1],c=y)

这里写图片描述

训练模型

#选取3个种子
kmeans = KMeans(n_clusters=3)
# 无监督学习:estimator.fit(X)
# 监督学习:estimator.fit(X,y)
kmeans.fit(X)

显示聚类中心

#查看聚类中心坐标点
cluster_centers_ = kmeans.cluster_centers_
cluster_centers_

这里写图片描述

#显示聚类中心
plt.scatter(X[:,0],X[:,1],c=y)
plt.scatter(cluster_centers_[:,0],cluster_centers_[:,1],
           s=300,alpha=0.4,c='r')

这里写图片描述

预测

#预测
y_ = kmeans.predict(X)
plt.scatter(X[:,0],X[:,1],c = y_)

这里写图片描述

2、亚洲足球队分类

导包

from sklearn.cluster import KMeans
#导入3D图像包
from mpl_toolkits.mplot3d import Axes3D
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

读取数据

#读取数据
football = pd.read_csv('./AsiaZoo.txt',header=None)
football

这里写图片描述

修改列索引

#修改列索引
columns = {0:'国家',1:'2006世界杯',2:'2010世界杯',3:'2007亚洲杯'}
football.rename(columns=columns,inplace=True)

训练模型

#特征数据
X = football.iloc[:,1:]
#3个聚类中心
kmeans = KMeans(3)
#训练模型
kmeans.fit(X)
#预测
y_ = kmeans.predict(X)
y_

这里写图片描述

#输出分类结果
for i in range(3):
    print('--------第%d类--------'%(3-i))
    index = np.argwhere(y_ == i).reshape(-1)
    print(football['国家'][index].values)

这里写图片描述

绘制3D图像

fig = plt.figure(figsize=(8,8))
axes3D = Axes3D(fig)
axes3D.scatter(X['2006世界杯'],X['2010世界杯'],X['2007亚洲杯'],
                c = y_)
#设置坐标轴标签 字体为宋体 大小为30
axes3D.set_xlabel('2006世界杯',fontproperties = 'FangSong',
                  size = 30)
axes3D.set_ylabel('2010世界杯',fontproperties = 'FangSong',
                  size = 30)
axes3D.set_zlabel('2007亚洲杯',fontproperties = 'FangSong',
                  size = 30)

这里写图片描述

三、图片压缩

导包

from sklearn.cluster import KMeans

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

#绘图时可以显示中文
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

获取数据

bird = plt.imread('./img/bird_small.png')
plt.imshow(bird)

这里写图片描述

这里写图片描述

这张图片大小是128*128像素,有16384个(红,蓝,绿)组成的像素值。

#特征数据
X = bird.reshape(-1,3)
#三维图像变形成二维
df = pd.DataFrame(X)
#查看没有重复的像素值有多少
df.drop_duplicates().shape

这里写图片描述

说明原图颜色种类有13930种。

训练模型

#取16个聚类中心,相当于取16种颜色
kmeans = KMeans(16)
kmeans.fit(X)
#对原图像像素进行分类,分成16类
y_ = kmeans.predict(X)

这里写图片描述

预测后的数据有16384个像素值,颜色种类只有16种,相比原来的图片减少了13930 - 16 = 13914,所以图片相当于压缩了。

绘制压缩后的图片

#获取聚类像素值(即颜色种类)
cluster_centers_ = kmeans.cluster_centers_
cluster_centers_.shape

这里写图片描述

#把分类后的颜色种类取出16384个,组成一幅新的图片
bird_cluster = cluster_centers_[y_]
bird_cluster.shape

这里写图片描述

plt.figure(figsize=(3,1*2))

axes = plt.subplot(1,2,1)
axes.imshow(bird.reshape(128,128,3))
axes.set_title('压缩前')
axes.axis('off')

axes = plt.subplot(1,2,2)
axes.imshow(bird_cluster.reshape(128,128,3))
axes.set_title('压缩后')
axes.axis('off')

这里写图片描述

压缩后的图片和压缩前的图片相似度还是挺高的。

猜你喜欢

转载自blog.csdn.net/lm_is_dc/article/details/81410669
今日推荐