K-Means聚类

K-means算法是经典的基于划分的聚类方法

基本思想

以空间中的k个点为中心进行聚类,对最靠近它们的对象归类,类别数为k。不断迭代,逐次更新各聚类中心的值,直至得到最好的聚类结果。
最终的k个聚类具有以下特点

各聚类本身尽可能的紧凑,而各聚类之间尽可能的分开。该算法的最大优势在于简洁和快速,算法的关键在于预测可能分类的数量以及初始中心和距离公式的选择。

算法描述

假设要把样本集分为k个类别
(1)初始时随机地从样本集D={X1,X2,...,Xm}中选择k个点作为k个类的初始聚类中心;
(2)在第i次迭代中,对任意一个样本点,求其到聚类k个中心的距离,将该样本点归到距离最短的聚类中心所在的类;
(3)利用均值等方法更新该类的聚类中心;
(4)对于所有的k个聚类中心,如果利用(2)(3)的迭代法更新后,值保持不变或相差很小,则迭代结束,否则继续迭代。

局限

K-Means是线性分类器,对于线性不可分数据就会失效,如

K-Means数学依据

样本集:D=\left \{ X_{1},X_{2},...,{X_{m}} \right \}

聚类中心集合:U=\left \{ U_{1},U_{2},...,U_{k} \right \}

簇的集合:C=\left \{ C_{1},C_{2},...,C_{k} \right \}

要将样本点划分成K类,我们希望每个样本点离它所以簇的聚类中心越近越好,即minE=\sum_{i=1}^{k}\sum_{X\in C_{i}}\left \| X-U_{i} \right \|_{2}^{2} , 其中U_{i}=\frac{1}{|C_{i}|}\sum_{X\in C_{i}}X 。E越小,簇内相似度越高。

图像分割

图像分割即把图像分割成若干不相交的区域,实质是像素的聚类过程,是图像处理的一种方法。可分为:

  1. 基于区域技术,如聚类算法
  2. 基于边缘技术 
  • 利用opencv2实现k-means

cv2.kmeans(data, K, bestLabels, criteria, attempts, flags)

参数: data: 分类数据,最好是np.float32的数据,每个特征放一列。

K: 分类数,opencv2的kmeans分类是需要已知分类数的。

bestLabels:预设的分类标签或者None

criteria:迭代停止的模式选择,这是一个含有三个元素的元组型数。格式为(type, max_iter, epsilon) 其中,type有如下模式: —–cv2.TERM_CRITERIA_EPS :精确度(误差)满足epsilon停止。 —-cv2.TERM_CRITERIA_MAX_ITER:迭代次数超过max_iter停止。 —-cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER,两者合体,任意一个满足结束。

attempts:重复试验kmeans算法次数,将会返回最好的一次结果

flags:初始中心选择,有两种方法: ——cv2.KMEANS_PP_CENTERS; ——cv2.KMEANS_RANDOM_CENTERS

 

返回值: compactness:紧密度,返回每个点到相应重心的距离的平方和

labels:结果标记,每个成员被标记为0,1等 centers:由聚类的中心组成的数组 '''

  • 对灰度图像进行分割

import cv2
import matplotlib.pyplot as plt
import numpy as np


def seg_kmeans_gray():
    #读取图片
    img = cv2.imread('pic.jpg', cv2.IMREAD_GRAYSCALE)

    # 展平
    img_flat = img.reshape((img.shape[0] * img.shape[1], 1))
    img_flat = np.float32(img_flat)

    # 迭代参数
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TermCriteria_MAX_ITER, 20, 0.5)
    flags = cv2.KMEANS_RANDOM_CENTERS

    # 进行聚类
    compactness, labels, centers = cv2.kmeans(img_flat, 2, None, criteria, 10, flags)

    # 显示结果
    img_output = labels.reshape((img.shape[0], img.shape[1]))
    plt.subplot(121), plt.imshow(img, 'gray'), plt.title('input')
    plt.subplot(122), plt.imshow(img_output, 'gray'), plt.title('kmeans')
    plt.show()


if __name__ == '__main__':
    seg_kmeans_gray()
  • 对彩色图像进行聚类

import cv2
import matplotlib.pyplot as plt
import numpy as np

def seg_kmeans_color():
    img = cv2.imread('pic.png', cv2.IMREAD_COLOR)
    # 变换图像通道bgr->rgb
    b, g, r = cv2.split(img)
    img = cv2.merge([r, g, b])

    # 3个通道展平
    img_flat = img.reshape((img.shape[0] * img.shape[1], 3))
    img_flat = np.float32(img_flat)

    # 迭代参数
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TermCriteria_MAX_ITER, 20, 0.5)
    flags = cv2.KMEANS_RANDOM_CENTERS

    # 聚类,这里k=2
    compactness, labels, centers = cv2.kmeans(img_flat, 2, None, criteria, 10, flags)

    # 显示结果
    img_output = labels.reshape((img.shape[0], img.shape[1]))
    plt.subplot(121), plt.imshow(img), plt.title('input')
    plt.subplot(122), plt.imshow(img_output, 'gray'), plt.title('kmeans')
    plt.show()


if __name__ == '__main__':
    seg_kmeans_color()

效果图: 

    

  •  补:k-means处理文本信息

https://blog.csdn.net/wangqianqianya/article/details/88074545

Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