Part3-Chpter10-利用k均值聚类算法对未标注数据分组(2)

本文档详细介绍了如何使用k均值聚类算法对未标注数据进行分组。作者通过对比自己编写的代码和书中示例代码,深入探讨了两种实现的异同,帮助读者更好地理解和掌握这一机器学习中的经典算法。
摘要由CSDN通过智能技术生成

前一节贴了我自己写的代码,写完后我又看了书上的代码,并将它复现了一遍。两个代码的思想基本一致,只在部分地方有所区别。

import numpy as np
import random

#载入数据
#filename:文件名
def loadDataSet(filename):
    dataMat = []
    fr = open(filename)
    for line in fr.readlines():
        curLine = line.strip().split('\t')
        fitLine = list(map(float,curLine))
        dataMat.append(fitLine)
    dataMat = np.mat(dataMat)
    return dataMat

#距离计算函数
#vecA,vecB:计算距离的两个行向量
#我的函数这里传递的是数据集和质点集以及对应的行,这里却直接传递了需要进行计算的向量
def distEclud(vecA,vecB):
    return np.sqrt(np.sum(np.power(vecA - vecB,2)))

#初始随机质点选择
#dataSet:数据集
#k:指定质点数
#我这里用的方法是初始化一个k行数据列数列的零矩阵,然后用random()乘以数据行数并向上取
#整(避免取到第0个),这样是使用数据点作为初始质点。书里的做法是计算出数据每一列的上下
#界,然后随机在这个界限内取值,作为初始质点。这总方法应该更好一点,因为选取的质点可能
#更加均匀,且在处理类别间数量差异大的数据时,效果会更好
def randCent(dataSet,k):
    n = np.shape(dataSet)[1]
    centroids = np.mat(np.zeros((k,n)))
    for j in range(n):
        minJ = np.min(dataSet[:,j])
        rangeJ = float(np.max(dataSet[:,j]) - minJ)
        centroids[:,j] = minJ + rangeJ * random.random()*k
    return centroids


#k-均值聚类函数
#dataSet:数据集
#distMeas:距离计算函数,默认使用平方差方法计算距离
#creatCent:初始质点创建函数,默认使用randCen()
def kMeans(dataSet,k,distMeas = distEclud,createCent = randCent):
    m = np.shape(dataSet)[0]
    #数据的类别及与所属类别的质点的距离矩阵。我是创建了一个新的m行(n+2)列矩阵,前n列是数
    #据,后2列和这个矩阵相同。我的方法大概更直观些,且可以少记一个变量名。这里的方法使程
    #序更简洁
    clusterAssment = np.mat(np.zeros((m,2)))
    #得到初始质点矩阵
    centroids = createCent(dataSet,k)
    #检查是否有数据点改变了类别
    clusterChanged = True
    while clusterChanged:
        clusterChanged = False
        for i in range(m):
            minDist = np.inf
            minIndex = -1
            for j in range(k):
                distJI = distMeas(centroids[j,:],dataSet[i,:])
                if distJI < minDist:
                    minDist = distJI
                    minIndex = j
            #若与该数据点距离最近的质点所属类别与该数据的类别不同,则更新标记置为真
            if clusterAssment[i,0] != minIndex: clusterChanged = True
            clusterAssment[i,:] = minIndex,minDist ** 2
        print (centroids)
        #将同一类别内的所有数据取平均作为新的质点数据。我这里是遍历数据,并记录类别内数据
        #数及数据之和,然后用前者除以后者,虽然结果也可以,但不如这里的方法的简洁和优雅
        for cent in range(k):
            ptsInClust = dataSet[np.nonzero(clusterAssment[:,0].A == cent)[0]]
            centroids[cent,:] = np.mean(ptsInClust,axis = 0)
    return centroids,clusterAssment

if __name__ == '__main__':
    dataMat = loadDataSet('testSet.txt')
    myCentroids,clustAssing = kMeans(dataMat,4)
    print(myCentroids,clustAssing)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值