机器学习3

理解K-Means聚类

T-shirt尺寸问题

考虑一家公司,该公司将向市场发布新型号的T恤。显然,他们将不得不制造不同尺寸的模型,以满足各种体型的人们的需求;因此,该公司会记录人们的身高和体重数据,并将其绘制到图形上,如下所示:
在这里插入图片描述
公司无法制作所有尺寸的T恤,取而代之的是,将人划分为小,中和大,并仅制造这三种适合所有人的模型。可以通过k均值聚类将人员分为三组,并且算法可以提供最佳的3种大小,这将满足所有人员的需求。如果不满足,公司可以将人员分为更多的组,可能是五个,依此类推。查看下面的图片:
在这里插入图片描述

作用过程

该算法是一个迭代过程,将在图像的帮助下逐步解释它; 考虑如下一组数据(可以将其视为T恤问题),需要将此数据分为两类。
在这里插入图片描述

  1. 算法随机选择两个质心 C 1 C_1 C1 C 2 C_2 C2(有时,将任何两个数据作为质心)。
  2. 计算每个点到两个质心的距离。如果测试数据更接近 C 1 C_1 C1,则该数据标记为“0”。如果它更靠近 C 2 C_2 C2,则标记为“1”(如果存在更多质心,则标记为“2”,“3”等)。
    在示例中,将为所有标记为红色的“0”和所有标记为蓝色的“1”上色;因此,经过以上操作,得到以下图像:
    在这里插入图片描述
  3. 接下来,分别计算所有蓝点和红点的平均值,它们将成为新质心。即 C 1 C_1 C1 C 2 C_2 C2
    转移到新计算的质心(显示的图像不是真实值,也不是真实比例,仅用于演示)。再次使用新的质心执行步骤2,并将标签数据设置为‘0’和‘1’,所以得到如下结果:
    在这里插入图片描述

现在,迭代步骤2和步骤3,直到两个质心都收敛到固定点(或者可以根据提供的标准,例如最大的迭代次数或达到特定的精度等,将其停止)。这些点使测试数据与其对应质心之间的距离之和最小,或者简单地说, C 1 ↔ R e d P o i n t s C_1↔RedPoints C1RedPoints C 2 ↔ B l u e P o i n t s C_2↔BluePoints C2BluePoints之间的距离之和最小。
m i n i m i z e    [ J = ∑ A l l   R e d _ P o i n t s d i s t a n c e ( C 1 , R e d _ P o i n t ) + ∑ A l l   B l u e _ P o i n t s d i s t a n c e ( C 2 , B l u e _ P o i n t ) ] minimize \;\bigg[J = \sum_{All\: Red\_Points}distance(C1,Red\_Point) + \sum_{All\: Blue\_Points}distance(C2,Blue\_Point)\bigg] minimize[J=AllRed_Pointsdistance(C1,Red_Point)+AllBlue_Pointsdistance(C2,Blue_Point)]
最终结果如下所示:
在这里插入图片描述
这仅仅是对K-Means聚类的直观理解,它只是K-Means聚类的宏观层面;此算法有很多部分可以修改,例如如何选择初始质心,如何加快迭代过程等。

OpenCV中的K-Means

理解参数

输入参数

  1. sample:它应该是np.float32数据类型,并且每个功能都应该放在单个列中。
  2. nclusters(K):结束条件所需的簇数
  3. criteria:这是迭代终止条件,满足此条件后,算法迭代将停止;实际上,它应该是3个参数的元组,它们是(type, max_iter, epsilon):
    • type 终止条件的类型,它具有3个标志,如下所示:
      • cv.TERM_CRITERIA_EPS 如果达到指定的精度epsilon,则停止算法迭代。
      • cv.TERM_CRITERIA_MAX_ITER 在指定的迭代次数max_iter之后停止算法。
      • cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER 当满足上述任何条件时,停止迭代。
    • max_iter 一个整数,指定最大迭代次数。
    • epsilon-要求的精度:
      1. attempts:该标志用于指定使用不同的初始标签执行算法的次数,该算法返回产生最佳紧密度的标签,该紧凑性作为输出返回。
      2. flags:此标志用于指定初始中心的获取方式。通常,为此使用两个标志:cv.KMEANS_PP_CENTERScv.KMEANS_RANDOM_CENTERS

输出参数

  1. 紧凑度:它是每个点到其相应中心的平方距离的总和。
  2. 标签:这是标签数组,其中每个元素标记为“0”,“ 1” ,… 。
  3. 中心:这是群集中心的阵列。

应用K-Means算法的三个示例

1.单特征数据

考虑一下,有一组仅具有一个特征(即一维)的数据。例如,可以解决T恤问题,只用身高来决定T恤的尺寸。
因此,首先创建数据并将其绘制在Matplotlib中:

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

