机器学习——聚类算法一

机器学习——聚类算法一

文章目录

  • 前言
  • 一、基于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 = 1if centroid_1_dist > centroid_2_dist:cluster = 2clusters.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    880    49
-1    13
Name: cluster, dtype: int64sc = 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 筑基篇

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

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

相关文章

ASCII码 对照表

总256个字符元素 0~255 码值整数据 字符结构 字符元素(内容) 整数结构 码值整数

怎么将pdf合并成一个?将pdf合并成一个的方法

在日常工作和学习中,我们经常会遇到需要将多个PDF文件合并成一个的情况。这不仅能够提高文件管理的便捷性,还能节省存储空间并使阅读更加流畅。那么,怎么将pdf合并成一个呢?在本文中,我将为您介绍几种简单实用的方法&a…

无涯教程-机器学习 - 数据可视化

在上一章中,无涯教程讨论了数据对于机器学习算法的重要性,以了解具有统计信息的数据,还有另一种称为可视化的方式来理解数据。 借助数据可视化,可以看到数据的属性保持什么样的关联,这是查看要素是否与输出相对应的最…

【枚举区间+线段树】CF Ehu 152 E

Problem - E - Codeforces 题意: 思路: 感觉是个套路题 对区间计数,按照CF惯用套路,枚举其中一个端点,对另一个端点计数 对于这道题,枚举右端点,对左端点计数 Code: #include &…

类和对象(中)

💓博主个人主页:不是笨小孩👀 ⏩专栏分类:数据结构与算法👀 C👀 刷题专栏👀 C语言👀 🚚代码仓库:笨小孩的代码库👀 ⏩社区:不是笨小孩👀 🌹欢迎大…

Spring Cloud Gateway的快速使用

环境前置搭建Nacos&#xff1a;点击跳转 Spring Cloud Gateway Docs 新建gateway网关模块 pom.xml导入依赖 <!-- 网关 --> <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifact…

React 如何获取上一次 state 的值

React 如何获取上一次 state 的值 一、用 ref 存储上一次的 state 类似 usePrevious function usePrevious(value) {const ref useRef();useEffect(() > {ref.current value;});return ref.current; }二、通过 setState 的入参改为函数获取

【ES6】Promise.race的用法

Promise.race()方法同样是将多个 Promise 实例&#xff0c;包装成一个新的 Promise 实例。 const p Promise.race([p1, p2, p3]);上面代码中&#xff0c;只要p1、p2、p3之中有一个实例率先改变状态&#xff0c;p的状态就跟着改变。那个率先改变的 Promise 实例的返回值&#…

知识图谱笔记:TransH

1 TransE存在的问题 一对多 假设有一个关系 "是父亲"&#xff0c;其中一个父亲&#xff08;头实体&#xff09;可能有多个孩子&#xff08;尾实体&#xff09; 父亲 A -> 孩子 1父亲 A -> 孩子 2在 TransE 中&#xff0c;这两个关系会被建模为&#xff1a; A是…

进程控制相关 API-创建进程、进程分离、进程退出、进程阻塞

进程控制相关 API p.s 进程控制中的状态转换 相关 API&#xff0c;用户很少用到&#xff0c;在此不提。 一般来说&#xff0c;这些内核标准 API&#xff0c;在执行出错&#xff08;可能是资源不够、权限不够等等&#xff09;会返回负值&#xff08;比如 -1&#xff09;&#…

【Qt QAxObject】使用 QAxObject 高效任意读写 Excel 表

1. 用什么操作 Excel 表 Qt 的官网库中是不包含 Microsoft Excel 的操作库&#xff0c;关于对 Microsoft Excel 的操作库可选的有很多&#xff0c;包含基于 Windows 系统本身的 ActiveX、Qt Xlsx、xlsLib、LibXL、qtXLS、BasicExcel、Number Duck。 库.xls.xlsx读写平台Qt Xls…

JVM的故事——类文件结构

类文件结构 文章目录 类文件结构一、概述二、无关性基石三、Class类文件的结构 一、概述 计算机是只认由0、1组成的二进制码的&#xff0c;不过随着发展&#xff0c;我们编写的程序可以被编译成与指令集无关、平台中立的一种格式。 二、无关性基石 对于不同平台和不同平台的…

docker命令学习

docker vscode插件出现的问题 docker命令 docker images &#xff08;查看所有的镜像&#xff09; docker ps -a &#xff08;查看所有的容器&#xff09; docker ps &#xff08;查看运行的容器&#xff09; docker run imageID docker run --gpus all --shm-size8g -it imag…

网络安全体系架构介绍

网络安全体系是一项复杂的系统工程&#xff0c;需要把安全组织体系、安全技术体系和安全管理体系等手段进行有机融合&#xff0c;构建一体化的整体安全屏障。针对网络安全防护&#xff0c;美国曾提出多个网络安全体系模型和架构&#xff0c;其中比较经典的包括PDRR模型、P2DR模…

Revit SDK 介绍:AvoidObstruction 避免碰撞

前言 这个例子介绍如何让碰撞在一起的管道避免碰撞&#xff0c;即对管道进行调整。 内容 调整前&#xff1a; 调整后&#xff1a; 从结果来看&#xff0c;所有的碰撞都被调整了。作为一个例子&#xff0c;不会去考虑是否合理&#xff0c;仅仅是展示了一下 Revit API 的能…

我开课了!《机器学习》公益课9月4日开课

我是黄海广&#xff0c;大学老师&#xff0c;我上的一门课叫《机器学习》&#xff0c;本科生学机器学习有点难&#xff0c;但也不是没有可能&#xff0c;我在摸索中&#xff0c;设计适合本科生的机器学习课程&#xff0c;写了教材&#xff0c;录了视频&#xff0c;做了课件。我…

手写Openfeign实现原理——极简版

文章目录 前言Openfeign实现思路前期准备基本依赖项 开始实现自定义注解自定义代理类定义创建代理对象的工厂InstantiationAwareBeanPostProcessor实现bean的注入OpenInstantiationAwareBeanPostProcessor 自定义 feign接口启动类小结 踩坑记录ImportComponent和Configuration区…

HTTP与SOCKS5的区别对比

在互联网世界中&#xff0c;服务器是一种重要的工具&#xff0c;可以帮助我们提高网络安全性等。今天&#xff0c;我们将重点关注两种常见的技术&#xff1a;HTTP和SOCKS5。让我们深入了解它们的工作原理、用途和优缺点&#xff0c;并通过Python代码示例学习如何使用它们。 HT…

一文了解tcp/ip协议的运行原理

接触代理ip的人都了解https/sock5等ip协议&#xff0c;那么TCP/IP 协议又是什么&#xff1f; 一、什么是TCP/IP 协议&#xff1f; TCP/IP 协议实际上是一系列网络通信协议的一个统称&#xff0c;他负责具体的数据传输工作&#xff0c;核心的两个协议包括TCP以及IP&#xff0c…

Unity3D 如何在ECS架构下,用Unity引擎进行游戏开发详解

前言 Unity3D是一款强大的游戏引擎&#xff0c;它提供了丰富的功能和工具&#xff0c;可以帮助开发者快速构建高质量的游戏。而Entity Component System&#xff08;ECS&#xff09;是Unity3D中一种新的架构模式&#xff0c;它可以提高游戏的性能和可扩展性。本文将详细介绍在…