当前位置: 首页 > article >正文

大数据-213 数据挖掘 机器学习理论 - KMeans Python 实现 距离计算函数 质心函数 聚类函数

点一下关注吧!!!非常感谢!!持续更新!!!

目前已经更新到了:

  • Hadoop(已更完)
  • HDFS(已更完)
  • MapReduce(已更完)
  • Hive(已更完)
  • Flume(已更完)
  • Sqoop(已更完)
  • Zookeeper(已更完)
  • HBase(已更完)
  • Redis (已更完)
  • Kafka(已更完)
  • Spark(已更完)
  • Flink(已更完)
  • ClickHouse(已更完)
  • Kudu(已更完)
  • Druid(已更完)
  • Kylin(已更完)
  • Elasticsearch(已更完)
  • DataX(已更完)
  • Tez(已更完)
  • 数据挖掘(正在更新…)

章节内容

上节我们完成了如下的内容:

  • 无监督学习算法
  • KMeans 基本原理
  • KMeans 簇内误差平方和

在这里插入图片描述

Python实现

导入依赖

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
# 解决坐标轴刻度负号乱码
plt.rcParams['axes.unicode_minus'] = False
# 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['Simhei']

导入数据集

此处使用鸢尾花数据集为例:

import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline
#导入数据集
iris = pd.read_csv("iris.txt",header = None)
iris.head()
iris.shape

执行结果如下图所示:
在这里插入图片描述

编写距离计算函数

我们需要定义一个两个长度相等的数组之间欧式距离计算函数,在不直接应用计算结果,只比较距离远近的情况下,我们可以用距离平方和代替距离进行比较,化简开平方运算,从而减少函数计算量。此外需要说明的是,涉及到距离计算的,一定要注意量纲的统一。
如果量纲不统一的话,模型极易偏向量纲大的那一方。

  • 函数功能:计算两个数据集之间的欧式距离
  • 输入:两个 array 数据集
  • 返回:两个数据集之间的欧式距离(此处用距离平方和代替距离)
def distEclud(arrA, arrB):
    d = arrA - arrB
    dist = np.sum(np.power(d, 2), axis=1)
    return dist

编写随机函数生成质心函数

在定义随机质心生成函数时,首先需要计算每列数值的范围,然后从该范围中随机生成指定个数的质心。

  • 函数功能:随机生成 k 个质心
  • 参数说明:dataSet 包含标签的数据集,k 是簇的个数,返回 data_cent 是 k 个质心
def randCent(dataSet, k):
    # n为列数,假设dataSet是一个DataFrame
    n = dataSet.shape[1]  # 获取数据集的列数(例如 iris 数据集有 5 列)
    
    # 获取每一列的最小值和最大值(仅使用前 n-1 列,最后一列是标签或类别)
    data_min = dataSet.iloc[:, :n-1].min()  # 前4列的最小值
    data_max = dataSet.iloc[:, :n-1].max()  # 前4列的最大值
    
    # 在最小值和最大值之间生成 k 个随机中心点,形状为 (k, n-1)
    data_cent = np.random.uniform(data_min, data_max, (k, n-1))
    
    return data_cent

经过上述定义,在 iris 中随机生成了三个质心:
执行对应的代码:

iris_cent = randCent(iris, 3)
iris_cent

执行结果如下图所示:
在这里插入图片描述

编写 K-Means 聚类函数

在执行 K-Means 的时候,需要不断的迭代质心,因此我们需要两个可迭代的容器来完成该目标:

  • 第一个容器用于存放和更新质心,该容器可考虑使用 list 来执行,list 不仅是可迭代对象,同时 list 内不同元素索引位置也可以用于标记和区分各质心,即各簇的编号:即代码中的 centroids。
  • 第二个容器则需要记录,保存和更新到各点到质心之间的距离,并能够方便对其进行比较,该容器考虑使用一个三列的数组来执行。

第二个容器中:

  • 第一列用于存放最近一次计算完成后某点到各质心的最短距离
  • 第二列用于记录最近一次计算完成后根据最短距离得到的代表对应质心的数值索引,即所述簇,即质心编号。
  • 第三列用于存放上一次某点对应质心编号(某点所属簇),后两列用于比较质心发生变化后某点所属簇的情况是否发生变化。

函数功能:K-均值聚类算法
参数说明:

  • dataSet 带标签数据集
  • k 簇的个数
  • distMeas 距离计算函数
  • createCent 随机质心生成函数

返回:

  • centroids 质心
  • result_set 所有数据划分结果
