KMeans算法(使用numpy)——python

最近学习了numpy库,对之前的KMeans算法进行了一个改进。

import random
import copy
import matplotlib.pyplot as plt
import numpy as np
import time
# 该写法只在计算使用numpy,其余使用列表
class KMeans():
    def __init__(self,data,k=1):
        # 可以传入ndarry类型
        self.__data = data  # 存放输入点数据
        self.__k = k  # 中心点个数
        # 可以改为ndarry类型
        self.__centerPoint = []  # 中心点
        self.__result = []  # 对输入点进行分类的结果
        for i in range(k):
            self.__result.append([])   #[[] [] [] [] [] ]

    # 随机取k个中心点
    def randomCenterPoint(self):
        for i in range(self.__k):
            # 随机出k个下标
            index = random.randint(0,len(self.__data)-1)
            # 判断取出的数是否在中心点中  防止取重复数  使中心点重复
            # 不使用ndarry类型,因为tnp.append添加数据特别耗时间
            if self.__data[index] not in self.__centerPoint:
                self.__centerPoint.append(self.__data[index])
        pass

    # 把数据进行分类 计算各点到中心点的距离
    # data为点数据
    # center为中心点
    def calCenterPointDistance(self, data, center):
        centerDistance = []  # 用来记录每个点到k个中心点的距离[[k个数][k个数][k个数][k个数]...]长度为len(data)
        # 计算并存储各点到中心点距离
        center = np.array(center)
        data = np.array(data)
        for temp in data:
            centerDistance.append((np.sum((center-temp)**2,axis = 1)**0.5))
            pass

        self.__result = []
        # 因为对result进行的使append操作 及时清空 否则数据会堆积 越来越多
        # 对result清空操作
        for i in range(self.__k):
            self.__result.append([])
        m = 0
        # 根据各点到中心点距离  把数据点进行分类
        for temp in centerDistance:
            index = np.argmin(temp).tolist()
            self.__result[index].append(copy.deepcopy(data[m]))
            m += 1

    # 计算生成新的中心点
    def newCenterPoint(self, result):
        newCenterPoint = []  # 存放新的中心点
        # 转置矩阵  把各点x,y ,z...放在同一数组 方便计算
        for temp in result:
            temp = np.array(temp)
            temps = (np.sum(temp,axis=0)/len(temp)).tolist()
            newCenterPoint.append(copy.deepcopy(temps))
        return newCenterPoint

    #  计算新旧中心点之间的距离
    #  old代表原来的中心点列表  new新生成的中心点列表
    def calCenterPointToCenterPointDistance(self, old, new):
        old = np.array(old)
        new = np.array(new)
        res = np.sum((np.sum((new - old)**2,axis=1)**0.5))/len(old)
        return res  
        pass

    # 执行函数
    def fit(self, threshold):
        self.randomCenterPoint() # 随机中心点
        self.calCenterPointDistance(self.__data, self.__centerPoint)  # 把数据根据中心点分类
        newCenterPoint = self.newCenterPoint(self.__result)  # 生成新的中心点
        oldCenterPoint = self.__centerPoint  # 旧的中心点
        # 程序结束的条件
        while self.calCenterPointToCenterPointDistance(oldCenterPoint,newCenterPoint) > threshold:
            self.calCenterPointDistance(self.__data, newCenterPoint)  # 对data点数据进行新的分类
            oldCenterPoint = newCenterPoint  # 覆盖旧点
            newCenterPoint = self.newCenterPoint(self.__result)  # 生成新点

        self.__centerPoint = newCenterPoint
        return newCenterPoint, self.__result

if __name__ == "__main__":
    #  生成x个随机点
    a = time.time()
    data = [[random.randint(1, 100), random.randint(1, 100)]for i in range(10000)]
    km = KMeans(data, 6)
    center,result = km.fit(0.0001)

    # 数据可视化 可清楚看见点的分布情况
    plt.plot()
    plt.title("KMeans Classification")
    i = 0
    tempx = []
    tempy = []
    color = []
    for temp in result:
        temps = [[temp[x][i] for x in range(len(temp))] for i in range(len(temp[0]))]
        color += [i] * len(temps[0])
        tempx += temps[0]
        tempy += temps[1]
        i += 2
        pass
    plt.scatter(tempx, tempy, c=color, s=30)
    plt.show()
    b = time.time()
    print(b-a)

你可能感兴趣的:(KMeans算法(使用numpy)——python)