机器学习——聚类算法一

机器学习——聚类算法一

文章目录

  • 前言
  • 一、基于numpy实现聚类
  • 二、K-Means聚类
    • 2.1. 原理
    • 2.2. 代码实现
    • 2.3. 局限性
  • 三、层次聚类
    • 3.1. 原理
    • 3.2. 代码实现
  • 四、DBSCAN算法
    • 4.1. 原理
    • 4.2. 代码实现
  • 五、区别与相同点
    • 1. 区别:
    • 2. 相同点:
  • 总结


前言

在机器学习中,有多种聚类算法可以用于将数据集中的样本按照相似性进行分组。本文将介绍一些常见的聚类算法:

  1. K-Means聚类
  2. 层次聚类
  3. DBSCAN算法

在这里插入图片描述

一、基于numpy实现聚类

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from numpy.linalg import norm
import random
np.random.seed(42)
data = np.random.randn(100,2)  #生成一个包含100个样本点的随机数据集,每个样本有2个特征
df = pd.DataFrame(data= data,columns=["x1","x2"])

x1_min, x1_max, x2_min, x2_max = df.x1.min(), df.x1.max() ,df.x2.min(), df.x2.max()

# 初始化两个质心
centroid_1 = np.array([random.uniform(x1_min, x1_max), random.uniform(x2_min, x2_max)])
centroid_2 = np.array([random.uniform(x1_min, x1_max), random.uniform(x2_min, x2_max)])

data = df.values
#设置迭代次数为10
for i in range(10):
    clusters = []
    for point in data:
        centroid_1_dist = norm(centroid_1- point) #计算两点之间的距离
        centroid_2_dist = norm(centroid_2- point)
        cluster = 1
        if centroid_1_dist > centroid_2_dist:
            cluster = 2
        clusters.append(cluster)
    df["cluster"] = clusters

#更换质心(即迭代聚类点)
centroid_1 = [round(df[df.cluster == 1].x1.mean(),3), round(df[df.cluster == 1].x2.mean(),3)]
centroid_2 = [round(df[df.cluster == 2].x1.mean(),3), round(df[df.cluster == 2].x2.mean(),3)]

plt.scatter(x1, x2, c=df["cluster"])
plt.scatter(centroid_1,centroid_2, marker='x', color='red')
plt.show()


在这里插入图片描述

二、K-Means聚类

2.1. 原理

K-means 是一种迭代算法,它将数据集按照距离划分为 K 个簇(其中K是用户预先指定的簇的数量),每个簇代表一个聚类(聚类后同一类数据尽可能聚集到一起,不同类数据分离)。实现步骤如下:

  1. 随机初始化K个质心,每个质心代表一个簇
  2. 将每个样本点分配到距离其最近的质心所代表的簇。(如此就形成了K个簇)
  3. 更新每个簇的质心,(即计算每个簇中样本点的平均值)
  4. 重复步骤2和步骤3,直到质心的位置不再改变或达到预定的迭代次数。

2.2. 代码实现

  1. 导入数据集,以鸢尾花(iris)数据集为例:
from sklearn.datasets import load_iris
import pandas as pd

# 加载数据集
iris = load_iris()

#查看数据集信息
print(iris.keys())
dict_keys(['data', 'target', 'frame', 'target_names', 'DESCR', 'feature_names', 'filename', 'data_module'])

#获取特征数据
data = iris["data"]

# 获取标签数据
target = iris["target"]
print(pd.Series(target).unique())
[0 1 2]


#查看分类名
print(iris["target_names"])
['setosa' 'versicolor' 'virginica']


#整合到数据框
import pandas as pd
df = pd.DataFrame(data= iris["data"],columns= iris["feature_names"])
print(df.head())
   sepal length (cm)  sepal width (cm)  petal length (cm)  petal width (cm)
0                5.1               3.5                1.4               0.2
1                4.9               3.0                1.4               0.2
2                4.7               3.2                1.3               0.2
3                4.6               3.1                1.5               0.2
4                5.0               3.6                1.4               0.2
  1. 确定初始化质点K的取值

