房山公务员助力 2018-06-28 10:35 采纳率: 0%
浏览 1562
已结题

使用Python实现K均值聚类算法使用什么变成思想

请问大神,使用Python实现K均值聚类算法,使用面向对象和面向过程,
这两种设计思想的区别,和优劣是什么,是结合这个具体的实现算法谈一下,

  • 写回答

3条回答

  • threenewbee 2018-06-28 15:27
    关注

    如果你去看python的数学函数库,比如numpy pandas scipy 等等,很少有用到面向对象的,而这些库都是很知名的,具有影响力的库。成熟并且大量使用。

    你要搞明白一个问题,就是使用python进行科学运算和统计优化的都是领域专家而不是职业程序员,他们需要的是简单高效的调用,而不是学院派的“面向对象”,也许专业开发者认为面向对象有利于编写那种健壮强大易于维护的软件,但是这些对于科学运算和数据处理没有什么实际用处。

    如果你非要结合程序来讨论,我们就看一个这样的程序:

     import numpy
    import random
    import codecs
    import copy
    import re
    import matplotlib.pyplot as plt
    
    def calcuDistance(vec1, vec2):
        # 计算向量vec1和向量vec2之间的欧氏距离
        return numpy.sqrt(numpy.sum(numpy.square(vec1 - vec2)))
    
    def loadDataSet(inFile):
        # 载入数据测试数据集
        # 数据由文本保存,为二维坐标
        inDate = codecs.open(inFile, 'r', 'utf-8').readlines()
        dataSet = list()
        for line in inDate:
            line = line.strip()
            strList = re.split('[ ]+', line)  # 去除多余的空格
            # print strList[0], strList[1]
            numList = list()
            for item in strList:
                num = float(item)
                numList.append(num)
                # print numList
            dataSet.append(numList)
    
        return dataSet      # dataSet = [[], [], [], ...]
    
    def initCentroids(dataSet, k):
        # 初始化k个质心,随机获取
        return random.sample(dataSet, k)  # 从dataSet中随机获取k个数据项返回
    
    def minDistance(dataSet, centroidList):
        # 对每个属于dataSet的item,计算item与centroidList中k个质心的欧式距离,找出距离最小的,
        # 并将item加入相应的簇类中
    
        clusterDict = dict()                 # 用dict来保存簇类结果
        for item in dataSet:
            vec1 = numpy.array(item)         # 转换成array形式
            flag = 0                         # 簇分类标记,记录与相应簇距离最近的那个簇
            minDis = float("inf")            # 初始化为最大值
    
            for i in range(len(centroidList)):
                vec2 = numpy.array(centroidList[i])
                distance = calcuDistance(vec1, vec2)  # 计算相应的欧式距离
                if distance < minDis:    
                    minDis = distance
                    flag = i                          # 循环结束时,flag保存的是与当前item距离最近的那个簇标记
    
            if flag not in clusterDict.keys():   # 簇标记不存在,进行初始化
                clusterDict[flag] = list()
            # print flag, item
            clusterDict[flag].append(item)       # 加入相应的类别中
    
        return clusterDict                       # 返回新的聚类结果
    
    def getCentroids(clusterDict):
        # 得到k个质心
        centroidList = list()
        for key in clusterDict.keys():
            centroid = numpy.mean(numpy.array(clusterDict[key]), axis = 0)  # 计算每列的均值,即找到质心
            # print key, centroid
            centroidList.append(centroid)
    
        return numpy.array(centroidList).tolist()
    
    def getVar(clusterDict, centroidList):
        # 计算簇集合间的均方误差
        # 将簇类中各个向量与质心的距离进行累加求和
    
        sum = 0.0
        for key in clusterDict.keys():
            vec1 = numpy.array(centroidList[key])
            distance = 0.0
            for item in clusterDict[key]:
                vec2 = numpy.array(item)
                distance += calcuDistance(vec1, vec2)
            sum += distance
    
        return sum
    
    def showCluster(centroidList, clusterDict):
        # 展示聚类结果
    
        colorMark = ['or', 'ob', 'og', 'ok', 'oy', 'ow']      # 不同簇类的标记 'or' --> 'o'代表圆,'r'代表red,'b':blue
        centroidMark = ['dr', 'db', 'dg', 'dk', 'dy', 'dw']   # 质心标记 同上'd'代表棱形
        for key in clusterDict.keys():
            plt.plot(centroidList[key][0], centroidList[key][1], centroidMark[key], markersize = 12)  # 画质心点
            for item in clusterDict[key]:
                plt.plot(item[0], item[1], colorMark[key]) # 画簇类下的点
    
        plt.show()
    
    if __name__ == '__main__':
    
        inFile = "D:/ML/clustering/testSet.txt"            # 数据集文件 
        dataSet = loadDataSet(inFile)                      # 载入数据集
        centroidList = initCentroids(dataSet, 4)           # 初始化质心,设置k=4
        clusterDict = minDistance(dataSet, centroidList)   # 第一次聚类迭代
        newVar = getVar(clusterDict, centroidList)         # 获得均方误差值,通过新旧均方误差来获得迭代终止条件
        oldVar = -0.0001                                   # 旧均方误差值初始化为-1
        print '***** 第1次迭代 *****'
        print 
        print '簇类'
        for key in clusterDict.keys():
            print key, ' --> ', clusterDict[key]
        print 'k个均值向量: ', centroidList
        print '平均均方误差: ', newVar
        print 
        showCluster(centroidList, clusterDict)             # 展示聚类结果
    
        k = 2
        while abs(newVar - oldVar) >= 0.0001:              # 当连续两次聚类结果小于0.0001时,迭代结束          
            centroidList = getCentroids(clusterDict)          # 获得新的质心
            clusterDict = minDistance(dataSet, centroidList)  # 新的聚类结果
            oldVar = newVar                                   
            newVar = getVar(clusterDict, centroidList)
    
            print '***** 第%d次迭代 *****' % k
            print 
            print '簇类'
            for key in clusterDict.keys():
                print key, ' --> ', clusterDict[key]
            print 'k个均值向量: ', centroidList
            print '平均均方误差: ', newVar
            print
            showCluster(centroidList, clusterDict)            # 展示聚类结果
    
            k += 
    

    数据载入、运算、显示结果清清楚楚,你告诉我面向对象你打算怎么面向?

    评论

报告相同问题?

悬赏问题

  • ¥15 oracle集群安装出bug
  • ¥15 关于#python#的问题:自动化测试
  • ¥20 问题请教!vue项目关于Nginx配置nonce安全策略的问题
  • ¥15 教务系统账号被盗号如何追溯设备
  • ¥20 delta降尺度方法,未来数据怎么降尺度
  • ¥15 c# 使用NPOI快速将datatable数据导入excel中指定sheet,要求快速高效
  • ¥15 再不同版本的系统上,TCP传输速度不一致
  • ¥15 高德地图点聚合中Marker的位置无法实时更新
  • ¥15 DIFY API Endpoint 问题。
  • ¥20 sub地址DHCP问题