机器学习实验报告5-K-means 算法

4.1 k-means算法简介

聚类分析,作为机器学习领域中的一种无监督学习方法,在数据探索与知识发现过程中扮演着举足轻重的角色。它能够在没有先验知识或标签信息的情况下,通过挖掘数据中的内在结构和规律,将数据对象自动划分为多个类别或簇。每个簇内的对象具有高度的相似性,而不同簇间的对象则表现出明显的差异性。

在众多聚类算法中,K-means算法因其简单高效而备受青睐。K-means算法的基本思想是:通过迭代的方式,将数据划分为K个不同的簇,并使得每个数据点与其所属簇的质心(或称为中心点、均值点)之间的距离之和最小。

K-means算法的优点在于其直观易懂、计算速度快且易于实现。然而,它也存在一些局限性,如对初始簇质心的选择敏感、可能陷入局部最优解以及需要预先设定聚类数K等。因此,在实际应用中,我们需要根据具体的问题和数据特点来选择合适的聚类算法,并可能需要对算法进行优化或改进以适应特定的需求。

4.2 算法的基本原理

(1)类和分类

类指的是具有相似性的集合。而分类是根据给定的已知类别的样本,训练出来一个模型,使该模型能够对未知类别的样本进行分类。故分类属于有监督学习。有监督学习是指提前由人工对训练数据做好了分类,训练样本同时包含有特征和类别信息。有监督学习类似于先学习带有标准答案的复习题,学习到知识规律以后,再去参加考试。

(2)聚类

对于一些给定的样本,不知道样本之间的关系,不知道他们是否属于同一类,也不知道到底可以分为多少类。此时,通过聚类把未知类别的数据,分为多个类别。聚类目的在于把相似的东西聚在一起,因此聚类属于无监督学习。

(3)K-均值聚类思想

K-均值(K-Means)是发现给定数据集的K个簇的算法。簇个数K是用户给定的,每一个簇通过其质心(即簇中所有点的中心)来描述。其核心思想是将数据集中的n个对象划分为K个聚类,使得每个对象到其所属聚类的中心(或称为均值点、质心)的距离之和最小。这里所说的距离通常指的是欧氏距离,但也可以是其他类型的距离度量。通过迭代的方式不断优化聚类结果,使得每个聚类内的对象尽可能紧密,而不同聚类间的对象则尽可能分开。

(4)算法步骤

K-means算法作为一种强大的无监督学习工具,具有简单易懂、计算效率高和易于实现等优点在多个领域有着广泛的应用下面我们将详细探讨K-means算法的实现步骤。K-means算法的执行过程通常包括以下个步骤

a.初始化选择K个初始聚类中心在算法开始时,需要随机选择K个数据点作为初始的聚类中心。这些初始聚类中心的选择对最终的聚类结果有一定的影响,因此在实际应用中,通常会采用一些启发式的方法来选择较好的初始聚类中心,如K-means++算法。

b.分配将每个数据点分配给最近的聚类中心对于数据集中的每个数据点,计算其与每个聚类中心的距离,并将其分配给距离最近的聚类中心。这一步通常使用欧氏距离作为距离度量,计算公式如下(1)。其中,x是数据点,ci是第i个聚类中心,d是数据的维度,xj和cij分别是x和ci在第j维上的值。

c.更新重新计算每个聚类的中心对于每个聚类,重新计算其聚类中心新的聚类中心是该聚类内所有数据点的均值,计算公式如下(2)。其中,Si是第i个聚类的数据点集合,|Si|是该集合中数据点的数量。

d.迭代,重复分配和更新步骤,直到满足终止条件。重复执行分配和更新步骤,直到满足某种终止条件。常见的终止条件包括,聚类中心不再发生显著变化:即新的聚类中心与旧的聚类中心之间的距离小于某个预设的阈值。达到最大迭代次数:为了避免算法陷入无限循环,通常会设置一个最大迭代次数作为终止条件。在迭代过程中,算法会不断优化聚类结果,使得每个聚类内的对象更加紧密,而不同聚类间的对象更加分散。最终,当满足终止条件时,算法停止迭代并输出最终的聚类结果。

4.3 算法实例

K-means算法作为一种强大的无监督学习工具,在多个领域有着广泛的应用。本实验以对俄勒冈州的波特兰地区地图上的点进行聚类为例,基于k-means算法实现将这些地方进行聚类的最佳策略,这样就可以安排交通工具抵达这些簇的质心,然后步行到每个内地址。实例操作可分为以下五个过程。

  1. 收集数据

通过调用geoGrab函数来实现收集数据,geoGrab函数的作用是收集数据,通过调用雅虎地理编码 API(Yahoo Geocoding API),将输入的街道地址和城市名称转换为对应的地理坐标(经纬度等位置信息),返回 API 响应的 JSON 格式数据,包含地址对应的地理编码信息(如坐标、地址匹配度等)。

