第十五课.K均值算法

news/2024/11/24 17:10:38/

目录

  • K均值算法原理
  • K均值算法的改进:K-means++
  • numpy实现K-means

K均值算法原理

K均值(K-means)算法属于无监督学习中的聚类算法;聚类是根据样本特征向量之间的相似度或距离,将样本数据划分为若干个样本子集,每个子集定义为一个类;相似的样本聚集在相同的类,不相似的样本分散在不同的类。由上面的定义可知,聚类算法只使用了样本的特征向量 x x x,并没有使用样本的标签 y y y,故聚类算法属于无监督学习

样本距离
样本距离越小,样本的相似性越大。K均值聚类使用欧式距离的平方作为样本距离,计算公式如下:
d ( x i , x j ) = ∑ k = 1 m ( x k i − x k j ) 2 = ∣ ∣ x i − x j ∣ ∣ 2 2 d(x_{i},x_{j})=\sum_{k=1}^{m}(x_{ki}-x_{kj})^{2}=||x_{i}-x_{j}||_{2}^{2} d(xi,xj)=k=1m(xkixkj)2=xixj22
x i = [ x 1 i , x 2 i , . . . , x m i ] T , x j = [ x 1 j , x 2 j , . . . , x m j ] T x_{i}=[x_{1i},x_{2i},...,x_{mi}]^{T},x_{j}=[x_{1j},x_{2j},...,x_{mj}]^{T} xi=[x1i,x2i,...,xmi]T,xj=[x1j,x2j,...,xmj]T
如上所述,先计算向量对应元素的差值,然后取平方,最后求和;这个计算过程还可以表示为:先对两个样本的特征向量作差,然后求二范数的平方。

K均值聚类使用欧氏距离的平方表示样本之间的距离或相似度。除此之外,欧氏距离、相关系数、夹角余弦等也可以用来表示两个样本特征向量之间的距离或相似度。

聚类中心
聚类得到的结果是若干样本子集,对样本子集中的特征向量求均值可以得到类中心:
x ‾ G = 1 ∣ G ∣ ∑ i = 1 ∣ G ∣ x i , x i ∈ G \overline{x}_{G}=\frac{1}{|G|}\sum_{i=1}^{|G|}x_{i},x_{i}\in G xG=G1i=1Gxi,xiG
其中, x i x_{i} xi为样本特征向量, ∣ G ∣ |G| G为类别 G G G的样本个数;

算法流程

  • 1.随机选取 K K K 个样本点作为初始聚类中心;
  • 2.计算样本特征向量 x i x_{i} xi 和每个聚类中心 c j c_{j} cj 的距离,计算公式如下:
    d ( x i , c j ) = ∑ k = 1 m ( x k i − c k j ) 2 d(x_{i},c_{j})=\sum_{k=1}^{m}(x_{ki}-c_{kj})^{2} d(xi,cj)=k=1m(xkickj)2
    x i = [ x 1 i , x 2 i , . . . , x m i ] T , c j = [ c 1 j , c 2 j , . . . , c m j ] T x_{i}=[x_{1i},x_{2i},...,x_{mi}]^{T},c_{j}=[c_{1j},c_{2j},...,c_{mj}]^{T} xi=[x1i,x2i,...,xmi]T,cj=[c1j,c2j,...,cmj]T
    i ∈ { 1 , 2 , . . . , n } , j ∈ { 1 , 2 , . . . , K } i\in \left \{1,2,...,n \right \},j\in \left \{1,2,...,K \right \} i{1,2,...,n},j{1,2,...,K} n n n为数据集的样本数, K K K为聚类的类别数;
  • 3.将样本 x i x_{i} xi 划分到离他最近的聚类中心所对应的类中;
  • 4.使用样本特征向量的均值,更新各个聚类中心,均值的计算公式如下:
    x ‾ G = 1 ∣ G ∣ ∑ i = 1 ∣ G ∣ x i , x i ∈ G \overline{x}_{G}=\frac{1}{|G|}\sum_{i=1}^{|G|}x_{i},x_{i}\in G xG=G1i=1Gxi,xiG
    其中, x i x_{i} xi为样本特征向量, ∣ G ∣ |G| G为类别 G G G的样本个数;
  • 5.重复步骤 2~4,直到聚类中心不再变化