肘部法则选择聚类数目:
该方法适用于K值相对较小的情况,随着聚类数目的增加,聚类误差(也称为SSE,Sum of Squared Errors)会逐渐减小。然而,当聚类数目达到一定阈值后,聚类误差的减小速度会变缓,形成一个类似手肘的曲线。这个手肘点对应的聚类数目就是肘部法则选择的合适聚类数目

from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
sse = []
# 设置聚类数目的范围
k_range = range(1, 10)
# 计算每个聚类数目对应的 SSE
for k in k_range:
    kmeans = KMeans(n_clusters=k,random_state = 42)
    kmeans.fit(df)
    sse.append(kmeans.inertia_)

# 绘制聚类数目与 SSE 之间的曲线图
plt.style.use("ggplot")
plt.plot(k_range, sse,"r-o")
plt.xlabel('Number of K')
plt.ylabel('SSE')
plt.title('Elbow Method')
plt.show()

在这里插入图片描述

从图中可看出,当K=3时,该曲线变得比较平缓,则该点为肘部点。即最佳的聚类数目为K=3

  1. 从sklean中调用k-Means算法模型
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=3,max_iter= 400,random_state=42)
kmeans.fit(df)
print(kmeans.cluster_centers_)
y_kmeans = kmeans.labels_
df["y_kmeans"] = y_kmeans
  1. 可视化聚类结果

绘制平面图:

plt.scatter(df["sepal length (cm)"], df["sepal width (cm)"], c=df["y_kmeans"], cmap='viridis')
# 绘制聚类中心
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], c='red', marker='x', s=100)
plt.xlabel('Sepal Length')
plt.ylabel('Sepal Width')
plt.title('K-Means Clustering')
handles, labels = sc.legend_elements()
plt.legend(handles, labels)
plt.show()

在这里插入图片描述

绘制三维图:

# 创建3D图形对象
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection='3d')
# 绘制散点图
sc = ax.scatter(df["sepal length (cm)"], df["sepal width (cm)"], df["petal length (cm)"], c=df["y_kmeans"], cmap='viridis')

# 绘制聚类中心
ax.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], kmeans.cluster_centers_[:, 2], c='red', marker='x', s=100)

ax.set_xlabel('Sepal Length')
ax.set_ylabel('Sepal Width')
ax.set_zlabel('Petal Length')
ax.set_title('K-Means Clustering')

# 添加图例
handles, labels = sc.legend_elements()
ax.legend(handles, labels)

plt.show()

在这里插入图片描述

2.3. 局限性

k-Means算法通过距离来度量样本之间的相似性,因此对于非凸形状的聚类,算法可能无法正确地将样本划分到正确的聚类中。

k-Means算法对噪声和离群点敏感。这些异常值可能会影响到聚类结果,使得聚类变得不准确

需要事先指定聚类的数量k,而且对结果敏感。如果选择的聚类数量不合适,会导致聚类结果不准确或不理想。

比如这种情况:
在这里插入图片描述

三、层次聚类

3.1. 原理

层次聚类(Agglomerative clustering)算法是一种基于树状结构的聚类方法,分为凝聚型和分裂型层次聚类。

分裂型层次聚类从整个数据集作为一个簇开始,然后逐步将簇分裂为更小的簇,直到达到预定的簇的数量或达到某个停止准则。

凝聚型层次聚类将数据集中的样本逐步合并为越来越大的簇。
即从N个簇开始(每个样本为一个簇),在每个步骤中合并两个最相似的簇,直到达到某个停止准则。

如图所示,从上(下)往下(上):
在这里插入图片描述

优点是可以直观地展示数据点之间的相似性关系,并且不一定要预先指定聚类簇的数量。
层次聚类的缺点是计算复杂度较高,且对数据的噪声和异常值比较敏感。

3.2. 代码实现

参数 linkage: 用于指定链接算法。
“ward” : 单链接,即两个簇的样本对之间距离的min
“complete”: 全链接,即两个簇的样本对之间距离的max
“average”: 均链接,即两个簇的样本对之间距离的mean

