《机器学习公式推导与代码实现》chapter17-kmeans

news/2024/5/20 9:22:37 标签: 机器学习, kmeans, 算法, python, 聚类, 数据挖掘

机器学习公式推导与代码实现》学习笔记,记录一下自己的学习过程,详细的内容请大家购买作者的书籍查阅。

聚类分析和k均值聚类算法

聚类分析(cluster analysis)是一类经典的无监督学习算法,在给定样本的情况下,聚类分析通过度量特征相似度或者距离,将样本自动划分为若干类别。

1 距离度量和相似度度量方式

距离度量和相似度度量是聚类分析的核心概念,大多数聚类算法建立在距离度量之上。常用的距离度量方式包括闵氏距离马氏距离,常用的相似度度量方式包括相关系数夹角余弦等。

(1) 闵氏距离闵可夫斯基距离(Minkowski distance),该距离定义如下,给定m维向量样本集合X,对于xixjXxi=(x1i,x2i,...xmi)T,那么样本xi与样本xj的闵氏距离可定义为:
d i j = ( ∑ k = 1 m ∣ x k i − x k j ∣ p ) 1 p , p ≥ 1 d_{ij}=\left ( \sum_{k=1}^{m}\left | x_{ki}-x_{kj} \right | ^{p} \right )^{\frac{1}{p} }, p\ge 1 dij=(k=1mxkixkjp)p1,p1
可以简单看出,当p=1时,闵氏距离就变成了曼哈顿距离(Manhatan distance):
d i j = ∑ k = 1 m ∣ x k i − x k j ∣ d_{ij}=\sum_{k=1}^{m}\left | x_{ki}-x_{kj} \right | dij=k=1mxkixkj
p=2时,闵氏距离就变成了欧氏距离(Euclidean distance):
d i j = ( ∑ k = 1 m ∣ x k i − x k j ∣ 2 ) 1 2 d_{ij}=\left ( \sum_{k=1}^{m}\left | x_{ki}-x_{kj} \right | ^{2} \right )^{\frac{1}{2} } dij=(k=1mxkixkj2)21
p=∞时,闵氏距离也称切比雪夫距离(Chebyshev distance):
d i j = m a x ∣ x k i − x k j ∣ d_{ij}=max\left | x_{ki}-x_{kj} \right | dij=maxxkixkj
(2) 马氏距离全称马哈拉诺比斯距离(Mahalanobis distance),是一种衡量各个特征之间相关性的聚类度量方式。给定一个样本集合X=(xij)mxn,假设样本的协方差矩阵为S,那么样本xi与样本xj之间的马氏距离可以定义为:
d i j = [ ( x i − x j ) T S − 1 ( x i − x j ) ] 1 2 d_{ij}=\left [\left(x_{i}-x_{j}\right)^{T} S^{-1}\left(x_{i}-x_{j}\right)\right] ^{\frac{1}{2}} dij=[(xixj)TS1(xixj)]21
S为单位矩阵,即样本的各特征之间相互独立且方差为1时,马氏距离就是欧氏距离。

(3) 相关系数(correlation coefficent)是度量样本相似度最常用的方式。相关系数有多种定义方式,较为常用的是皮尔逊相关系。相关系数越接近1,两个样本越相似;样本xi与样本xj之间的相关系数可定义为:
r i j = ∑ k = 1 m ( x k i − x ˉ i ) ( x k j − x ˉ j ) [ ∑ k = 1 m ( x k i − x ˉ i ) 2 ∑ k = 1 m ( x k j − x ˉ j ) 2 ] 1 2 r_{ij}=\frac{\sum_{k=1}^{m}\left ( x_{ki}-\bar{x}_{i}\right )\left ( x_{kj}-\bar{x}_{j}\right )}{\left [ \sum_{k=1}^{m} \left ( x_{ki}-\bar{x}_{i}\right )^{2} \sum_{k=1}^{m} \left ( x_{kj}-\bar{x}_{j}\right )^{2} \right ] ^{\frac{1}{2} } } rij=[k=1m(xkixˉi)2k=1m(xkjxˉj)2]21k=1m(xkixˉi)(xkjxˉj)
上边这个式子看起来有点复杂,其实就是:
r ( X , Y ) = C o v ( X , Y ) V a r [ X ] V a r [ Y ] r\left ( X,Y \right ) =\frac{Cov\left ( X,Y \right ) }{\sqrt{Var\left [ X \right ] Var\left [ Y \right ] } } r(X,Y)=Var[X]Var[Y] Cov(X,Y)
(4) 余弦夹角(angle cosine)也是度量两个样本相似度的方式。夹角余弦越接近1,表示两个样本越相似:
s i m i l a r i t y = c o s ( θ ) = A ⋅ B ∥ A ∥ ∥ B ∥ similarity=cos\left ( \theta \right ) =\frac{A\cdot B}{\left\|A\right\|\left\|B\right\|} similarity=cos(θ)=ABAB
样本xi与样本xj之间的夹角余弦可定义为:
A C i j = ∑ k = 1 m x k i x k j [ ∑ k = 1 m x k i 2 ∑ k = 1 m x k j 2 ] 1 2 AC_{ij}=\frac{\sum_{k=1}^{m}x_{ki}x_{kj}}{\left [ \sum_{k=1}^{m}x_{ki}^{2} \sum_{k=1}^{m}x_{kj}^{2}\right ] ^{\frac{1}{2}}} ACij=[k=1mxki2k=1mxkj2]21k=1mxkixkj