K均值算法的改进:K-means++

K 均值聚类的算法流程,由于原理简单、实现方便、模型的可解释性较强,所以比较常用。K均值聚类是通过最小化样本与其所属类中心的距离总和来进行算法迭代,具体做法是:先随机初始化类中心,将样本划分到离他最近的类中心,然后更新类中心,重复上述步骤,直到聚类中心不再变化。

但是K均值算法并不能保证收敛到全局最优,初始类中心的选择会直接影响到聚类的结果。一般来说:相同类中的样本距离较近,不同类中的样本距离较远。因此,初始的各个聚类中心应该越远越好。

K-means++ 算法原理
基于上述观点,K-means++算法针对初始聚类中心的选择做了优化和改进,具体步骤如下:

  • 步骤1:从数据集 X X X 中随机选择一个样本点作为第一个初始类中心 c 1 c_{1} c1
  • 步骤2:计算 X X X 中的每个样本点 x i x_{i} xi 和已有聚类中心的最近样本距离 d ( x i ) d(x_{i}) d(xi)
    假如已经初始化了 3 个聚类中心,则分别计算该样本点和这 3 个聚类中心的样本距离,取其中的最短距离作为计算结果,用数学公式表示如下:
    d ( x i ) = m i n j ∈ { 1 , 2 , 3 } ∣ ∣ x i − c j ∣ ∣ 2 2 d(x_{i})=min_{j\in \left \{1,2,3 \right \}}||x_{i}-c_{j}||_{2}^{2} d(xi)=minj{1,2,3}xicj22
    样本距离是欧氏距离的平方,和 K-means 算法保持一致;
  • 步骤3:计算每个样本点作为聚类中心的概率 p ( x i ) p(x_{i}) p(xi),公式如下:
    p ( x i ) = d ( x i ) ∑ j = 1 n d ( x j ) p(x_{i})=\frac{d(x_{i})}{\sum_{j=1}^{n}d(x_{j})} p(xi)=j=1nd(xj)d(xi)
  • 步骤4:根据 p ( x i ) p(x_{i}) p(xi) 从样本数据中随机选择聚类中心,距离已有聚类中心越远的样本点越有可能称为下一个初始聚类中心;
  • 步骤5:重复步骤 2~4,直到初始聚类中心的数量达到 K K K

除了初始聚类中心的选择,K-means++ 其余部分与 K-means 算法的流程一致;

K-means++ 算法关于初始聚类中心的选择实现如下:

import numpy as np # 欧氏距离的平方
def distance(u,v):'''u,v: 一维 numpy 数组表示的特征向量'''return sum((u-v)**2)def center_init(data,k):'''data: numpy array,样本特征向量集合k: int,聚类中心的个数'''# 用来保存聚类中心center = []# 随机选择一个样本特征向量的索引index = np.random.choice(range(len(data)))# 根据索引获得第一个聚类中心center.append(data[index])# 获取剩余 k-1 个聚类中心for _ in range(k-1):# 样本被选为聚类中心的概率prob = []# 遍历每个样本数据for x in data:# 根据步骤 2 的公式计算样本与最近类中心的距离d = min([distance(x,c) for c in center])prob.append(d)# 计算每个样本的被选概率prob = np.array(prob)/sum(prob)# 根据被选中的概率随机选择一个样本特征向量的索引i = np.random.choice(a=range(len(data)),p=prob)# 根据索引添加一个聚类中心center.append(data[i])# 返回 k 个初始化的聚类中心return np.array(center)

除了初始聚类中心,K值的选择以及样本距离计算方法的选择也会影响到聚类的结果。其中,K值属于超参数,需要根据实际聚类结果来调节

numpy实现K-means

定义函数distance计算样本距离:

def distance(u,v):'''u,v: 一维 numpy 数组表示的特征向量'''# 返回欧氏距离的平方return sum((u-v)**2)

初始化聚类中心:

import numpy as np# 从 data 中随机选择 k 个样本特征向量,作为初始聚类中心
def center_init(data,k):'''data: 存放样本特征向量的 numpy arrayk: 聚类中心的个数'''# 设置随机种子np.random.seed(2021)# 随机选择 k 个样本特征向量的索引index = np.random.choice(a=range(len(data)),size=k)# 根据索引获得 k 个聚类中心return data[index]

