人工智能算法|K均值聚类算法Python实现

news2024/12/23 18:09:05

01、算法说明

K均值聚类算法是一种简单的迭代型聚类算法,采用距离作为相似性指标,从而发现给定数据集中的K个类,且每个类有一个聚类中心,即质心,每个类的质心是根据类中所有值的均值得到。对于给定的一个包含n个d维数据点的数据集X以及要分得的类别K,选取欧式距离作为相似度指标。聚类目标是使得各类的聚类平方和最小,即最小化:

K-means是一个反复迭代的过程,算法分为四个步骤:

(1)选取数据空间中的 K个对象作为初始中心,每个对象代表一个聚类中心;
(2)对于样本中的数据对象,根据它们与这些聚类中心的欧氏距离,按距离最近的准则将它们分到距离它们最近的聚类中心(最相似)所对应的类;
(3)更新聚类中心:将每个类别中所有对象所对应的均值作为该类别新的聚类中心,计算目标函数的值;
(4)判断聚类中心和目标函数的值是否发生改变,若不变,则输出结果,若改变,则返回步骤(2)。

02、程序实现

以下是K均值法的python代码实现。程序使用的工具包括numpy和matplotlib,其中numpy是一个用于处理多维数组的库,而Matplotlib 则用于绘制二维图形。

# -*- coding: UTF-8-*-
import numpy   #用于处理多维数组的库import random  #用于生成初始质心
import codecs   #用于读取数据集文本并且解码import re      #利用正则表达式来整理输入数据的格式import matplotlib.pyplot as plt #绘制二维图形的库


# 计算向量vec1和向量vec2之间的欧氏距离def calcuDistance(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 = [[], [], [], ...]