# 假设 distEclud 和 randCent 是你定义的距离测量函数和随机生成质心函数
def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):
    # 获取数据集的维度,m 是行数,n 是列数
    m, n = dataSet.shape  # m是行数(数据量),n是列数(例如 iris 为 150*5)

    # 初始化质心 centroids,生成 k 个随机质心
    centroids = createCent(dataSet, k)  # centroids 为 k*n 的矩阵(随机生成)

    # 初始化 clusterAssment 矩阵,用来存储每个点的簇分配结果
    # clusterAssment: [该行到最近质心的距离, 本次迭代中最近质心编号, 上次迭代中最近质心编号]
    clusterAssment = np.zeros((m, 3))  # 初始化为 m*3 的矩阵
    clusterAssment[:, 0] = np.inf  # 设置初始距离为无穷大
    clusterAssment[:, 1:3] = -1  # 质心编号初始化为 -1

    # 将数据集和 clusterAssment 合并,形成 result_set
    result_set = pd.concat([dataSet, pd.DataFrame(clusterAssment)], axis=1, ignore_index=True)

    # 标记簇是否发生变化
    clusterChanged = True

    while clusterChanged:
        clusterChanged = False
        # 遍历每个样本点,计算它与每个质心的距离,并更新簇分配信息
        for i in range(m):
            # 计算当前数据点到所有质心的距离
            dist = distMeas(dataSet.iloc[i, :n-1].values, centroids)  # 计算距离,dist 是 k*1 的矩阵
            # 记录最小距离和对应质心的索引
            result_set.iloc[i, n] = dist.min()  # 记录最小距离
            result_set.iloc[i, n+1] = np.where(dist == dist.min())[0][0]  # 记录最近质心的索引

        # 检查当前簇分配与上次是否完全一致
        clusterChanged = not (result_set.iloc[:, -1] == result_set.iloc[:, -2]).all()

        # 如果簇分配发生变化,则更新质心和 result_set
        if clusterChanged:
            # 根据新的簇分配,计算新的质心位置
            cent_df = result_set.groupby(n+1).mean()  # 根据最新簇分配,分组计算新的质心
            centroids = cent_df.iloc[:, :n-1].values  # 更新质心,使用新的均值作为质心

            # 更新簇分配编码,将当前簇分配替换为上次的簇分配
            result_set.iloc[:, -1] = result_set.iloc[:, -2]

    return centroids, result_set

将鸢尾花数据带进去,查看模型的效果:

iris_cent,iris_result = kMeans(iris, 3)
iris_cent
iris_result.head()

执行结果若下所示:
在这里插入图片描述
有几点需要特别注意:

  • 设置统一的操作对象 result_set,为了调用和使用的方便,这里将 clusterAssment 转换为了 DataFrame 并与输入 DataFrame 合并,组成的对象作为后续调用的统一对象,该对象内即保存了原始数据,也保存了迭代运算的中间结果,包括数据所属簇标记和数据质心距离等,该对象同时也作为最终函数的返回结果
  • 判断质心是否发生改变条件,在K-Means 中判断质心是否发生改变,即判断是否继续进行下一步迭代的依据并不是某点距离新的质心距离变短,而是某点新的距离向量(到各质心的距离)中最短的分量位置是否发生变化,即质心变化后某点是否应归属另外的簇,在质心变化导致各点所属簇发生变化的过程中,点到质心的距离不一定会变短,即判断条件不能用下述语句表示
  • 质心和类别一一对应,在最后生成的结果中,centroids的行标为 result_set 中各点所属类别

http://www.kler.cn/a/386335.html

相关文章:

  • ABAP关于PS模块CJ20N中项目物料的屏幕和字段增强CI_RSADD
  • LaTeX之四:如何兼容中文(上手中文简历和中文论文)、在win/mac上安装新字体。
  • 使用Python实现对接Hadoop集群(通过Hive)并提供API接口
  • arcgis做buffer
  • 使用 unicorn 和 capstone 库来模拟 ARM Thumb 指令的执行(一)
  • 贪心算法day03(最长递增序列问题)
  • Python使用PDF相关组件案例详解
  • 从截图到代码:screenshot-to-code开源项目实践指南
  • 内网项目,maven本地仓库离线打包,解决Cannot access central in offline mode?
  • spring boot 统一异常处理
  • 大模型学习笔记------CLIP模型解读与思考
  • Redis-07 Redis哨兵
  • 2025斯诺克器材与用品展,2025郑州台球器材展会3月举办
  • 如何利用内部开源加速创新
  • SAP_MM负库存简介
  • 基于Spring Boot的网上商品订单转手系统设计与实现,LW+源码+讲解
  • Webserver(5.2)网页服务器框架
  • Chromium127编译指南 Linux篇 - 获取Chromium源码(四)
  • 【前端】Svelte:匿名插槽与具名插槽
  • 深度学习:BERT 详解
  • Flink API 的层次结构
  • 机器学习—神经网络如何高效实现
  • 数据采集器与物联网网关的区别
  • 基于Springboot+Vue的游乐园管理系统 (含源码数据库)
  • C#(asp.net)民宿客房管理系统-计算机设计毕业源码76233
  • SCI论文数据可视化的在线网址