样本聚类:

def predict(x,center):'''x: 一维数组表示的样本特征向量center: 存放 k 个聚类中心的数组'''# 输入的样本 x 必须为一维数组,否则触发异常assert np.array(x).ndim==1# 返回距离样本 x 最近的聚类中心索引return np.argmin([distance(x,c) for c in center])

获取聚类中心对应的样本子集:

def cluster(data,center):'''data: 存放样本特征向量的 numpy arraycenter: 存放 k 个聚类中心的数组'''# 存放各类样本子集的字典:key = 聚类中心索引; value = data 子集center_data = dict()# 遍历样本特征向量for x in data:# 获取样本 x 的聚类索引i =  predict(x,center)# 将 x 添加到聚类索引对应的样本子集中"""D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in DD.get(k[,d]) -> D[k] if k in D, else d.  d defaults to None."""center_data.setdefault(i,[])center_data[i].append(x)# 返回各聚类中心对应的样本子集return center_data

聚类可视化,二维空间可视化:

import matplotlib.pyplot as pltdef visualization_2D(center,center_data):'''center: 存放 k 个聚类中心的数组center_data: 聚类中心对应的样本子集的集合'''# 设置画布大小plt.figure(figsize=(8,6))# 设置可选颜色:红、绿、蓝color = ['r','g','b']# 遍历每个聚类中心的索引for i in center_data:# 根据索引,取该聚类中心对应的样本第一列特征x = np.array(center_data[i])[:,0]# 根据索引,取该聚类中心对应的样本第二列特征y = np.array(center_data[i])[:,1]# 绘制当前聚类的样本散点图,s 控制大小,c 控制颜色plt.scatter(x,y,s=30,c=color[i])# 遍历每个聚类中心 c 和对应的索引 ifor i,c in enumerate(center):# 在二维平面上绘制聚类中心,alpha 控制透明度plt.scatter(x=c[0],y=c[1],s=200,c=color[i],alpha=0.2)# 显示图片plt.show()

三维空间可视化:

from mpl_toolkits import mplot3ddef visualization_3D(center,center_data):'''center: 存放 k 个聚类中心的数组center_data: 聚类中心对应的样本子集'''# 取第一个聚类的样本子集,若样本的特征维数小于 3if np.array(center_data[0]).shape[1] < 3:# 则返回空值,放弃三维可视化return None# 设置画布大小plt.figure(figsize=(10,8))# 设置可选颜色:红、绿、蓝color = ['r','g','b']# 创建三维空间直角坐标系ax = plt.axes(projection='3d')# 遍历每个聚类中心的索引for i in center_data:# 根据索引,取该聚类中心对应的样本第一列特征x = np.array(center_data[i])[:,0]# 根据索引,取该聚类中心对应的样本第二列特征y = np.array(center_data[i])[:,1]# 根据索引,取该聚类中心对应的样本第三列特征z = np.array(center_data[i])[:,2]# 绘制当前聚类的样本散点图,s 控制大小,c 控制颜色ax.scatter3D(x,y,z,s=30,c=color[i])# 遍历每个聚类中心 c 和对应的索引 ifor i,c in enumerate(center):# 在三维空间中绘制当前聚类中心,alpha 控制透明度ax.scatter3D(xs=c[0],ys=c[1],zs=c[2],s=200,c=color[i],alpha=0.2)# 显示图片plt.show()

算法迭代:

def fit(data,k,visualization=None):'''data: 存放样本特征向量的 numpy arrayvisualization: 可视化选项,默认为 None,不对聚类过程做可视化'''# 初始化聚类中心center = center_init(data,k)# 循环迭代while True:# 根据已有的聚类中心将样本划分到不同的聚类集合中center_data = cluster(data,center)# 当前聚类中心和样本特征向量在二维空间的可视化 if visualization == '2d':visualization_2D(center,center_data)# 当前聚类中心和样本特征向量在三维空间的可视化 if visualization == '3d':visualization_3D(center,center_data)# 保存上一次迭代的聚类中心old_center = center.copy()# 遍历各个聚类中心的索引for i in center_data:# 更新每一个聚类中心:样本子集特征向量的均值center[i] = np.mean(center_data[i],axis=0)# 循环迭代的停止条件:最近两次迭代,聚类中心的位置不再变化if sum([distance(center[i],old_center[i]) for i in range(k)]) == 0:breakreturn center,center_data