2 聚类算法一览

聚类算法将相似的样本归入同一个簇(cluster)中,这使得同一个簇中的样本对象的相似度尽可能大,同时不同簇中的样本对象的差异性也尽可能大。常用的聚类算法有如下几种:

在这里插入图片描述
sklearn在不同数据集上的10类聚类算法效果对比。

3 K-means算法原理

在这里插入图片描述

4 K-means算法numpy实现

python">import numpy as np

# 定义欧氏距离
def euclidean_distance(x, y):
    
    distance = 0
    for i in range(len(x)):
        distance += np.power((x[i] - y[i]), 2)
    return np.sqrt(distance)
python"># 质心初始化
def centroids_init(X, k): # 训练样本,质心个数(聚类簇数)

    m, n = X.shape # 样本数和特征数
    centroids = np.zeros((k, n)) # 初始化质心矩阵,大小为质心个数*特征数
    for i in range(k):
        centroid = X[np.random.choice(range(m))]
        centroids[i] = centroid
    return centroids # centroids:质心矩阵,k个长度为n的从m个样本中选取的样本
python"># 求单个样本所属最近质心的索引
def closest_centroid(x, centroids): # 单个样本实例,质心矩阵

    closest_i, closest_dist = 0, float('inf')
    for i, centroid in enumerate(centroids):
        distance = euclidean_distance(x, centroid)
        if distance < closest_dist:
            closest_i = i
            closest_dist = distance
    return closest_i # closest_i:最近质心
python"># 构建簇与分配样本
def build_clusters(centroids, k, X): # 质心矩阵,质心个数, 训练样本

    clusters = [[] for _ in range(k)] # 初始化簇列表
    for x_i, x in enumerate(X):
        centroid_i = closest_centroid(x, centroids) # 样本最近质心的下标
        clusters[centroid_i].append(x_i) # 样本下标加入簇矩阵中
    return clusters # 聚类
python"># 计算新的质心
def calculate_centroids(clusters, k, X):

    n = X.shape[1] # 特征数
    centroids = np.zeros((k, n)) # 初始化质心矩阵
    for i, cluster in enumerate(clusters):
        centroid = np.mean(X[cluster], axis=0) # 计算每个簇的均值作为新的质心
        centroids[i] = centroid # 更新质心矩阵
    return centroids # 返回新的质心矩阵
python"># 获取每个样本所属聚类类别
def get_cluster_labels(clusters, X):

    y_pred = np.zeros(X.shape[0]) # 样本数
    for cluster_i, cluster in enumerate(clusters):
        for sample_i in cluster:
            y_pred[sample_i] = cluster_i
    return y_pred # 预测结果
python"># 封装k-means算法
def kmeans(X, k, max_iterations):

    centroids = centroids_init(X, k) # 训练样本,质心个数(聚类簇数)

    # 迭代至收敛
    for _ in range(max_iterations):
        clusters = build_clusters(centroids, k, X) # 分配样本与构建簇
        new_centroids = calculate_centroids(clusters, k, X) # 计算新的质心
        print(f'迭代进行到第{_}轮')
        diff = centroids - new_centroids
        centroids = new_centroids
        if not diff.any():
            break
    return get_cluster_labels(clusters, X) # 获取每个样本所属聚类类别
python">from sklearn import datasets

# 测试算法
data = datasets.load_iris()
iris, y = data.data, data.target
label_pred = kmeans(iris, 3, 100)