x = np.random.randint(25, 100, 25)
y = np.random.randint(175, 255, 25)
z = np.hstack((x, y))
z = z.reshape((50, 1))
z = np.float32(z)
plt.hist(z, 256, [0, 256])
plt.show()

有了“ z”,它是一个大小为50的数组,值的范围是0到255。将“z”重塑为列向量,如果存在多个特征,它将更加有用。然后制作了np.float32类型的数据,得到以下图像:
在这里插入图片描述

现在应用KMeans函数。在此之前,需要指定标准;标准是,每当运行10次算法迭代或达到epsilon = 1.0的精度时,就停止算法并返回答案。

# 定义终止标准
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 10, 1.0)
# 设置标志
flags = cv.KMEANS_RANDOM_CENTERS
# 应用K均值
compactness, labels, centers = cv.kmeans(z, 2, None, criteria, 10, flags)

得到了紧凑度,标签和中心。在这种情况下,得到的中心分别为60和212。标签的大小将与测试数据的大小相同,其中每个数据的质心都将标记为“ 0”,“ 1”,“ 2”等。现在,根据标签将数据分为不同的群集;用红色绘制A,用蓝色绘制B,用黄色绘制其质心并显示。

A = z[labels == 0]
B = z[labels == 1]
# 现在用红色绘制'A',用蓝色绘制'B',用黄色绘制中心
plt.hist(A, 256, [0, 256], color='r')
plt.hist(B, 256, [0, 256], color='b')
plt.hist(centers, 32, [0, 256], color='y')
plt.show()

在这里插入图片描述

2. 多特征数据

在前面的示例中,仅考虑了T恤问题中的身高。在这里,将同时考虑身高和体重,即两个特征。 在以前的情况下,将数据制作为单个列向量;每个特征排列在一列中,而每一行对应于一个输入测试样本。 例如,在这种情况下,设置了一个大小为50x2的测试数据,即50人的身高和体重。第一列对应于全部50个人的身高,第二列对应于他们的体重。第一行包含两个元素,其中第一个是第一个人的身高,​​第二个是他的体重;类似地,剩余的行对应于其他人的身高和体重。查看下面的图片:
在这里插入图片描述
multi_feature_data.py

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

X = np.random.randint(25, 50, (25, 2))
Y = np.random.randint(60, 85, (25, 2))
Z = np.vstack((X, Y))
# 将数据转换为np.float32
Z = np.float32(Z)
# 定义停止标准,应用K均值
criteria = (cv.TermCriteria_EPS + cv.TermCriteria_MAX_ITER, 10, 1.0)
ret, label, center = cv.kmeans(Z, 2, None, criteria, 10, cv.KMEANS_RANDOM_CENTERS)
# 现在分离数据, 注意flatten()
A = Z[label.ravel() == 0]
B = Z[label.ravel() == 1]
# 绘制数据
plt.scatter(A[:, 0], A[:, 1])
plt.scatter(B[:, 0], B[:, 1], c = 'r')
plt.scatter(center[:, 0], center[:, 1], s = 80, c = 'y', marker = 's')
plt.xlabel('Height'), plt.ylabel('Weight')
plt.show()

在这里插入图片描述

3. 颜色量化

颜色量化是减少图像中颜色数量的过程,这样做的原因之一是减少内存。有时,某些设备可能会受到限制,因此只能产生有限数量的颜色;在这些情况下,也会执行颜色量化。
在这里,使用k均值聚类进行颜色量化。有3个特征,例如R,G,B;因此,需要将图像重塑为Mx3大小的数组(M是图像中的像素数)。在聚类之后,将质心值(也是R,G,B)应用于所有像素,以使生成的图像具有指定数量的颜色。同样,需要将其重塑为原始图像的形状。下面是代码color_quantization.py:

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

img = cv.imread('./OpenCV/data/home.jpg')
Z = img.reshape((-1, 3))
# 将数据转化为np.float32
Z = np.float32(Z)
# 定义终止标准,聚类数并应用k均值
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 10, 1.0)
arrK = [8, 4, 2]
plt.subplot(2, 2, 1)
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.title('image')
plt.xticks([]), plt.yticks([])
for i in range(3):
    K = arrK[i]
    ret, label, center = cv.kmeans(Z, K, None, criteria, 10, cv.KMEANS_RANDOM_CENTERS)
    # 现在将数据转化为uint8,并绘制原图像
    center = np.uint8(center)
    res = center[label.flatten()]
    res2 = res.reshape((img.shape))
    plt.subplot(2, 2, i + 2)
    plt.imshow(cv.cvtColor(res2, cv.COLOR_BGR2RGB))
    plt.title('K = {}'.format(arrK[i]))
    plt.xticks([]), plt.yticks([])
plt.show()

在这里插入图片描述
学习来源:OpenCV-Python中文文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值