数理统计之k-means聚类算法及应用

在概率论与数理统计中,我们学习到什么是样本均值,样本方差等统计量

把课本以外一些陌生统计参数写在最前面,后面需要用

1、均方误差:MSE(Mean Squared Error)

\text{MSE= }\frac1m\sum_{i=1}^m\left(y_i-\hat{y}_i\right)^2

其中,为测试集上真实值-预测值。可用做回归预测检验其拟合度

2、均方根误差:RMSE(Root Mean Squard Error)

\mathrm{MSE}=\frac{1}{m}\sum_{i=1}^{m}\left(y_{i}-\hat{y}_{i}\right)^{2}

3、决定系数:R2(R-Square)

\text{R2=}\quad1-\frac{\sum_i(\overset{\wedge}{\operatorname*{y}}_i-y_i)^2}{\sum_i(\overset{-}{\operatorname*{y}}_i-y_i)^2}

SSR为回归平方和,SSE为残差平方和,SST为总离差平方和,三者还存在下列关系:

k-means聚类是一种无监督学习的聚类算法

定义:按照某个特定标准(如距离)把一个数据集分割成不同的类或簇,使得同一个簇内
的数据对象的相似性尽可能大,同时不在同一个簇中的数据对象的差异性也尽可能地大。

K-means聚类算法流程

第一步,确定K值(关键,不同的k值效果大相径庭),即将数据集聚集成K个类,簇或小组;
第二步,从数据集中随机选择K个数据点作为质心(Centroid)或数据中心;
第三步,分别计算每个点到每个质心之间的(欧式)距离,并将每个点划分到离最近质心的小组;
第四步,当每个质心都聚集了一些点后,重新定义算法选出新的质心。(对于每个簇,计算其均值,即得到新的k个质心点);
第五步,迭代执行第三步到第四步,直到迭代终止条件满足为止(分类结果不再变化)。

用数学表达式就是

欧式距离: 

\rho=\sqrt{(x_{2}-x_{1})^{2}+(y_{2}-y_{1})^{2}},|X|=\sqrt{x_{2}^{2}+y_{2}^{2}}

用MATLAB模拟聚类算法

clc,clf;
% 生成15行3列的随机数据矩阵  
rng(20); % 为了可重复性设置随机数生成器的种子  
x = rand(15, 3);  
% 使用kmeans函数进行聚类  
% 'Replicates', 10 表示算法将重复10次,并选择最佳结果  
% 'Display', 'final' 表示仅在聚类结束时显示结果  
[idx, cen] = kmeans(x, 3, 'Replicates', 10, 'Display', 'final');
% 使用k-means聚类   
  
% 计算轮廓值和轮廓系数(如果有相应的函数)   
silhouette(x, idx);  
  
% 设置颜色  
color = ['r', 'g','b']; 
  
% 绘图展示聚类结果  
figure;  
hold on;  
for i = 1:3  
    plot(x(idx == i, 1), x(idx == i, 2), 'Color', color(i), 'LineStyle', 'none', 'Marker', 'x');  
end  
  
% 绘制质心  
plot(cen(:, 1), cen(:, 2), 'Color', 'k', 'LineStyle', 'none', 'Marker', 'o');  
  
hold off;  
grid on;  
title('K-Means Clustering Results');  
xlabel('Feature 1');  
ylabel('Feature 2');  
legend(arrayfun(@(i) sprintf('Cluster %d', i), 1:3, 'UniformOutput', false), 'Location', 'best');

聚类效果评估

聚类的效果可采用误差平方和SSE进行评价,SSE值越小,表示数据点越接近它们的中心点,聚类效果越好。

也可以用轮廓系数,是用于评价聚类效果好坏的一种指标。可以理解为描述聚类后各个类别的轮廓清晰度的指标。

\mathrm{S(i)=\frac{b(i)-a(i)}{\max\{a(i),b(i)\}}}

轮廓系数S的取值范围为[-1, 1],轮廓系数越大聚类效果越好。和相关系数r相类似。

在0附近说明是这个簇的边界,越靠近-1说明这个点不应该属于这个簇,而是别的簇类别里

K-means 聚类算法的应用
K-means 聚类因其简单、高效的特点,在数据分析,图像处理中有着广泛应用,例如在数据分析中可以

1.对消费者数据进行聚类,识别具有相似消费习惯或偏好特征的客户群体,以便制定针对性的营销策略,

2.对文本数据(如新闻文章、网页等)进行聚类,自动划分主题相似的文章类别。
在图像处理中可以对对图像像素进行聚类,实现基于颜色、纹理等特征的区域划分即图像分割
还能对象识别与跟踪:对视频帧中的对象进行聚类,辅助进行运动对象的识别与跟踪。

