一、K均值算法
1、引入
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/08dff88507fad7271bdde8d21f11e894.png#pic_center)
- 如上图a所示,所有的绿色点为数据,从人的主观肉眼上明显看出,该数据分为两类,上面为一类,下面为一类。但是计算机并不知道,那计算机是怎么分类的呢?
- 图b所示,计算机随机生成两个质心点(一般情况下计算机会从已有的原数据中选择质心点,而不是随机生成新的质心点),一个红色一个蓝色。
- 图c所示,计算机会根据每个点的坐标,去计算这些数据距离哪一个质心点距离最近,就把它分到哪一类中,c图所示,将数据一部分分为蓝色类,一部分分为红色类。
- 接下来会更新质心点(质心点更新:将之前分好类的数据按照类求均值,得到每个类的新质心点),如图d所示,计算机会重新选择两个质心点,再重新计算每个数据到质心点之间的距离
- 将数据进一步分类,哪个数据距离哪个质心点最近,就分到哪一类当中,如图e所示。
- 再更新一次质心点,如图f所示,使得质心点在每一分类中靠近中心。最终得到两个分类
- 总结:聚类K均值算法思想和KNN算法相似,距离哪个质心点近就分到哪一类,同时对分好类的数据求均值,得到新的质心点,完成最终的分类。
2、K均值
- k均值(k-means)是聚类算法中最为简单、高效的、属于无监督学习算法
- 核心思想:由用户指定k个初始质心(inital centroids),以作为聚类的类别(cluster),重复迭代直至算法收敛
- 基本算法流程
1、选取K个初始质心(作为初始cluster)
2、repeat:
(1) 对每一个样本点,计算得到距离其最近质心,将其类别标为该质心所对应的cluter
(2)重新计算k个cluster对应的质心
3、直到l质心不再发生变化或者迭代达到上限
3、代码案例
import numpy as np
import matplotlib.pyplot as plt
#引入scipy中的距离函数,默认欧式距离
from scipy.spatial.distance import cdist
#从sklearn中直接生成聚类数据
from sklearn.datasets._samples_generator import make_blobs
if __name__ == '__main__':
#数据加载
# n_samples:表示数据个数
# centers:表示质心点个数,也是分类的个数
# random_state:随机种子,随机生成的数据为同一个数据
# cluster_std:质心点随机分布时,偏差值为多少
# x:表示数据集(坐标),y:表示类别,属于哪一类
x,y = make_blobs(n_samples=100,centers=6,random_state=1024,cluster_std=0.6)
#因为数据集x是一个二维数组,第一列为点的x坐标,第二列为y坐标
#建立散点图,c表示颜色,c=y表示,由多少分类就由多少种颜色
plt.scatter(x[:,0],x[:,1],c=y)
plt.show()
- 散点图展示
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/2482a0b1e8fbd7e3c0d7b249fbc39cf4.png#pic_center)
#算法k-means实现
class K_Means(object):
#初始化,参数n_clusters(K)、迭代次数max_iter、初始质心centroids
def __init__(self,n_clusters=6,max_iter=300,centroids=[]):
self.n_clusters = n_clusters
self.max_iter = max_iter
self.centroids = np.array(centroids,dtype=np.float)
#训练模型方法,k-means聚类过程,传入原始数据
def fit(self,data):
#假如没有指定初始质心,就随机选取data中的点作为初始质心
if(self.centroids.shape==(0,)):
#从data中随机生成0到data行的6个整数,作为索引值
self.centroids = data[np.random.randint(0,data.shape[0],self.n_clusters),:]
#开始迭代
for i in range(self.max_iter):
#1、计算距离矩阵,得到一个100*6的矩阵
distance = cdist(data,self.centroids)
#2、对距离按照从今到远排序,选取最近的质心点的类别,作为当前点的分类
c_ind = np.argmin(distance,axis=1)
#3、对每一类数据进行均值计算,更新质心点坐标
for i in range(self.n_clusters):
#首先排除掉没有出现在c_ind里的类别
if i in c_ind:
#选出所哟u类别时i的点,取data里面坐标的均值,更新第i个质心
self.centroids[i] = np.mean(data[c_ind==i],axis=0)
#实现预测方法
def predict(self,sample):
#先计算距离矩阵,然后选取距离质心最近的那个质心的类别
distance = cdist(sample, self.centroids)
c_ind = np.argmin(distance, axis=1)
return c_ind
dist = np.array([[121,221,32,43],
[121,1,12,23],
[65,21,2,43],
[1,321,32,43],
[21,11,22,3]])
c_ind = np.argmin(dist, axis=1)
print(c_ind)
x_new=x[0:5]
print(x_new)
print(c_ind==2)
print(x_new[c_ind==2])
np.mean(x_new[c_ind==2],axis=0)
#测试
#定义一个绘制子图函数
def plotKmeans(x,y,centroids,subplot,title):
#分配子图,121表示1行2列的子图中的第一个
plt.subplot(subplot)
plt.scatter(x[:,0],x[:,1],c='r')
#画出质心点
plt.scatter(centroids[:,0],centroids[:,1],c=np.array(range(6)),s=100)
plt.title(title)
kmeans = K_Means(max_iter=300,centroids=np.array([[2,1],[2,2],[2,3],[2,4],[2,5],[2,6]]))
plt.figure(figsize=(16,6))
plotKmeans(x,y,kmeans.centroids,121,'Inital State')
#开始聚类
kmeans.fit(x)
plotKmeans(x,y,kmeans.centroids, 122, 'Final State')
#预测新数据点的类别
x_new = np.array([[0,0],[10,7]])
y_pred = kmeans.predict(x_new)
print(kmeans.centroids)
print(y_pred)
plt.scatter(x_new[:,0],x_new[:,1], c='black')
plt.show()
- 初始和最终预测散点图展示:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/ee013810ba8062a1c9e8671bf38dc6aa.png#pic_center)