参数 affinity : 用于计算距离。
“euclidean”:使用欧几里德距离来计算数据点之间的距离(这是默认的距离度量方法)。
“manhattan”:使用曼哈顿距离来计算数据点之间的距离,它是两个点在所有维度上绝对值之和的总和。
“cosine”:使用余弦相似度来计算数据点之间的距离。

from sklearn.cluster import AgglomerativeClustering
cluster = AgglomerativeClustering()
print(cluster.fit_predict(df))

cluster = AgglomerativeClustering(n_clusters= 3 ,linkage= "complete",affinity="manhattan")
cluster.fit(df)
df["cluster"] = cluster.labels_
print(cluster.labels_)


# 创建3D图形对象
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection='3d')
plt.style.use("ggplot")

for i in range(len(df["cluster"])):
    if df["cluster"][i] == 0:
        ax.scatter(df["sepal length (cm)"][i], df["sepal width (cm)"][i], df["petal length (cm)"][i],c = "red")
    elif df["cluster"][i] ==1:
        ax.scatter(df["sepal length (cm)"][i], df["sepal width (cm)"][i], df["petal length (cm)"][i],c = "blue")
    else:
        ax.scatter(df["sepal length (cm)"][i], df["sepal width (cm)"][i], df["petal length (cm)"][i],c = "yellow")

ax.set_xlabel('Sepal Length')
ax.set_ylabel('Sepal Width')
ax.set_zlabel('Petal Length')
ax.set_title('Clustering')
plt.show()

在这里插入图片描述

四、DBSCAN算法

4.1. 原理

DBSCAN是一种基于密度的聚类算法,它能够发现任意形状的聚类簇,并且能够识别出噪声点,它将样本划分为核心点、边界点和噪声点。算法的步骤如下:

  1. 随机选择一个未访问的样本点。根据设置的距离半径(eps),称在这一范围的区域为该样本实例的邻域

  2. 如果该样本点的邻域内样本数大于设定的阈值(min_samples),则将其标记为核心点,并将其邻域内的样本点加入到同一个簇中。

  3. 如果该样本点的邻域内样本数小于设定的阈值,则将其标记为边界点。

  4. 重复以上步骤,直到所有样本点都被访问。

  5. 最后,任何不是核心点,且邻域中没有实例样本的样本点都将被标记为噪声点

4.2. 代码实现

from sklearn.cluster import DBSCAN
cluster = DBSCAN(eps= 0.6 , min_samples= 10)
cluster.fit(df)
df["cluster"] = cluster.labels_
print(df)

#-1代表噪声点
print(df["cluster"].value_counts())
 1    88
 0    49
-1    13
Name: cluster, dtype: int64


sc = plt.scatter(df["sepal length (cm)"],df["sepal width (cm)"],c = df["cluster"])
plt.title('DBSCAN Clustering')
handles, labels = sc.legend_elements()
plt.legend(handles, labels)
plt.show()

在这里插入图片描述

from sklearn.cluster import DBSCAN
from sklearn.datasets import make_moons

# 生成随机数据
X, y = make_moons(n_samples=200, noise=0.05) 
print(X)

dbscan = DBSCAN(eps=0.3, min_samples=5)
dbscan.fit(X)

# 获取聚类标签
labels = dbscan.labels_

#因为设置的noise很小,故没有噪声点
print(pd.Series(labels).value_counts())
0    100
1    100
dtype: int64


# 绘制聚类结果
plt.scatter(X[:, 0], X[:, 1], c=labels)
plt.title('DBSCAN Clustering')
handles, labels = sc.legend_elements()
plt.legend(handles, labels)
plt.show()

在这里插入图片描述

五、区别与相同点

1. 区别:

  1. K-means是一种划分聚类算法,它将数据集划分为固定数量的簇(一定要预先指定簇的数量),而层次聚类(不一定要指定簇的数量)和DBSCAN算法(需要指定邻域半径和最小样本数),它们可以自动确定簇的数量。

  2. K-means和层次聚类算法都假设簇具有相同的形状和大小,而DBSCAN算法可以发现任意形状和大小的簇。

  3. K-means和层次聚类算法都对异常值敏感,而DBSCAN算法对异常值不敏感。(可去掉噪声点)

