机器学习-聚类算法Kmeans【手撕】

news/2024/5/20 9:22:51 标签: 机器学习, 算法, 聚类

聚类算法

在训练时,使用没有标签的数据集进行训练,希望在没有标签的数据里面可以发现潜在的一些结构。
其中使用范围较广的是,聚类算法聚类算法的目的是将数据划分成有意义或有用的组(或簇)。这种划分可以基于我们的业务需求或建模需求来完成,也可以单纯地帮助我们探索数据的自然结构和分布。比如在商业中,如果我们手头有大量 的当前和潜在客户的信息,我们可以使用聚类将客户划分为若干组,以便进一步分析和开展营销活动,最有名的客户价值判断模型RFM,就常常和聚类分析共同使用。再比如,聚类可以用于降维和矢量量化(vector quantization),可以将高维特征压缩到一列当中,常常用于图像,声音,视频等非结构化数据,可以大幅度压缩数据量。

Kmeans

作为聚类算法的典型代表,KMeans可以说是最简单的聚类算法没有之一。
聚类算法中,有两个概念非常重要:簇和质心
聚类算法将一组 N N N个样本的特征矩阵 X X X划分为 K K K个无交集的簇,直观上来看是簇是一组一组聚集在一起的数据,在一个簇中的数据就认为是同一类。簇就是聚类的结果表现。簇中所有数据的均值通常被称为这个簇的“质心”(centroids)。在一个二维平面中,一簇数据点的质心的横坐标就是这一簇数据点的横坐标的均值,质心的纵坐标就是这一簇数据点的纵坐标的均值。同理可推广至高维空间。
Kmeans算法中,步骤可以分为四步:
(1)数据预处理。主要是标准化,异常点过滤
(2)随机选取K个中心,计为 μ 1 ( 0 ) \mu^{(0)}_1 μ1(0), μ 2 ( 0 ) \mu^{(0)}_2 μ2(0),…, μ k ( 0 ) \mu^{(0)}_k μk(0)
(3)定义损失: J ( c , μ ) = m i n ∑ i = 1 M ∣ ∣ x i − μ c i ∣ ∣ 2 J(c,\mu) = min \sum^M_{i=1}||x_i - \mu_{c_i}||^2 J(c,μ)=mini=1M∣∣xiμci2
(4)令 t = 0 , 1 , 2 , . . . , k t=0,1,2,...,k t=0,1,2,...,k为迭代步数,重复如下过程直至 J J J收敛:
(4.1)对于每一个样本 x i x_i xi,将其分配到距离最近的中心: c i t < − a r g m i n ∣ ∣ x i − μ k t ∣ ∣ 2 c^t_i < - argmin||x_i - \mu^t_k||^2 cit<argmin∣∣xiμkt2
(4.2)对于每个类中心点 k k k,重新计算该类的中心: μ k ( t + 1 ) < − a r g m i n ∑ i : c i t = k k ∣ ∣ x i − μ ∣ ∣ 2 \mu_k^{(t+1)}<-argmin\sum^k_{i:c_i^t = k}||x_i - \mu||^2 μk(t+1)<argmini:cit=kk∣∣xiμ2

KMeans最核心的部分就是先固定中心点,调整每个样本所属的类别来减少 J J J;再固定每个样本的类别,调整中心点继续减小 J J J 。两个过程交替循环, J J J单调递减直到最(极)小值,中心点和样本划分的类别同时收敛。

聚类算法如何评价

聚类算法聚出的类有什么含义呢?这些类有什么样的性质?我们认为,被分在同一个簇中的数据是有相似性的,而不同簇中的数据是不同的,当聚类完毕之后,我们就要分别去研究每个簇中的样本都有什么样的性质,从而根据业务需求制定不同的商业或者科技策略。这个听上去和我们在上周的评分卡案例中讲解的“分箱”概念有些类似,即我们分箱的目的是希望,一个箱内的人有着相似的信用风险,而不同箱的人的信用风险差异巨大,以此来区别不同信用度的人,因此我们追求“组内差异小,组间差异大”。聚类算法也是同样的目的,我们追求“簇内差异小,簇外差异大”。而这个“差异“,由样本点到其所在簇的质心的距离来衡量。

对于一个簇来说,所有样本点到质心的距离之和越小,我们就认为这个簇中的样本越相似,簇内差异就越小。而距离的衡量方法有多种,令 x x x表示簇中的一个样本点, μ \mu μ表示该簇中的质心, n n n表示每个样本点中的特征数目, i i i表示组 x x x成点的每个特征,则该样本点到质心的距离可以由以下距离来度量:

欧式距离:
d ( x , μ ) = ∑ i = 1 n ( x i − μ ) 2 d(x,\mu) = \sqrt{\sum^n_{i=1}(x_i - \mu)^2} d(x,μ)=i=1n(xiμ)2
曼哈顿距离:
d ( x , μ ) = ∑ i = 1 n ( ∣ x i − μ ∣ ) d(x,\mu) = \sum^n_{i=1}(|x_i - \mu|) d(x,μ)=i=1n(xiμ)
余弦距离:
c o s θ = ∑ 1 n ( x i ∗ μ ) ∑ i = 1 n ( x i ) 2 ∗ ∑ i = 1 n ( μ ) 2 cos\theta = \frac{\sum^n_1(x_i * \mu)}{ \sqrt{\sum^n_{i=1}(x_i)^2} * \sqrt{\sum^n_{i=1}(\mu)^2}} cosθ=i=1n(xi)2 i=1n(μ)2 1n(xiμ)

