233 test

# rand.py
import random

f = open('Dataset.txt', "w")
for i in range(1, 500):
    a = random.randint(0, 1000000)
    a = a / 20000
    b = random.randint(0, 1000000)
    b = b / 20000
    f.write(str(a) + "\t" + str(b) + "\n")
    print(str(a) + "\t" + str(b) + "\n")
f.close()

kmeans.py
# -*- coding: utf-8 -*-
from numpy import *
import matplotlib.pyplot as plt

"""
函数说明:加载数据集
parameters:
    fileName -文件名
return:
    dataMat -数据列表
"""


def loadDataSet(fileName):
    dataMat = []
    fr = open(fileName)
    for line in fr.readlines():
        curLine = line.strip().split('\t')
        fltLine = list(map(float, curLine))  # 将数据转换为float型数据
        dataMat.append(fltLine)
    return dataMat


"""
函数说明:计算向量欧氏距离
parameters:
    vecA -向量A
    vecB -向量B
return:
    欧氏距离
"""


def distEclud(vecA, vecB):
    return sqrt(sum(power(vecA - vecB, 2)))  # 此处也可以使用其他距离计算公式


"""
函数说明:为给定数据集构建一个包含k个随机质心的集合
parameters:
    dataSet -数据集
    k -质心个数
return:
    centroids -质心列表
"""


def randCent(dataSet, k):
    n = shape(dataSet)[1]
    centroids = mat(zeros((k, n)))  # 创建存储质心的矩阵,初始化为0
    for j in range(n):  # 随机质心必须再整个数据集的边界之内
        minJ = min(dataSet[:, j])
        rangeJ = float(max(dataSet[:, j]) - minJ)  # 通过找到数据集每一维的最小和最大值
        centroids[:, j] = mat(minJ + rangeJ * random.rand(k, 1))  # 生成0到1之间的随机数,确保质心落在边界之内
    return centroids


"""
函数说明:K-均值算法
parameters:
    dataSet -数据集
    k -簇个数
    distMeas -距离计算函数
    createCent -创建初始质心函数
return:
    centroids -质心列表
    clusterAssment -簇分配结果矩阵
"""


def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):
    m = shape(dataSet)[0]  # 确定数据集中数据点的总数
    clusterAssment = mat(zeros((m, 2)))  # 创建矩阵来存储每个点的簇分配结果
    # 第一列记录簇索引值,第二列存储误差
    centroids = createCent(dataSet, k)  # 创建初始质心
    clusterChanged = True  # 标志变量,若为True,则继续迭代
    while clusterChanged:
        clusterChanged = False
        for i in range(m):  # 遍历所有数据找到距离每个点最近的质心
            minDist = 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[nonzero(clusterAssment[:, 0].A == cent)[0]]  # 得到该簇中所有点的值
            centroids[cent, :] = mean(ptsInClust, axis=0)  # 计算所有点的均值并更新为质心
    return centroids, clusterAssment


"""
函数说明:绘图
parameters:
    centList -质心列表
    myNewAssments -簇列表
    dataMat -数据集
    k -簇个数
return:
    null
"""


def drawDataSet(dataMat, centList, myNewAssments, k):
    fig = plt.figure()
    rect = [0.1, 0.1, 0.8, 0.8]  # 绘制矩形
    scatterMarkers = ['s', 'o', '^', '8', 'p', 'd', 'v', 'h', '>', '<']  # 构建标记形状的列表用于绘制散点图
    ax1 = fig.add_axes(rect, label='ax1', frameon=False)
    for i in range(k):  # 遍历每个簇
        ptsInCurrCluster = dataMat[nonzero(myNewAssments[:, 0].A == i)[0], :]
        markerStyle = scatterMarkers[i % len(scatterMarkers)]  # 使用索引来选择标记形状
        ax1.scatter(ptsInCurrCluster[:, 0].flatten().A[0], ptsInCurrCluster[:, 1].flatten().A[0], marker=markerStyle,
                    s=90)
    ax1.scatter(centList[:, 0].flatten().A[0], centList[:, 1].flatten().A[0], marker='+', s=300)  # 使用"+"来标记质心
    plt.show()


if __name__ == '__main__':
    size = 4
    dataMat = mat(loadDataSet('Dataset.txt'))
    centList, myNewAssments = kMeans(dataMat, size)
    print(centList)
    drawDataSet(dataMat, centList, myNewAssments, size)

猜你喜欢

转载自blog.csdn.net/BING1926/article/details/89704502
233
今日推荐