# 初始化k个质心,随机获取
def initCentroids(dataSet, 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  # 返回新的聚类结果


# 得到k个质心
def getCentroids(clusterDict):
    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:\Python\practice\kmean.txt"  # 数据集文件
    dataSet = loadDataSet(inFile)  #载入数据集
    centroidList = initCentroids(dataSet, 3)  #初始化质心,设置k=3
    clusterDict = minDistance(dataSet,centroidList)  # 第一次聚类迭代
    newVar = getVar(clusterDict, centroidList)  #获得均方误差值,通过新旧均方误差来获得迭代终止条件
    oldVar = -0.0001  #开始时均方误差值初始化为-0.0001
    print('***** 第1次迭代 *****')
    print()
    print('簇类')
    for key in clusterDict.keys():
        print(key, ' --> ', clusterDict[key])
    print('k个均值向量: ',centroidList)
    print('平均均方误差: ',newVar)
    print(showCluster(centroidList,clusterDict))  # 展示聚类结果

    j = 2  #
    while abs(newVar- oldVar) >= 0.0001:  # 当连续两次聚类结果小于0.0001时,迭代结束
        centroidList = getCentroids(clusterDict)  #获得新的质心
        clusterDict = minDistance(dataSet,centroidList)  # 新的聚类结果
        oldVar = newVar
        newVar = getVar(clusterDict,centroidList)

        print('***** 第%d次迭代 *****' % j)
        print()
        print('簇类')
        for key in clusterDict.keys():
            print(key, ' --> ', clusterDict[key])
        print('k个均值向量: ',centroidList)
        print('平均均方误差: ',newVar)

        print(showCluster(centroidList,clusterDict))         # 展示聚类结果

        j += 1

03、数据验证

现在假设有9个坐标点数据,它们分别是(3,2)、(3,9)(8,6)(9,5)(2,4)(3,10)(2,5)(9,6)(2,2)。利用上面的程序来计算它的簇,设定在计算开始时随机选择三个点作为初始质心,并且要求聚类结果必须小于0.0001。

程序运行的字符界面输出的结果如下图1和图2所示。

▍图1 程序运行的字符界面输出的结果

▍图2 程序运行的字符界面输出的结果(续)

程序调用python的绘图包输出图形界面的结果如下图3、图4和图5所示。从这几个图中可以看到簇类和簇心的变化。

图3展示的迭代开始时,随机选择的簇心。

▍图3 第一次迭代,随机选择的簇心

图4展示第二次迭代后,簇心发生变化,平均均方误差减小(从图2可以看出)。

▍图4 第二次迭代后,簇心发生的变化

图5展示第三次迭代后,簇心进一步发生变化,平均均方误差更小(从图2可以看出)。

▍图5 第三次迭代后,簇心进一步发生变化

从图2可以看出,第4次迭代与第三次迭代的结果是相同的,因此迭代4次后,程序终止执行。

04、程序说明

(1)在计算机安装了python之后,还需要安装numpy和matplotlib。这两个工具包分别是帮助进行科学运算并且根据计算结果绘制图的。

(2)安装完成后,可以根据实际情况改变数据集文件的地址,数据集是由loadDataSet这个函数进行数据的加载和整理的。本程序中main函数部分的语句:

dataset=loadDataSet(inFile)

就是完成这个功能。

(3)数据集加载完成后,由函数initCentroids来进行质心的初始化。在本程序中,使用了random函数来从数据集中随机抽取若干个质心,而质心的数量可以由第二个参数来设定。本程序设定的质心数量为3个。

(4)整理好的数据集和随机选取的质心会作为参数,交给函数minDistance进行聚类迭代计算。在这个计算里面,使用了定义的calcuDistance函数来计算点到点之间的欧式距离。

(5)最后利用上一步的结果,使用函数getVar来计算簇集合间的均方误差。

(6)控制迭代结束的条件是,在main函数中利用两次聚类的结果只差小于0.0001。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/535511.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Word怎么删除空白页?分享5个基础方法!

案例&#xff1a;Word怎么删除空白页 【我最近在用word写文章&#xff0c;但经常都会遇到的一个问题就是总是会有空白页&#xff0c;使用word时怎么删除空白页呢&#xff1f;请大家给我支支招吧&#xff01;】 在使用Microsoft Word编辑文档时&#xff0c;有时会出现空白页&a…

Stimulsoft 报表开发工具支持设置水印啦!一起来看~

Stimulsoft Reports是一款报告编写器&#xff0c;主要用于在桌面和Web上从头开始创建任何复杂的报告。可以在大多数平台上轻松实现部署&#xff0c;如ASP.NET, WinForms, .NET Core, JavaScript, WPF, Angular, Blazor, PHP, Java等&#xff0c;在你的应用程序中嵌入报告设计器…

AI智能机器人的语音消息使用方式

如何在没有资金扩大营销的情况下增加收入&#xff0c;这是不是有点像先有蛋还是先有鸡的问题&#xff1f;如果没有足够的收入来源&#xff0c;小型企业很难对新客源扩展营销和传播。有关系统问题欢迎和博主一起交流。 机器人的语音消息是不是给百姓造成了生活上的影响&#xf…

Redis内存优化——Stream类型介绍及底层原理详解

系列文章目录 Redis内存优化——String类型介绍及底层原理详解 Redis内存优化——Hash类型介绍及底层原理详解 Redis内存优化——List类型介绍及底层原理详解 Redis内存优化——Set类型介绍及底层原理详解 Redis内存优化——ZSet类型介绍及底层原理详解 Redis内存优化——Stre…

4 个无质量损失的免费在线图像压缩器

本文内容&#xff1a;最佳在线图像优化器&#xff0c;无质量损失&#xff0c;可让您压缩 JPG、PNG 和 GIF 文件。 在线图像优化器工具可帮助您压缩图像而不会降低质量。并给出图像可以压缩多少的想法。 经过测试和比较的没有质量损失的最佳在线图像优化器 4 个无质量损失的免…

网管必备技巧:如何跟踪IP地址

作为网管员&#xff0c;在我们解决Windows 操作系统的DHCP故障时&#xff0c;有时要找出某个地址范围内有哪些地址没有被使用。方法&#xff1a;打开命令提示窗口&#xff0c;在For…in…Do循环中调用ping命令。 例如&#xff0c;为了找出在地址范围192.168.1.1 到 192.168.1.1…

左耳朵耗子

晚上回来后&#xff0c;到coolshell上看文章。 程序员是一件非常累的工作&#xff0c;在我看到稚晖君做出那么多优秀的产品&#xff0c;我是很惊叹的&#xff0c;因为我知道那需要付出非常非常多的时间和精力&#xff0c;当大家都在夸赞的时候&#xff0c;我也能发现稚晖君发梢…

GitHub Copilot:神一样的代码助手

我肝肯定&#xff0c;很多很多小伙伴还不了解 Copilot 是什么&#xff0c;尤其是初学计算机的小伙伴&#xff0c;我这里普及一下吧&#xff01; GitHub Copilot 是一个基于 AI 的代码自动完成工具&#xff0c;由 GitHub 和 OpenAI 共同开发。 GitHub 和 OpenAI 想必大家都很清楚…

《计算机网络——自顶向下编程》精炼——3.4.4

人生的旅途,前途很远,也很暗,名言警句励志。然而不要怕,不怕的人的面前才有路。——鲁迅 文章目录 选择重传&#xff08;SR&#xff09; 选择重传&#xff08;SR&#xff09; 选择重传协议是另一种流水线rdt协议。与GBN协议最大的区别是当发送方收到一个失序分组时&#xff0c…

微信小程序实现人脸识别(戴面具效果)

节前准备:文档: xr-frame 模型链接 (注明&#xff1a;来源于微信开放文档) 基础要点: 1.ar-system"modes:Face;camera:Front" ar-system 表示ar系统&#xff0c;camera表示相机(默认为后置Back&#xff0c;前置为Front) modes 表示模式,目前支持平面识…

DSBC176 3BSE019216R1​有综合保护器、电流表、电压表等器件​

​ DSBC176 3BSE019216R1 有综合保护器、电流表、电压表等器件 另一个方法是先对数组排序&#xff0c;然后取中间元素即可&#xff0c;因为如果某个元素的个数超过一半&#xff0c;那么数组排序后该元素必定占据数组的中间位置。 求数组中元素的最短距离 给定一个含有n个元素…

大数据分析案例-基于GBDT梯度提升决策树算法构建数据科学岗位薪资预测模型

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

中小企业CRM如何选型?

中小企业CRM如何选型&#xff1f;这就来分享一下&#xff01; 中小企业客户关系管理系统(CRM)的选型需要考虑多个方面&#xff0c;包括成本&#xff0c;功能&#xff0c;易用性&#xff0c;扩展性和安全性。 预算&#xff1a;中小企业的预算通常有限&#xff0c;因此成本是选…

sudo unable to open read-only file system”的原因

此错误是由多种原因引起的&#xff0c;包括&#xff1a; 文件系统不一致。文件系统配置错误&#xff08;/etc/fstab 文件中的错误条目&#xff09;。由于各种原因&#xff08;包括突然断电或电缆损坏&#xff09;导致系统意外或突然关闭。在某些情况下&#xff0c;Windows 的双…

TDengine数据库与Mybatis-plus 多租户屏蔽

使用TDengine时序数据库特有的查询: select sum(gen_power_total) gen_power_totals,last(ts) xdate from power.device_0123456 where ts >2023-05-16 08:53:05 and ts < 2023-05-17 08:53:05 interval(1h) ; 错误提示…

UM2010一款单片集成低功耗 Sub-1GHz 射频收发器芯片

UM2010 是一款工作于 200MHz~960MHz 范围内的低功耗、高性能、单片集成的(G)FSK/OOK 无线收发机芯片。内部集成完整的射频接收机、射频发射机、频率综合器、调制解调器&#xff0c;只需配备 简单、低成本的外围器件就可以获得良好的收发性能。 芯片支持灵活可设的数据包格式&am…

Java使用Groovy执行脚本的使用,GroovyShell Matespace内存溢出解决

目录 业务场景 使用了工具Groovy 遇到Metaspace内存溢出的问题 解决方案 业务场景 类似工作流的场景&#xff0c;需要判断 参数&#xff0c;是否满足流转条件。 随便举个例子: 新增商品资料。 如果是普通商品&#xff0c;状态为"待审核"&#xff0c; 如果为…

mapbox加载多个大数据图层并且播放的技术优化路线

先看成果图 介绍 首先介绍一下我这个数据有15W的面数据&#xff0c;可以即时渲染&#xff0c;即时加载&#xff0c;然后播放。 技术路线 首先这种数量级的大数据&#xff0c;用别的二维API是绝对不可行的&#xff0c;arcgis和openlayer自动放弃&#xff0c;leaflet最多可以坚…

漏测分析的目的

漏测分析的目的 漏测分析是软件测试过程中的一项重要工作&#xff0c;旨在识别和分析测试工作中可能存在的遗漏或疏漏&#xff0c;从而进一步提高软件质量和可靠性。 漏测分析的主要目的是找出未被覆盖的测试用例&#xff0c;即未能被测试到的功能或者代码路径。通过漏测分析&a…

纷享销客PaaS平台之“业务对象定制”

如何填补产品与市场之间的鸿沟&#xff1f;一定程度的定制化是高效运营的基础。 今天的企业需要的不再是简单的几套标准化系统&#xff0c;而是一个能够支撑业务常态化调整、兼具高性能与可扩展的弹性平台。 纷享销客PaaS平台基于元数据模型驱动&#xff0c;提供零代码和低代码…