本文着重讲述k-means聚类算法在图像处理中的应用

  1. 图像分割:K-means聚类算法可以将图像中的像素点分成不同的簇,从而实现图像的分割。这种方法可以用于将图像中的不同对象、区域或特征进行分离,以便进一步分析和处理。
  2. 图像降噪:在图像传输或存储过程中,可能会引入噪声。K-means聚类算法可以帮助去除这些噪声,提高图像质量。通过将相似的像素点聚集在一起,可以有效地减少噪声的影响。
  3. 图像压缩:K-means聚类算法也可以用于图像压缩。通过将相似的像素点聚集在一起,可以减少存储和传输所需的数据量,从而降低图像的大小。
  4. 图像分类:K-means聚类算法可以用于图像分类任务。通过将相似的像素点聚集在一起,可以将图像分为不同的类别,例如动物、植物、建筑物等。这有助于自动化图像识别和分析。 总之,K-means聚类算法在图像处理中有广泛的应用,可以帮助我们更好地理解和分析图像内容。

下面给出手搓代码 

# 图像修复
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
from sklearn.cluster import KMeans
import matplotlib

matplotlib.rc('font', family='Microsoft YaHei')
# 导入图片
# image=np.array(Image.open('huli.png'))
image = Image.open('狐狸.jpg').convert('RGB')  # 降维,这张图片有4个通道
img = np.array(image)  # np.array():将 PIL 图像对象转换为 numpy 数组,从而可以使用 shape 属性来获取图像的维度信息,比如(高度, 宽度, 通道数)
hang, lie, dims = img.shape
print('这张图片的像素矩阵有' + str(hang) + '行,' + str(lie) + '列,' + str(dims) + '通道')

# 构造原始像素矩阵
R = img[:, :, 0]
G = img[:, :, 1]
B = img[:, :, 2]

# 像素拼接
list_R, list_G, list_B = [], [], []  # 二维变一维,有点像矩阵A(:),行向量
for i in range(hang):
    for j in range(lie):
        list_R.append(R[i, j])
        list_G.append(G[i, j])
        list_B.append(B[i, j])
print('像素拼接完成')  # 一共m×n个元素

# 构建像素矩阵,即三维矩阵RGB
A = np.zeros(shape=(dims, len(list_G)))  # 创建一个形状为 (3, m×n) 的空数组
for i in range(A.shape[1]):
    A[0, i] = list_R[i]  # 第一行的元素均为红
    A[1, i] = list_G[i]
    A[2, i] = list_B[i]

# k-means聚类算法
k = 3
Kmeans = KMeans(n_clusters=k, init='random', n_init=10, tol=0.001)
Kmeans.fit(A.T)
label = Kmeans.labels_  # 每个数据点的簇标签
core = Kmeans.cluster_centers_.T  # 簇中心的坐标
print('聚类完成')

# 构建数据矩阵B
B = np.zeros(shape=(A.shape[0], A.shape[1]))
for i in range(A.shape[0]):
    for j in range(A.shape[1]):
        B[i, j] = core[i, label[j]]
R_new = np.zeros(shape=(hang, lie))
G_new = np.zeros(shape=(hang, lie))
B_new = np.zeros(shape=(hang, lie))
for i in range(hang):
    for j in range(lie):
        R_new[i, j] = B[0, hang * i + j]
        G_new[i, j] = B[1, hang * i + j]
        B_new[i, j] = B[2, hang * i + j]
print(R_new.shape)

# 新的图像--新的数据拼接
img_new = np.zeros(shape=(hang, lie, dims))
for i in range(hang):
    for j in range(lie):
        img_new[i, j, 0] = R_new[i, j]
        img_new[i, j, 1] = G_new[i, j]
        img_new[i, j, 2] = B_new[i, j]
print('新的像素矩阵合成完毕')

# 确保图像数据在 [0, 255] 范围内,并将数据类型转换为 uint8
img_new = np.clip(img_new, 0, 255).astype(np.uint8)
plt.subplot(1, 2, 1)
plt.imshow(img)
plt.xlabel('图像分割前的图像', fontsize=12)

plt.subplot(1, 2, 2)
plt.imshow(img_new)
plt.xlabel('图像分割后的图像', fontsize=12)
plt.show()

这里拿小狐狸做实验,发现原本充满噪声的图片经过k-means图像修复,(k=3)时,效果不错

这张是聚类k=6时,把图片分成了6个不同的类。 

后续还会对图像处理,视觉检测方向等做文章,敬请期待~

  • 11
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值