kmeans原理与实现

1 kmeans介绍

1.1 K-means的算法步骤

1.(随机)选择K个聚类的初始中心(质心);

2.对任意一个样本点,求其到K个聚类中心的距离,将样本点归类到距离最小的中心的聚类,如此迭代n次;

3.每次迭代过程中,利用均值等方法更新各个聚类的中心点(质心);

4.对K个聚类中心,利用2,3步迭代更新后,如果位置点变化很小(可以设置阈值),则认为达到稳定状态,迭代结束,对不同的聚类块和聚类中心可选择不同的颜色标注。

1.2 K-means++

目标:K-Means++算法就是对K-Means随机初始化质心的方法的优化

我们知道初始值的选取对结果的影响很大,对初始值选择的改进是很重要的一部分。在所有的改进算法中,K-means++ 最有名。

1、随机选取一个点作为第一个聚类中心。

2、计算所有样本与第一个聚类中心的距离。

3、选择出上一步中距离最大的点作为第二个聚类中心。

4、迭代:计算所有点到与之最近的聚类中心的距离,选取最大距离的点作为新的聚类中心。

5、终止条件:直到选出了这k个中心。

6、利用这k个质心来作为初始化质心去运行标准的K-Means算法

2 kmeans实现

2.1 引入依赖

import numpy as np
import matplotlib.pyplot as plt

# 从sklearn中直接生成聚类数据
from sklearn.datasets import make_blobs

2.2 数据加载

x, y = make_blobs( n_samples=100, centers=6, random_state=1234, cluster_std=0.6 )

plt.figure(figsize=(6,6))
plt.scatter(x[:,0], x[:,1], c=y)
plt.show()

在这里插入图片描述

2.3 算法实现

# 引入scipy中的距离函数,默认欧式距离
from scipy.spatial.distance import cdist

class K_Means(object):
    # 初始化,参数 n_clusters(K)、迭代次数max_iter、初始质心 centroids
    def __init__(self, n_clusters=5, 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的矩阵
            distances = cdist(data, self.centroids)
            
            # 2. 对距离按有近到远排序,选取最近的质心点的类别,作为当前点的分类
            c_ind = np.argmin( distances, axis=1 )
            
            # 3. 对每一类数据进行均值计算,更新质心点坐标
            for i in range(self.n_clusters):
                # 排除掉没有出现在c_ind里的类别
                if i in c_ind:
                    # 选出所有类别是i的点,取data里面坐标的均值,更新第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

2.4 测试

# 定义一个绘制子图函数
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(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' )

# 预测新数据点的类别
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], s=100, c='black')
[[ 5.76444812 -4.67941789]
 [-2.89174024 -0.22808556]
 [-5.89115978  2.33887408]
 [-2.8455246   5.87376915]
 [ 9.20551979  7.56124841]]
[1 4]

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值