# 取2个或者3个维度来看一下聚类的效果
X = iris[:,2:]
x0 = X[label_pred == 0]
x1 = X[label_pred == 1]
plt.scatter(x0[:, 0], x0[:, 1], c = "red", marker='o', label='label0')
plt.scatter(x1[:, 0], x1[:, 1], c = "green", marker='*', label='label1')
plt.xlabel('petal length')
plt.ylabel('petal width')
plt.legend(loc=2)
plt.show()

在这里插入图片描述

5 基于sklearn的K-means算法

python">from sklearn.cluster import KMeans

kmeans_sk = KMeans(n_clusters=3, random_state=2023).fit(iris)
label_pred = kmeans_sk.labels_ # 打印拟合标签

X = iris[:,2:]
x0 = X[label_pred == 0]
x1 = X[label_pred == 1]
plt.scatter(x0[:, 0], x0[:, 1], c = "red", marker='o', label='label0')
plt.scatter(x1[:, 0], x1[:, 1], c = "green", marker='*', label='label1')
plt.xlabel('petal length')
plt.ylabel('petal width')
plt.legend(loc=2)
plt.show()

在这里插入图片描述
笔记本_Github地址


http://www.niftyadmin.cn/n/461396.html

相关文章

Vue父子组件通讯方式及实现

68. Vue父子组件通讯方式及实现 1. props和$emit 父组件通过props向子组件传递数据&#xff0c;子组件通过$emit触发父组件定义的事件来传递数据。 父组件&#xff1a; <template><div><child-component :message"message" update-message"u…

文件上传漏洞-用骗子的角度分析

&#xff08;一&#xff09;文件上传漏洞 文件上传漏洞&#xff0c;发送在用户上传文件功能中&#xff0c;很多网址都对上传的文件格式进行限制&#xff0c;但是被攻击机者找到漏洞&#xff0c;把木马、病毒进行上传&#xff0c;然后控制服务器。对上传的文件格式不是不限制&a…

012-从零搭建微服务-接口文档(二)

写在最前 如果这个项目让你有所收获&#xff0c;记得 Star 关注哦&#xff0c;这对我是非常不错的鼓励与支持。 源码地址&#xff08;后端&#xff09;&#xff1a;https://gitee.com/csps/mingyue 源码地址&#xff08;前端&#xff09;&#xff1a;https://gitee.com/csps…

切底掌握Android中的Kotlin DSL

前言 在这篇文章中&#xff0c;我们将学习如何在您的 Android 项目中编写 Kotlin DSL。 这个文章会很长&#xff0c;所以花点时间&#xff0c;让我们一起来写你的 DSL。我们将讨论以下主题&#xff0c; 什么是简单英语中的 DSL&#xff1f;您使用任何 DSL 吗&#xff1f;为什…

Chat2DB数据AI工具开源!对数据分析师行业影响如何?

大家好&#xff0c;我是千与千寻&#xff0c;千寻目前在互联网公司担任算法工程师&#xff0c;也要经常性的和数据打交道。那么数据都存放在哪里&#xff1f;当然是数据库啦&#xff01; 说到数据库&#xff0c;我们就不得不提到一种编程语言——SQL数据语言&#xff0c;后端程…

解决阿里云ECS服务器下安装MySQL无法远程连接的问题

场景重现 在阿里云ECS下&#xff0c;Ubuntu系统上通过以下命令安装的MySQL数据库&#xff0c;本地连接正常, 但远程死活连接不上。 ? 1 2 # 安装MySQL apt-get install mysql-server 解决办法 主要有以下几点: 用户root默认受限为本地可访问(localhost), 远程拒绝(出于…

Linux网络-数据链路层,MAC帧解析,ARP协议

目录 数据链路层VS网络层 以太网概念 以太网的帧格式&#xff08;报文格式&#xff09;&#xff08;也可以称之为MAC帧&#xff09; MAC地址的概念 MAC帧格式 局域网通信原理 MTU MTU说明 MTU对IP协议的影响 MTU对UDP协议的影响 MTU对TCP协议的影响 ARP协议 ARP协…

【Django】图形验证码显示及验证

图形验证码显示及验证 开发项目时&#xff0c;在登陆或者注册功能中为防止脚本恶意破坏系统&#xff0c;故而添加图形验证码。 文章目录 图形验证码显示及验证1 安装配置2 验证码显示及正确性验证3 效果显示 1 安装配置 安装第三方库 pip install django-simple-captcha配置s…