【学习笔记】机器学习-K均值(k-means)

写在前面

对机器学习一直很有兴趣,这段时间一直在看这方面的资料,今天记录下自己对K-means算法的学习,主要是研究了下zouxy09大神的文章。文章中有不足不妥的地方欢迎提醒交流,多谢!

正式开始

关于k-means的理论知识,可以参考9神的文章,当然谷歌百度上也有很多。推荐都看看,集多家之所长,会让自己收获的更多。我这里就不再赘述了【懒癌一个】

执行流程

  • 确定分类簇数k,可通过查看散点分布

  • 随机选取质心点矩阵

  • 对数据集中每个点进行迭代,计算每个点与各质心点的距离,选取距离数据点最近的质心点簇作为自己的类簇

  • 直到数据集中所有数据点的类别不变为止

  • 可视化分类点

执行结果

数据集是引用9神文章中的测试数据

开始读取数据
绘制散点图

这里写图片描述

可以看出图片中的散点分布大致成4或则5类,这里我设置的类簇数为4。
以下是执行分类计算的代码执行结果

调用开始进行数据聚类
开始质心选取
初始化质点点完成

[[-1.786345 2.554248]
[ 3.367037 -3.184789]
[ 2.884105 3.043438]
[-3.284816 3.273099]]
开始分类
第1轮更新质点完成

[[-2.93239418 -0.59719121]
[ 2.21588922 -2.88365904]
[ 2.6265299 3.10868015]
[-3.29756333 2.80177833]]


第2轮更新质点完成

[[-3.4967025 -2.70989515]
[ 2.65077367 -2.79019029]
[ 2.6265299 3.10868015]
[-2.45009747 2.89275747]]


第3轮更新质点完成

[[-3.53973889 -2.89384326]
[ 2.65077367 -2.79019029]
[ 2.6265299 3.10868015]
[-2.46154315 2.78737555]]


第4轮更新质点完成

[[-3.53973889 -2.89384326]
[ 2.65077367 -2.79019029]
[ 2.6265299 3.10868015]
[-2.46154315 2.78737555]]


已完成数据分类
开始绘图

这里写图片描述

总共迭代了四轮,其实可以看出第四轮迭代后的质心矩阵与第三轮的质心矩阵一致,也就是实际上迭代了3轮,就已经分好类。看着结果还不错。

分类代码
以下是参考zouxy09大神的代码,我这里做了一些改动

# -*- coding:utf-8 -*-

from numpy import *
import matplotlib.pyplot as plt

class Kmeans():
    def __init__(self,dataSet,k):
        self.dataSet = dataSet
        self.k = k    #质点数
        self.numSamples = dataSet.shape[0]    #矩阵的行数
        self.dim = dataSet.shape[1]     #矩阵的列数
        self.signData  = mat(zeros((self.numSamples,2)))  #标签矩阵

#计算欧氏距离
    def euclDistance(self,vector1,vector2):
        return sqrt(sum(power(vector1 - vector2 ,2)))


    def dataCount(self):
        print u"开始质心选取"
        # centroids = zeros((self.k,self.dim))
        tem = [int(random.uniform(0,self.numSamples)) for i in xrange(self.k)]
        centroids = self.dataSet[tem]

        print u'初始化质点点完成\n'
        print centroids

        clusterChanged = True

        print u"开始分类"
        count = 0
        while clusterChanged:
            clusterChanged = False
            for i in xrange(self.numSamples):
                minDist = 1000000000
                index = 0

                for j in xrange(self.k):
                    distance = self.euclDistance(centroids[j,:],self.dataSet[i,:])
                    if distance < minDist:
                        minDist = distance
                        index = j

                #检查标签
                if self.signData[i,0] != index:
                    clusterChanged = True
                    self.signData[i,:] = index,minDist**2

            #更新质点
            for i in range(self.k):
                pointsInCluster = self.dataSet[nonzero(self.signData[:,0].A==i)[0]]
                centroids[i,:] = mean(pointsInCluster,axis=0)
            count +=1
            print u"第{}轮更新质点完成\n".format(count)
            print centroids
            print '*'*200  #分隔

        print u"已完成数据分类"

        print u'开始绘图'
        if self.dim !=2:
            print u"无法绘制2纬图"
            return 1
        mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']  #设置绘图颜色
        if k > len(mark):
            print u"选择的类别数太大,请重新确认类别数"
            return 1

        for i in xrange(self.numSamples):
            markIndex = int(self.signData[i,0])
            plt.plot(self.dataSet[i,0],self.dataSet[i,1],mark[markIndex])  #绘制分类图形

        mark = ['Dr', 'Db', 'Dg', 'Dk', '^b', '+b', 'sb', 'db', '<b', 'pb'] #设置质心绘图颜色
        for i in range(self.k):
            plt.plot(centroids[i,0],centroids[i,1],mark[i],markersize=12)

        plt.show()


if __name__=='__main__':

    print u'开始读取数据'
    dataSet = []
    with open('D:/datajl.txt') as files:
        for line in files.readlines():
            line = line.strip().split(',')
            # print line,type(line)
            dataSet.append([float(line[0]),float(line[1])])
    dataSet = mat(dataSet)

    print u'绘制散点图'
    for x in xrange(dataSet.shape[0]):
        plt.plot(dataSet[x,0],dataSet[x,1],'ob')
    plt.show()
    k = 4
    print u'开始进行数据聚类'
    Kmeans = Kmeans(dataSet,k)
    Kmeans.dataCount()

遇到的问题

  • 迭代计算中的时候总是报错,一轮都迭代不下去,核实了下代码,发现自己将记录标签的矩阵和质心矩阵弄混了,修改后,结果就能刷的一下出来了。

最后

任何算法都有其弊端,关于kmeans的缺点,还是参考zouxy09的文章吧,我就不误导了。

衷心感谢所有在互联网上分享自己技术文章的前辈们!

参考

最后希望对看到此处的你有所帮助【微笑】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值