算法实例:

x1 = [1,2,4,5,7,8,9,3,6]
x2 = [2,2,5,7,1,3,5,2,6]
data = np.array([i for i in zip(x1,x2)])
"""
array([[1, 2],[2, 2],[4, 5],[5, 7],[7, 1],[8, 3],[9, 5],[3, 2],[6, 6]])
"""# 聚类簇数
k = 3
# 获取最终的聚类中心和对应的样本子集,并对聚类过程可视化
center,center_data = fit(data,k,visualization='2d')
# 聚类中心和样本特征向量在二维空间的最终可视化 
visualization_2D(center,center_data)

fig1


http://www.ppmy.cn/news/231428.html

相关文章

bootstrapTable参数及事件详解

表的各项(Table options ) 定义在 jQuery.fn.bootstrapTable.defaults 文件内 名称属性类型默认值作用描述-data-toggleStringtable只要引入 jquery、bootstrap 、bootstrap-table的包&#xff0c;不用在js里面定义就可以使用 默认有写data-toggle”table”,data-toggle应该知道…

KNN(K最邻近分类算法)

K最近邻&#xff08;KNN&#xff0c;K-NearestNeighbor&#xff09;分类算法&#xff0c;是比较经典的分类算法&#xff0c;是将数据集合中每一个记录进行分类的方法&#xff0c;属于懒惰性学习算 法&#xff0c;只有当需要分类的向量到达时才开始构造泛化模型。是数据挖掘分类…

学习TensorFlow,TensorBoard可视化网络结构和参数

在学习深度网络框架的过程中&#xff0c;我们发现一个问题&#xff0c;就是如何输出各层网络参数&#xff0c;用于更好地理解&#xff0c;调试和优化网络&#xff1f;针对这个问题&#xff0c;TensorFlow开发了一个特别有用的可视化工具包&#xff1a;TensorBoard&#xff0c;既…

TensorFlow系列:TensorBoard可视化网络结构和参数

转自&#xff1a;https://blog.csdn.net/helei001/article/details/51842531 在学习深度网络框架的过程中&#xff0c;我们发现一个问题&#xff0c;就是如何输出各层网络参数&#xff0c;用于更好地理解&#xff0c;调试和优化网络&#xff1f;针对这个问题&#xff0c;Tensor…

深度学习基础:卷积与转置卷积、计算量与参数量、argparse库、信息熵(KL散度及交叉熵)、hook机制、top_k和AvgrageMeter函数(持续更新)

深度学习模型基础知识汇总&#xff08;持续更新&#xff09; 文章目录 一、卷积和转置卷积1、基本概念2、输出尺寸的计算公式3、nn.Conv2d、nn.ConvTranspose2d的参数k,s,p在图形上的含义&#xff0c;卷积运算过程 二、模型计算量(FLOPs)和参数量(Params)三、python的argparse…

HyperOpt参数优化

版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接和本声明。 本文链接&#xff1a; https://blog.csdn.net/u012735708/article/details/84820101 当我们创建好模型后&#xff0c;还要调整各个模型的参数&a…

机器学习之K近邻法(KNN)

目录 一、基本概念&#xff1a; 二、距离的计算方式&#xff1a; 三、k的选取: 四、特征归一化&#xff1a; 五、交叉验证&#xff1a; 一、基本概念&#xff1a; k近邻算法是一种基本分类和回归方法。这里只讨论分类问题的k近邻法。 k近邻算法&#xff0c;即是给定一个…

python位置参数错误_python – 函数缺少2个必需的位置参数:’x’和’y’

我正在尝试编写一个绘制Spirograph的Python龟程序,我不断收到此错误: Traceback (most recent call last): File "C:\Users\matt\Downloads\spirograph.py", line 36, in main() File "C:\Users\matt\Downloads\spirograph.py", line 16, in main spirog…