机器学习:Kmeans练习

实验介绍

1.实验内容

  • 通过对给定数据进行聚类分析来了解K-means算法。

2.实验目标

  • 通过本实验掌握K-means聚类算法

3.实验知识点

  • K-means算法原理
  • K-means算法流程
  • K-means算法应用

4.实验环境

  • python 3.6.5
  • numpy 1.13.3
  • matplotlib 2.2.3

实验准备

点击屏幕右上方的下载实验数据模块,选择下载KmeansData.txt到指定目录下,然后再依次选择点击上方的File->Open->Upload,上传刚才下载的数据集

数据介绍

本数据是随机生成的符合高斯分布的二维样本点

[K-means] 实验流程

import numpy as np
import matplotlib.pyplot as plt

1. 数据的读取与处理

def loadDataSet(fileName):
    #初始化空列表
    dataSet = []
    #读取文件
    fr = open(fileName)
    # 循环遍历文件所有行
    for line in fr.readlines():
        # 切割每一行的数据
        curLine = line.strip().split('\t')
        # 将数据转换为浮点类型,便于后面的计算
        # fltLine = [float(x) for x in curLine]
        # 将数据追加到dataMat
        fltLine = list(map(float,curLine))    # 映射所有的元素为 float(浮点数)类型
        dataSet.append(fltLine)
    # 返回dataMat
    return np.matrix(dataSet)

2. 样本点间的距离计算

def distEclud(vecA, vecB):
    return np.sqrt(sum(np.power(vecA - vecB, 2)))
    """
    函数说明:利用欧式距离来计算每个样本点之间的距离
    parameters:
        vecA - A样本的特征向量(本数据中指它的二维坐标值)
        vecB - B样本的特征向量(本数据中指它的二维坐标值)  
    return:
        Dist - 样本点间的欧式距离
    """ 

3. 簇中心的初始化

def randCent(DataMat, k):
    """
    函数说明:从当前样本点中随机选取k个初始簇中心
    parameters:
         DataMat - 数据集
         k - 聚类后簇的数量
    return:
        centroids - 簇中心列表
    """    
    # 获取样本数与特征值
    m, n = np.shape(dataMat)
    # 初始化质心,创建(k,n)个以零填充的矩阵
    centroids = np.mat(np.zeros((k, n)))
    # 循环遍历特征值
    for j in range(n):
        # 计算每一列的最小值
        minJ = min(dataMat[:, j])
        # 计算每一列的范围值
        rangeJ = float(max(dataMat[:, j]) - minJ)
        # 计算每一列的质心,并将值赋给centroids
        centroids[:, j] = np.mat(minJ + rangeJ * np.random.rand(k, 1))
    # 返回质心
    return centroids

4. K-means的中心思想实现---即通过不断更新簇中心,把与各个簇中心距离相近的样本点归为一类

def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):
    """
    函数说明:K-均值算法
    parameters:
         dataSet -数据集
         k -簇个数
         distMeas -距离计算函数
         createCent -创建初始质心函数
    return:
         centroids -质心列表
         clusterAssment -簇分配结果矩阵
    """   
    # 获取样本数和特征数
    m, n = np.shape(dataMat)
    # 初始化一个矩阵来存储每个点的簇分配结果
    # clusterAssment包含两个列:一列记录簇索引值,第二列存储误差(误差是指当前点到簇质心的距离,后面会使用该误差来评价聚类的效果)
    clusterAssment = np.mat(np.zeros((m, 2)))
    # 创建质心,随机K个质心
    centroids = createCent(dataMat, k)
    # 初始化标志变量,用于判断迭代是否继续,如果True,则继续迭代
    clusterChanged = True
    while clusterChanged:
        clusterChanged = False
        # 遍历所有数据找到距离每个点最近的质心,
        # 可以通过对每个点遍历所有质心并计算点到每个质心的距离来完成
        for i in range(m):
            minDist = np.inf
            minIndex = -1
            for j in range(k):
                # 计算数据点到质心的距离
                # 计算距离是使用distMeas参数给出的距离公式,默认距离函数是distEclud
                distJI = distMeas(centroids[j, :], dataMat[i, :])
                # 如果距离比minDist(最小距离)还小,更新minDist(最小距离)和最小质心的index(索引)
                if distJI < minDist:
                    minDist = distJI
                    minIndex = j
            # 如果任一点的簇分配结果发生改变,则更新clusterChanged标志
            if clusterAssment[i, 0] != minIndex: clusterChanged = True
            # 更新簇分配结果为最小质心的index(索引),minDist(最小距离)的平方
            clusterAssment[i, :] = minIndex, minDist ** 2
        # print(centroids)
        # 遍历所有质心并更新它们的取值
        for cent in range(k):
            # 通过数据过滤来获得给定簇的所有点
            ptsInClust = dataMat[np.nonzero(clusterAssment[:, 0].A == cent)[0]]
            # 计算所有点的均值,axis=0表示沿矩阵的列方向进行均值计算
            centroids[cent, :] = np.mean(ptsInClust, axis=0)
    # 返回所有的类质心与点分配结果
    return centroids, clusterAssment

5. 实验结果的可视化

def drawDataSet(dataMat, centList, clusterAssment, k):
    """
    函数说明:将聚类结果可视化
    parameters:
        centList -质心列表
        clusterAssment -簇列表
        dataMat -数据集
        k -簇个数
    return:
        A picture
    """
    m, n = np.shape(dataMat)
    
    # 创建一个画布
    plt.figure()
    
    # 用不同的颜色绘制不同簇的点
    for i in range(k):
        # 找到属于第i簇的数据点
        ptsInClust = dataMat[np.nonzero(clusterAssment[:, 0].A == i)[0]]
        
        # 使用不同颜色绘制每个簇的数据点
        plt.scatter(ptsInClust[:, 0].A[:, 0], ptsInClust[:, 1].A[:, 0], label=f'Cluster {i+1}')
    
    # 绘制质心的位置
    centroids = np.array(centList)
    plt.scatter(centroids[:, 0], centroids[:, 1], marker='x', s=150, color='black', label='Centroids')
    
    # 添加图例
    plt.legend()
    
    # 添加标题和轴标签
    plt.title(f'K-Means Clustering with {k} Clusters')
    plt.xlabel('Feature 1')
    plt.ylabel('Feature 2')
    
    # 显示图像
    plt.show()

6. 主函数调用上述函数

if __name__ == '__main__':
    # 载入数据集
    fileName = 'KmeansData.txt'
    dataMat = loadDataSet(fileName)
    
    # 设置簇的数量 k
    k = 3  # 假设我们希望聚成 3 个簇
    
    # 执行K-Means聚类
    centroids, clusterAssment = kMeans(dataMat, k)
    
    # 可视化聚类结果
    drawDataSet(dataMat, centroids, clusterAssment, k)

output_26_0

posted @   hjdssj  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示