如我们采用欧几里得距离,则一个簇中所有样本点到质心的距离的平方和为:
C l u s t e r S u m o f S q u a r e ( C S S ) = ∑ j = 0 m ∑ i = 1 n ( x i − μ i ) 2 T o t a l C l u s t e r S u m o f S q u a r e = ∑ l = 1 k C S S l Cluster Sum of Square(CSS) = \sum^m_{j=0} \sum^n_{i=1}(x_i - \mu_i)^2 \\ Total Cluster Sum of Square = \sum^k_{l=1} CSS_l ClusterSumofSquare(CSS)=j=0mi=1n(xiμi)2TotalClusterSumofSquare=l=1kCSSl
其中, m m m为一个簇中样本的个数, j j j是每个样本的编号。这个公式被称为簇内平方和(cluster Sum of Square),又叫做Inertia。而将一个数据集中的所有簇的簇内平方和相加,就得到了整体平方和(Total Cluster Sum of Square),又叫做total inertia。Total Inertia越小,代表着每个簇内样本越相似,聚类的效果就越好。因此KMeans追求的是,求解能够让Inertia最小化的质心。实际上,在质心不断变化不断迭代的过程中,总体平方和是越来越小的。我们可以使用数学来证明,当整体平方和最小的时候,质心就不再发生变化了。如此,K-Means的求解过程,就变成了一个最优化问题。

代码

import numpy as np
import matplotlib.pyplot as plt
 
# 生成随机数据
np.random.seed(0)
X = np.random.rand(100, 2)
 
# 定义K值和迭代次数
K = 3
max_iterations = 100
 
# 随机初始化簇中心点
centers = X[np.random.choice(X.shape[0], K, replace=False)]
 
# 迭代更新簇中心点
for _ in range(max_iterations):
    # 计算每个数据点到每个簇中心点的欧氏距离
    distances = np.linalg.norm(X[:, np.newaxis, :] - centers, axis=2)
    
    # 分配每个数据点到最近的簇
    labels = np.argmin(distances, axis=1)
    
    # 更新簇中心点为每个簇的平均值
    new_centers = np.array([X[labels == k].mean(axis=0) for k in range(K)])
    
    # 如果簇中心点不再改变,结束迭代
    if np.all(centers == new_centers):
        break
    
    centers = new_centers

参考

【手撕】K-measn算法及python代码实现及改进_k-means手撕代码-CSDN博客
菜菜的scikit-learn课堂


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

相关文章

星际探险家

你是一个智能体,对于一切输入信息都是按照如下方式处理:输入信息:信息1 ,目的识别结果:有(没有就提取目的)提取信息1中目的相关有效信息,并设计和搜索达到完成目的的步骤和如何检测目的是否完成的步骤,执行步骤并达到目的,检测目标是否实现 实现则结束, 没有实现则检…

Android Room数据库异常: Room cannot verify the data integrity.

文章目录 一、前言二、错误信息如下三、参考链接 一、前言 在Room数据库结构变动的情况下&#xff0c;如果没有进行Room数据库升级迁移&#xff0c;则会报错Room cannot verify the data integrity.。在实际开发过程中&#xff0c;数据库结构会经常变化&#xff0c;直到发版。…

Redis stream特性了解

在发布订阅中我们了解到发布订阅模式存在的无法持久化保存消息和对于离线重连的客户端不能读取历史消息的缺陷&#xff0c;以下就来了解一下stream是如何解决这个问题的 steam是类似于仅添加log的数据结构&#xff0c;提供了以下基本命令 XADD: 添加新条目到stream # 语法xadd…

设计一个支持并发的前端缓存接口

文章目录 一、概述二、并发缓存2.1、问题2.2、思考2.3、优化 三、总结四、最后 一、概述 缓存池不过就是一个map&#xff0c;存储接口数据的地方&#xff0c;将接口的路径和参数拼到一块作为key&#xff0c;数据作为value存起来罢了&#xff0c;这个咱谁都会。 const cacheMa…

【Linux取经路】进程控制——进程等待

文章目录 一、进程创建1.1 初识 fork 函数1.2 fork 函数返回值1.3 写时拷贝1.4 fork 的常规用法1.5 fork 调用失败的原因1.6 创建一批进程 二、进程终止2.1 进程退出场景2.2 strerror函数2.3 errno全局变量2.4 程序异常2.5 进程常见退出方法2.6 exit 函数2.7 _exit 函数和 exit…

MySQL 8.0 安装脚本

1 下载安装包 首先&#xff0c;我们下载MySQL 8.0.25的安装包&#xff1a; wget https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.25-linux-glibc2.12-x86_64.tar.xz 再解压这个xz文件 xz -d mysql-8.0.25-linux-glibc2.12-x86_64.tar.xz 2 编辑配置文件模…

【开源】SpringBoot框架开发海南旅游景点推荐系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户端2.2 管理员端 三、系统展示四、核心代码4.1 随机景点推荐4.2 景点评价4.3 协同推荐算法4.4 网站登录4.5 查询景点美食 五、免责说明 一、摘要 1.1 项目介绍 基于VueSpringBootMySQL的海南旅游推荐系统&#xff…

学习前端之HTML5中的`<!DOCTYPE>`声明有什么意义

HTML5中的<!DOCTYPE>声明是用来告诉浏览器当前页面使用的是哪个HTML版本。 它在HTML文档的最开始位置&#xff0c;放在<html>标签之前。 <!DOCTYPE>声明的意义是&#xff1a; 1. 确定浏览器使用正确的解析模式&#xff1a;不同版本的HTML有不同的解析规则…