kmeans聚类代码详解

kmeans聚类

keans算法主要是将所有点与质心算距离,与每个点距离最小的质心就是它的类别,然后再从每一类中选取平均值作为新的质心

#核心算法中的数据处理示例:
#假设五个点与四个之心距离分别如下:
dist = np.array([[112,324,532,32],
               [56,574,592,236],
               [13,34,57,32],
               [420,329,532,32],
               [112,324,52,32]])
#截取每一行的最小值
c_ind=np.argmin(dist,axis=1)
print(c_ind)
#打印类别是否是3
print(c_ind==3)
#打印类别为3的点
print(dist[c_ind==3])
#打印类别为3的新的质心
prin(np.mean(dist[c_ind==3],axis=0))

[3 0 0 3 3]
[ True False False True True]
[[112 324 532 32]
[420 329 532 32]
[112 324 52 32]]
array([214.66666667, 325.66666667, 372. , 32. ])

以下是详细代码:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets._samples_generator import make_blobs
#sklearn中的一种方法,直接生成聚类数据,有些版本的_samples_generator也写作samples_generator
###数据加载
x,y = make_blobs(n_samples = 100,centers=6,random_state=1234,cluster_std=0.6)
#生成100个样本点,六个中心点,随机种子任意设置,标准差0.6
#x极为坐标,y为类别
x.shape

(100, 2)

##画图
plt.figure(figsize=(6,6))
plt.scatter(x[:,0],x[:,1],c=y)#y不同,颜色不同
plt.show()

kmeans聚类代码详解_第1张图片

###算法实现
from scipy.spatial.distance import cdist
##默认欧氏距离
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,)):
            #random.randint随机出data的n_clusters个索引值,得到原始质心
            self.centroids = data[np.random.randint(0,data.shape[0],n_clusters),:]
            
        #开始迭代
        for i in range(self.max_iter):
            #计算距离矩阵
            distances = cdist(data,self.centroids)
            
            #对距离按远近排序,选取最近质心点的类别,作为当前点的分类
            #将distances这个(100,6)的矩阵截取为(100,1)的矩阵
            c_ind= np.argmin(distances,axis=1)
            
            #对每一类进行均值计算,更新质心点坐标
            for i in range(self.n_clusters):
                #排除掉没有出现在c_indt里的原始质心
                if i in c_ind:
                    #选相互所有类别值为i的点,更新坐标值
                    self.centroids[i] = np.mean(data[c_ind==i],axis=0)
                    
        #预测
    def predict(self,samples):
        #先计算距离矩阵,在选取距离最近的那个质心的类别
        distances=cdist(samples,self.centroids)
        c_ind = np.argmin(distances,axis=1)
        return c_ind
###测试
def plotKMeans(x,y,centroids,subplot,title):
    #分配子图
    plt.subplot(subplot)
    plt.scatter(x[:,0],x[:,1],c='r')
    #画出质心点
    plt.scatter(centroids[:,0],centroids[:,1],c=np.array(range(5)),s=100)
    plt.title(title)
    
kmeans=K_means(max_iter=300,centroids=np.array([[2,1],[2,2],[2,3],[2,4],[2,5]]))
plt.figure(figsize=(16,6))
plotKMeans(x,y,kmeans.centroids,121,'Initial State')
#开始聚类
kmeans.fit(x)
plotKMeans(x,y,kmeans.centroids,122,'Final State')

#打印当前质心
print(kmeans.centroids)

#预测新数据点类别
x_new= np.array([[0,0],[10,7]])
y_pred = kmeans.predict(x_new)
#打印两个点的分类
print(y_pred)
plt.scatter(x_new[:,0],x_new[:,1],s=100,c='black')

kmeans聚类代码详解_第2张图片

[[ 5.76444812 -4.67941789]
[-2.89174024 -0.22808556]
[-5.89115978 2.33887408]
[-2.8455246 5.87376915]
[ 9.20551979 7.56124841]]
[1 4]

由结果可知,[0,0],[10,7]两点分类的质心是[-2.89174024 -0.22808556]、 [ 9.20551979 7.56124841]

你可能感兴趣的:(python)