机器学习——K均值算法(K-means)

一、K均值算法

1、引入

在这里插入图片描述

  • 如上图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()
  • 散点图展示
    在这里插入图片描述
#算法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表示12列的子图中的第一个
        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()
  • 初始和最终预测散点图展示:
    在这里插入图片描述
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值