2. 相同点:

K-means、层次聚类和DBSCAN算法都是无监督学习算法中的聚类算法,它们不依赖于标签信息。

这些算法都使用距离或相似性度量来度量样本之间的相似性或距离。


总结

本文从最开始的自己实现聚类到后面的三个机器学习中聚类算法:( K-Means 、层次聚类、DBSCAN聚类)的学习,再到后面对这三个算法的比较与总结。加深了对聚类原理的了解。

我住长江头,君住长江尾;日日思君不见君

–2023-8-31 筑基篇

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微机原理 || 第3次测试:第八章-常用接口芯片82558253(测试题+手写解析)

(一)知识点总结 一直没有学明白8253和8255芯片,觉得后面难,其实看懂后,就是照着表格去对应填写, 知道地址怎么回事就没问题哒~ 相信你😘 一、8255芯片(不是偷懒,真的就…

百亿级访问量,如何做缓存架构设计

说在前面 在40岁老架构师 尼恩的读者社区(50)中,最近有小伙伴拿到了一线互联网企业如阿里、网易、有赞、希音、百度、网易、滴滴的面试资格,遇到一几个很重要的面试题:: 分布式缓存系统,如何架构?百亿级访…

Android安卓实战项目(12)—关于身体分析,BMI计算,喝水提醒,食物卡路里计算APP【支持中英文切换】生活助手类APP(源码在文末)

Android安卓实战项目(12)—关于身体分析,BMI计算,喝水提醒,食物卡路里计算APP【支持中英文切换】生活助手类APP(源码在文末🐕🐕🐕) 一.项目运行介绍 B站演示…

题目有点太简单了,不知道怎么选了

有个公司给了下面一个题目&#xff0c;看了下太简单了&#xff0c;都怕选错了。 后来拿着程序跑了下&#xff0c;就是这个意思嘛。 结论 程序跑出来的结果就是对输入的列表进行倒序排列。 public void testGetPut() throws Exception {List<Integer> numbers List.of(…

安防监控/磁盘阵列存储/视频汇聚平台EasyCVR调用rtsp地址返回的IP不正确是什么原因?

安防监控/云存储/磁盘阵列存储/视频汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有GB28181、RTSP/Onvif、RTMP等&#xff0c;以及厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等&#xff0c;能对外分发RTSP、RT…

【SQL应知应会】索引 • Oracle版:B-树索引;位图索引;函数索引;单列与复合索引;分区索引

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 本文免费学习&#xff0c;自发文起3天后&#xff0c;会收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习&#xff0c;有基础也有进阶&#xff0c;有MySQL也有Oracle …

Vue+Element-ui实现表格本地导入

表格文件存储在前端 如图&#xff0c;表格文件template.xlsx存储在public下的static文件夹下 注意这里的路径容易报错 a链接下载文件失败的问题(未发现文件&#xff09; a.href ‘./static/template.xlsx’ 写的时候不能带public&#xff0c;直接这么写就可以 DownloadTemp…

Linux进程概念及其状态

文章目录 &#x1f347;1. 什么是进程&#x1f348;1.1 概念&#x1f348;1.2 理解进程 &#x1f34b;2. Linux的PCB&#x1f34e;3. 查看进程 & 杀死进程&#x1f352;4. 系统调用获取进程标识符&#x1f353;4.1 进程PID&#x1f353;4.2 父进程PPID &#x1f346;5. 系统…

uniapp 微信小程序添加隐私保护指引

隐私弹窗&#xff1a; <uni-popup ref"popup"><view class"popupWrap"><view class"popupTxt">在你使用【最美万年历】之前&#xff0c;请仔细阅读<text class"blueColor" click"handleOpenPrivacyContract…

Linux学习之lvm删除

umount /mnt/logicvolumntest卸载挂载。 lvremove /dev/vgname/my_lv可以删除逻辑卷&#xff0c;其中vgname是指定逻辑卷所在的卷组名称&#xff0c;my_lv是逻辑卷的名称。 注意&#xff1a;使用lvremove命令会永久删除逻辑卷和其中的数据&#xff0c;因此请在使用之前进行适当…

解决springboot项目中的groupId、package或路径的混淆问题

对于像我一样喜欢跳跃着学习的聪明人来说&#xff0c;肯定要学springboot&#xff0c;什么sevlet、maven、java基础&#xff0c;都太老土了&#xff0c;用不到就不学。所以古代的聪明人有句话叫“书到用时方恨少”&#xff0c;测试开源项目时&#xff0c;编译总是报错&#xff…

【FreeRTOS】互斥量的使用与逐步实现

在FreeRTOS中&#xff0c;互斥量是一种用于保护共享资源的同步机制。它通过二进制信号量的方式&#xff0c;确保在任意时刻只有一个任务可以获取互斥量并访问共享资源&#xff0c;其他任务将被阻塞。使用互斥量的基本步骤包括创建互斥量、获取互斥量、访问共享资源和释放互斥量…

RNN 单元:分析 GRU 方程与 LSTM,以及何时选择 RNN 而不是变压器

一、说明 深度学习往往感觉像是在雪山上找到自己的道路。拥有坚实的原则会让你对做出决定更有信心。我们都去过那里 在上一篇文章中&#xff0c;我们彻底介绍并检查了 LSTM 单元的各个方面。有人可能会争辩说&#xff0c;RNN方法已经过时了&#xff0c;研究它们是没有意义的。的…

Python Opencv实践 - 轮廓检测

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/map.jpg") print(img.shape) plt.imshow(img[:,:,::-1])#Canny边缘检测 edges cv.Canny(img, 127, 255, 0) plt.imshow(edges, cmapplt.cm.gray)#查找轮廓 #c…

pdf怎么删除其中一页?

pdf怎么删除其中一页&#xff1f;现在&#xff0c;pdf文件已经深入影响着我们的工作和学习&#xff0c;如果你是一个上班族&#xff0c;那么几乎每天都会使用到pdf格式的电脑文件。当我们阅读一个页数众多的PDF文件时&#xff0c;可能会发现实际上只需要其中的一小部分内容。很…

jvm-堆

1.堆的核心概念 一个jvm实例只存在一个堆内存&#xff0c;堆也是java内存管理核心区域 java堆区在jvm启动的时候即被创建&#xff0c;其空间大小就确定了&#xff0c;是jvm管理最大的一块内存空间&#xff1b; 堆可以处于物理上不连续的内存空间&#xff0c;但在逻辑上它应该被…

Sqoop实操案例-互联网招聘数据迁移

&#x1f947;&#x1f947;【大数据学习记录篇】-持续更新中~&#x1f947;&#x1f947; 个人主页&#xff1a;beixi 本文章收录于专栏&#xff08;点击传送&#xff09;&#xff1a;【大数据学习】 &#x1f493;&#x1f493;持续更新中&#xff0c;感谢各位前辈朋友们支持…

在 macOS 中安装 TensorFlow 1g

tensorflow 需要多大空间 pip install tensorflow pip install tensorflow Looking in indexes: https://pypi.douban.com/simple/ Collecting tensorflowDownloading https://pypi.doubanio.com/packages/1a/c1/9c14df0625836af8ba6628585c6d3c3bf8f1e1101cafa2435eb28a7764…

面试被打脸,数据结构底层都不知道么--回去等通知吧

数据结构之常见的8种数据结构&#xff1a; -数组Array -链表 Linked List -堆 heap -栈 stack -队列 Queue -树 Tree -散列表 Hash -图 Graph 数据结构-链表篇 Linklist定义&#xff1a; -是一种线性表&#xff0c;并不会按线性的顺序存储数据&#xff0c;即逻辑上相邻…

Spring Boot源码解读与原理剖析:深入探索Java开发的奥秘!

评论区留言赠书15本 关注点赞评论&#xff0c;评论区回复“Spring Boot源码解读与原理剖析&#xff1a;深入探索Java开发的奥秘&#xff01;” 每篇最多评论3条&#xff01;&#xff01;采用抽奖助手自动拉取评论区有效评论送书两本&#xff0c; 开奖时间&#xff1a;9月11号 承…