K-Means算法

K-Means算法简介:聚类是一种无监督的学习,即数据没有所属分类的标签,通过计算数据间的“距离”,将“距离”上靠近的一些数据划分为一类,这样就将无序的数据进行了分类,至于最后划分成几类,也就是K均值聚类算法中的K了。

K-Means的工作流程: 首先,随机选取K个点做为质心,第一次遍历整个数据集,计算每一条数据和K个质心的距离(每一条数据都要和k个质心计算一下距离,都计算完了找到距离最小的,记录该距离并把对应的是哪个质心记录下来,然后对下一条数据进行计算),第一次遍历结束所有数据都有了所属的分类,整个数据集被分为了K类。

然后更新质心,计算每个类里数据的平均值,以该值做为新的质心。

更新完所有的质心,重新遍历数据集,和第一次过程一样,不同的是找到最小距离后先比较一下和原来的类别是否一样,不一样的话记录距离和所属类别,然后因为分类有变化需要再次更新质心和进行下一轮的遍历,直到所有的质心都不再变化,即所有数据的分类都不再变化算法结束。

程序实现如下:

支持函数部分

def loadDataSet(fileName):

dataMat = []          //读取数据集

fr = open(fileName)

for line in fr.readlines():

    curLine = line.strip().split('\t')

    fltLine = list(map(float,curLine))

    dataMat.append(fltLine)

return dataMat

loadDataSet函数是读取数据集,数据是以txt文本格式保存的,每条数据的不同特征之间用空格分开,程序每次读取一行数据。
strip() 函数是除去每行开头或结尾指定的字符,默认是空格或换行符;

split() 是分割函数,以指定字符分割字符串,本程序是以空格将不同的特征分开;

map() 函数有两个参数,第一个是一个函数,第二个是待处理的数据,map将第二个参数提供的数据依次经过第一个函数处理,返回结果,本程序中是将得到的特征数据都转换为浮点型变量,每一行数据存为一个list,通过append函数(比较与extend函数的区别)将list加在dataMat中,得到可用的数据集。

append() 方法向列表的尾部添加一个新的元素
extend() 方法只接受一个列表作为参数,并将该参数的每个元素都添加到原有的列表中
如:mylist=[1,2,3] mylist.append([4,5,6])=[1,2,3,[4,5,6]] mylist.extend([4,5,6])=[1,2,3,4,5,6]

def disEclud(numA,numB):

return sqrt(sum(power(numA-numB,2)))

disEclud函数是计算距离的函数,两个n维的数据,对应位置相减计算平方和,再开根号可得到两点的距离。

def randCent(dataSet,k):

 n = shape(dataSet)[1]
 
centropoint = mat(zeros((k,n)))

for j in range(n):

    minj = min(dataSet[:,j])

    maxj = max(dataSet[:,j])

    rangej = float(maxj-minj)

    centropoint[:,j] = minj + rangej*random.rand(k,1)

return centropoint

randCent函数得到随机的K个初始质心,虽然说是随机的但是也是在一定范围的,范围就是保证每一维度得到的点都在整个数据集内部.

Shape()函数得到dataSet的行和列,[1]表示取列. shape函数是numpy.core.fromnumeric中的函数,它的功能是读取矩阵的长度,比如shape[0]就是读取矩阵第一维度的长度。它的输入参数可以使一个整数表示维度,也可以是一个矩阵。当输入是一个矩阵的时候就得到这个矩阵各个维度的长度。
zeros()先得到一个k行n列的值为零的数组.

mat()函数将数组转换为矩阵;找到数据集每一列的最小值和最大值,最大值减去最小值即数据的范围,最小值加一个变化范围乘以0到1的随机值就得到了在数据集范围内随机选出的质心。
1.mat()函数与array()函数生成矩阵所需的数据格式有区别:mat()函数中数据可以为字符串以分号(;)分割,或者为列表形式以逗号(,)分割。而array()函数中数据只能为逗号。
2.mat()函数与array()函数生成的矩阵计算方式不同。(1) mat()函数中矩阵的乘积可以使用 * 或 .dot()函数。矩阵对应位置元素相乘需调用numpy.multiply()函数。(2) array()函数中矩阵的乘积只能使用 .dot()函数。而星号乘 (*)则表示矩阵对应位置元素相乘,与numpy.multiply()函数结果相同。
随机生成的数组只有经mat()转换之后才能做一些线性操作。Python中的mat()函数

X[:,0]就是取矩阵X的所有行的第0列的元素,X[:,1] 就是取所有行的第1列的元素。

X[:, m:n]即取矩阵X的所有行中的的第m到n-1列数据,含左不含右。

X[0,:]就是取矩阵X的第0行的所有元素,X[1,:]取矩阵X的第一行的所有元素。Python中的矩阵表示

K均值算法实现:

def kMeans(dataSet,k,disMeans=disEclud,createCent=randCent):

    m = shape(dataSet)[0]         //读取dataSet的行数,即一共多少个点

    dataTag = mat(zeros(m,2))  //记录每个点前一次离那个质心最近,第一列是质心的下标,第二列是最小距离的平方

    centropoint = createCent(dataSet,k)//生成了k个质心

    flag = True //标记位 用来看分组是否发生变化,是否已经收敛

    while flag:

        flag = False

        for i in range(m):  //遍历总数据中的每个点

            minj = inf//表示无穷大量

            minindex = -1

            for j in range(k): //遍历每个质心

                distance =  dismeans(centropoint[j,:],dataSet[i,:]) //算出点到每个质心的距离

                if distance < minj: 更新最短距离和最近质点的下标

                    minj = distance 

                    minindex = j

                    if dataTag[i,0] != minindex:  如果上一次最近质点的下标与这次计算的不同

                        dataTag[i,:] = minindex,minj**2 //更新矩阵,第一列为最近质点下标,第二列为最短距离的平方

                        flag = True    //分组发生了变化,标记位记为True

      //print(centropoint)

        for n in range(k)://在while循环里 更新当前的质点

            dataSelect = dataSet[nonzero(dataTag[:,0].A==n)[0]]

            centropoint[k,:] = mean(dataSelect,axis=0)

    return centropoint,dataTag              

mean函数的使用方法:Python中的mean函数

对K均值算法的解析:

首先得到整个数据集的行数,定义一个m行2列的矩阵用来记录每条数据的分类信息和与质心的距离;然后调用函数生成k个随机质心,标志位位true,遍历整个数据集用minj和minindex记录最小的距离和所属分类,并且如果分类有变化标志位计为true,更新质心再次遍历数据集进行计算并分类;每一次遍历完数据集更新质心,更新质心关键的一句是

dataSelect = dataSet[nonzero(dataTag[:,0].A==n)[0]],nonzeros(a)返回数组a中值不为零的元素的下标,true不为零,false为零,所以通过这一句可以选出数据集中属于某一类的数据,然后计算筛选出数据的平均值,mean函数计算平均值,axis=0表示按列计算平均值,即每一个特征列计算其平均值,得到的就是该类数据的中心。最后返回更新的质心和每条数据所属的分类以及他们距离各自中心点的距离。

参考文章:
文本聚类算法之K-means算法的python实现
机器学习算法初识—K均值聚类算法(K-Means)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值