相关代码如下:

def geoGrab(stAddress, city):

    apiStem = 'http://where.yahooapis.com/geocode?'  #create a dict and constants for the goecoder

    params = {}

    params['flags'] = 'J'#JSON return type

    params['appid'] = 'aaa0VN6k'

    params['location'] = '%s %s' % (stAddress, city)

    url_params = urllib.parse.urlencode(params)

    yahooApi = apiStem + url_params      #print url_params

    print (yahooApi)

    c=urllib.parse.urlopen(yahooApi)

    return json.loads(c.read())

  1. 准备数据

准备数据中,只保留经纬度信息。我们可以通过调用massPlaceFind函数。该函数其作用是批量处理地址数据,通过调用geoGrab函数获取地理坐标(经纬度),并将结果写入文件。该函数适用于批量处理地址数据,生成带地理坐标的数据集,常用于地理信息系统(GIS)、数据分析或地图可视化等场景。

相关代码如下:

def massPlaceFind(fileName):

    fw = open('places.txt', 'w')

    for line in open(fileName).readlines():

        line = line.strip()

        lineArr = line.split('\t')

        retDict = geoGrab(lineArr[1], lineArr[2])

        if retDict['ResultSet']['Error'] == 0:

            lat = float(retDict['ResultSet']['Results'][0]['latitude'])

            lng = float(retDict['ResultSet']['Results'][0]['longitude'])

            print("%s\t%f\t%f" % (lineArr[0], lat, lng))

            fw.write('%s\t%f\t%f\n' % (line, lat, lng))

        else: print ("error fetching")

        sleep(1)

    fw.close()

  1. 分析数据

使用Matplotlib来构建一个二维数据图,其中包含簇与地图。我们通过调用clusterClubs函数来实现。clusterClubs函数,其核心功能是对地点的经纬度数据进行聚类分析,并在地图背景上可视化聚类结果。该函数适用于地理数据的聚类分析与可视化,常用于城市规划、商业选址、轨迹分析等场景,帮助快速识别数据中的空间分布模式。

图1 调用函数

图2 二维数据图

相关代码如下:

def clusterClubs(numClust=5):

    datList = []

    for line in open('places.txt').readlines():

        lineArr = line.split('\t')

        datList.append([float(lineArr[4]), float(lineArr[3])])

    datMat = matrix(datList)

    myCentroids, clustAssing = biKmeans(datMat, numClust, distMeas=distSLC)

    fig = plt.figure()

    rect=[0.1,0.1,0.8,0.8]

    scatterMarkers=['s', 'o', '^', '8', 'p', \'d', 'v', 'h', '>', '<']

    axprops = dict(xticks=[], yticks=[])

    ax0=fig.add_axes(rect, label='ax0', **axprops)

    imgP = plt.imread('Portland.png')

    ax0.imshow(imgP)

    ax1=fig.add_axes(rect, label='ax1', frameon=False)

    for i in range(numClust):

        ptsInCurrCluster = datMat[nonzero(clustAssing[:,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(myCentroids[:,0].flatten().A[0], myCentroids[:,1].flatten().A[0], marker='+', s=300)

    plt.show()

  1. 测试算法

通过调用biKmeans()函数来测试算法。该函数实现了二分K均值算法(Bisecting K-Means),用于对数据集进行聚类分析。其核心作用是通过 “逐步分裂簇” 的策略,将数据集划分为指定数量的簇(k个)

图3 测试算法

相关代码如下:

def biKmeans(dataSet, k, distMeas=distEclud):

    m = shape(dataSet)[0]

    clusterAssment = matrix(zeros((m,2)))

    centroid0 = mean(dataSet, axis=0).tolist()[0]

    centList =[centroid0] #create a list with one centroid

    for j in range(m):#calc initial Error

        clusterAssment[j,1] = distMeas(matrix(centroid0), dataSet[j,:])**2

    while (len(centList) < k):

        lowestSSE = inf

        for i in range(len(centList)):

            ptsInCurrCluster = dataSet[nonzero(clusterAssment[:,0].A==i)[0],:]#get the data points currently in cluster i

            centroidMat, splitClustAss = kMeans(ptsInCurrCluster, 2, distMeas)

            sseSplit = sum(splitClustAss[:,1])#compare the SSE to the currrent minimum

            sseNotSplit = sum(clusterAssment[nonzero(clusterAssment[:,0].A!=i)[0],1])

            print("sseSplit, and notSplit: ",sseSplit,sseNotSplit)

            if (sseSplit + sseNotSplit) < lowestSSE:

                bestCentToSplit = i

                bestNewCents = centroidMat

                bestClustAss = splitClustAss.copy()

                lowestSSE = sseSplit + sseNotSplit

        bestClustAss[nonzero(bestClustAss[:,0].A == 1)[0],0] = len(centList) #change 1 to 3,4, or whatever

        bestClustAss[nonzero(bestClustAss[:,0].A == 0)[0],0] = bestCentToSplit

        print ('the bestCentToSplit is: ',bestCentToSplit)

        print ('the len of bestClustAss is: ', len(bestClustAss))

        centList[bestCentToSplit] = bestNewCents[0,:].tolist()[0]#replace a centroid with two best centroids

        centList.append(bestNewCents[1,:].tolist()[0])

        clusterAssment[nonzero(clusterAssment[:,0].A == bestCentToSplit)[0],:]= bestClustAss#reassign new clusters, and SSE

    return matrix(centList), clusterAssment

  1. 使用算法

我们通过使用clusterClubs函数来输出包含簇及簇中心的地图。clusterClubs函数,其核心功能是对地点的经纬度数据进行聚类分析,并在地图背景上可视化聚类结果。操作过程与(3)分析数据相同。

图4 簇及簇中心图

相关代码如下:

def clusterClubs(numClust=5):

    datList = []

    for line in open('places.txt').readlines():

        lineArr = line.split('\t')

        datList.append([float(lineArr[4]), float(lineArr[3])])

    datMat = matrix(datList)

    myCentroids, clustAssing = biKmeans(datMat, numClust, distMeas=distSLC)

    fig = plt.figure()

    rect=[0.1,0.1,0.8,0.8]

    scatterMarkers=['s', 'o', '^', '8', 'p', \

                    'd', 'v', 'h', '>', '<']

    axprops = dict(xticks=[], yticks=[])

    ax0=fig.add_axes(rect, label='ax0', **axprops)

    imgP = plt.imread('Portland.png')

    ax0.imshow(imgP)

    ax1=fig.add_axes(rect, label='ax1', frameon=False)

    for i in range(numClust):

        ptsInCurrCluster = datMat[nonzero(clustAssing[:,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(myCentroids[:,0].flatten().A[0], myCentroids[:,1].flatten().A[0], marker='+', s=300)

    plt.show()

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

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

相关文章

【已解决】yoloOnnx git工程部署

首先 yoloonnx一个VS工程下来整个工程大概1-2个g的大小因此在git的过程中总是会因为文件超过100M而触发报错&#xff0c;上传不上去&#xff0c;因此现在需要做一个过滤才能把工程重新上传上去&#xff0c;那么这个时候别人需要下载下来的时候确实不完整的工程&#xff0c;因此…

如何轻松地将照片从电脑传输到安卓手机

一些安卓用户正在寻找有效可靠的方法&#xff0c;将照片从电脑传输到安卓设备。如果您也想将有趣或难忘的照片导入安卓手机或平板电脑&#xff0c;可以参考这篇文章&#xff0c;它提供了 6 种可靠的方法&#xff0c;让您轻松传输照片。 第 1 部分&#xff1a;如何通过 Android …

准备纯血鸿蒙理论高级认证的一些心得

最近在准备纯血鸿蒙理论高级认证&#xff0c;一些心得记录下来&#xff0c;希望早日考过高级&#xff01; 一、考试目标&#xff1a; HarmonyOS核心技术理念HarmonyOS应用架构设计ArkTS原理和实践ArkUI开发HarmonyOS关键技术能力开发工程管理、代码编辑、调试与定位应用上架运…

义乌购拍立淘API接入指南

一、接口概述 拍立淘是义乌购平台提供的以图搜货服务&#xff0c;通过HTTP RESTful API实现。当前版本为v3.2&#xff0c;支持JPG/PNG格式图片&#xff08;≤5MB&#xff09;&#xff0c;返回相似商品列表及供应链信息。 二、接入准备 申请开发者账号 # 开发者注册示例&…

Web 连接和跟踪

大家读完觉得有帮助记得及时关注和点赞&#xff01;&#xff01;&#xff01; 抽象 网络跟踪是一种普遍且不透明的做法&#xff0c;可实现个性化广告、重新定位和转化跟踪。 随着时间的推移&#xff0c;它已经演变成一个复杂的侵入性生态系统&#xff0c;采用越来越复杂的技术来…

前端技术栈与 SpreadJS 深度融合:打造高效数据表格应用

引言 在当今数字化的时代&#xff0c;数据表格应用在各种 Web 项目中扮演着至关重要的角色。从企业级的管理系统到电商平台的商品展示&#xff0c;数据表格都是用户与数据交互的重要界面。前端技术栈如 JavaScript、HTML 和 CSS 为构建用户界面提供了强大的工具和方法&#xf…

如何用ai描述缺陷(bug)

附件1&#xff1a; 附件2&#xff1a; 将附件1和附件2发送给deepseek&#xff0c;且输入对话框的文字&#xff1a; 然后进入禅道用户登录 - 禅道 ### **缺陷报告&#xff1a;登录功能无响应缺陷** **提交平台**&#xff1a;禅道缺陷管理系统 **发现环境**&#xff1a;测试环…

软考 系统架构设计师系列知识点之杂项集萃(89)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之杂项集萃&#xff08;88&#xff09; 第161题 下面可提供安全电子邮件服务的是&#xff08; &#xff09;。 A. RSA B. SSL C. SET D. S/MIME 正确答案&#xff1a;D。 解析&#xff1a; MIME&#xff08;Multi…

开源 Arkts 鸿蒙应用 开发(一)工程文件分析

文章的目的为了记录使用Arkts 进行Harmony app 开发学习的经历。本职为嵌入式软件开发&#xff0c;公司安排开发app&#xff0c;临时学习&#xff0c;完成app的开发。开发流程和要点有些记忆模糊&#xff0c;赶紧记录&#xff0c;防止忘记。 相关链接&#xff1a; 开源 Arkts …

protobuf遇到protoc-gen-go: unable to determine Go import path for “xxx“

问题 这个错误是因为 .proto 文件中缺少必需的 go_package 选项。在 protobuf 生成 Go 代码时&#xff0c;这是关键配置项。 pandaVM:~/dev/pb$ protoc --go_out. pb.proto protoc-gen-go: unable to determine Go import path for "pb.proto"Please specify eithe…

linux unix socket 通信demo

好&#xff0c;下面是已经整合完善的版本&#xff1a; ✅ 功能点&#xff08;你要求的全部实现了&#xff09;&#xff1a; Unix Domain Socket (SOCK_STREAM) 服务端先启动&#xff1a;正常通信 客户端先启动&#xff1a;等待服务端直到连接成功 客户端每秒发送一条消息 服务端…

近期GitHub热榜推荐

【1】fluentui-system-icons (HTML) &#x1f468;‍&#x1f4bb; 作者&#xff1a; microsoft &#x1f4e6; 仓库&#xff1a; microsoft / fluentui-system-icons &#x1f310; 链接&#xff1a; https://github.com/microsoft/fluentui-system-icons ⭐ 星标&#xf…

Jupyter 是什么?基于浏览器的交互式计算环境

&#x1f9e0; 一、Jupyter 是什么&#xff1f; Jupyter 是一个基于浏览器的交互式计算环境&#xff0c;名字取自Julia Python R 三种语言&#xff0c;但现在已支持超过40种编程语言。它最核心的功能是让你在同一个文档&#xff08;.ipynb 文件&#xff09;中混合编写代码、…

CTF解题:[NSSCTF 2022 Spring Recruit]弱类型比较绕过

一、漏洞背景介绍 在 CTF&#xff08;Capture The Flag&#xff09;竞赛和 Web 安全测试中&#xff0c;PHP 语言的类型比较漏洞是常见的考点。这类漏洞源于 PHP 的弱类型特性&#xff0c;即当使用进行比较时&#xff0c;PHP 会自动进行类型转换&#xff0c;从而导致一些不符合…

【SQL】存储过程 vs 普通 SQL

一、存储过程 vs 普通 SQL 的核心区别 先明确两者的本质&#xff1a; 普通 SQL&#xff1a;是直接执行的查询 / 操作语句&#xff08;如SELECT、INSERT&#xff09;&#xff0c;每次执行都要编译&#xff0c;逻辑写在应用端或直接运行。存储过程&#xff1a;是预编译并存储在…

Vue.js第一节

初识Vue、插值操作、属性绑定 初识&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>D…

前端打断点

这个按钮有个点击事件&#xff0c;然后点击这个js 即可进入到代码中 如果这时想打一些临时的表达式&#xff0c;可以按esc弹出console控制台&#xff0c; 右上角有可以使用的变量

Jmeter接口测试与性能测试

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 目前最新版本发展到5.0版本&#xff0c;需要Java7以上版本环境&#xff0c;下载解压目录后&#xff0c;进入\apache-jmeter-5.0\bin\&#xff0c;双击ApacheJMete…

如何利用大模型搭建本地知识库

要利用大模型搭建本地知识库&#xff0c;核心在于&#xff1a;构建高质量知识内容源、使用向量化技术实现语义检索、部署大语言模型以实现自然语言问答接口、设计本地知识库的数据更新机制、注重隐私与合规性控制。其中&#xff0c;使用向量化技术实现语义检索至关重要&#xf…

vscode连接不上服务器问题修复

原因&#xff1a;运维人员修复漏洞&#xff0c;升级了服务器openssh版本&#xff0c;导致无法新建连接连上vscode 操作&#xff1a; 1.删除云桌面上C:\Users\.ssh 路径下known_hosts文件&#xff1b; 2.设置免密登录 1&#xff09;执行 ssh-keygen -t rsa -C "your_em…