山东大学计算机科学与技术学院机器学习实验六

山东大学计算机科学与技术学院机器学习实验六

实验题目:K_means
实验学时:4
实验目的:
In this exercise, you will use K-means to compress an image by reducing the number of colors it contains. To begin, download data6.zip and unpack its contents into your Matlab/Octave working directory. Photo credit: The bird photo used in this exercise belongs to Frank Wouters and is used with his permission.
实验步骤与内容:

  1. 首先读取图片到一个numpy数组中
A = np.array(Image.open('ex8Data/bird_small.tiff'))

A的形状是(128,128,3),分别是长宽高和(R,G,B)颜色

  1. 然后显示这张图片
3.	    # Display the original image
4.	plt.figure()
5.	plt.imshow(A.astype(np.uint8))
6.	plt.title('original')
7.	plt.show()

在这里插入图片描述

如图所示:

  1. 随机取16个点作为16个聚簇的中心
4.	 m, n, color = A.shape
5.	k = 16
6.	centers = np.zeros((k, 3))
7.	for i in range(k):
8.	    a = random.randint(1, n - 1)
9.	    b = random.randint(1, m - 1)
10.	    centers[i, :] = A[a, b, :]
  1. 设置迭代的次数,和每一个像素点属于的label
12.	  max_iter = 100
13.	label = np.zeros((m, n))
14.	loss = np.zeros(max_iter)
15.	
16.	flag = 0
17.	iteration = 0

进行K-means算法,迭代到最大次数或者说两次迭代之间的损失小于一个数的时候就停止迭代
for i in tqdm(range(max_iter))::这是外层循环,控制K-means算法的迭代次数,max_iter 是最大迭代次数。tqdm 是一个用于在循环中显示进度条的库。
内层三重循环:
for x in range(m)::遍历图像的行。
for y in range(n)::遍历图像的列。
for j in range(k)::遍历聚类中心。
计算每个像素到各个聚类中心的距离,并将其分配给距离最近的聚类中心(label[x, y] 记录该像素的聚类标签)。
更新损失值 loss[i],这是每次迭代中所有像素点与其最近聚类中心的距离之和。
如果当前迭代与上一次迭代的损失值差异小于某个阈值(abs(loss[i - 1] - loss[i]) < 1),则认为算法已经收敛,提前结束迭代。
更新聚类中心:
计算每个聚类中的像素点数量和各个维度上的和。
更新聚类中心为各个维度上的平均值。
如果提前结束迭代,则跳出外层循环。

18.	  for i in tqdm(range(max_iter)):
19.	    for x in range(m):
20.	        for y in range(n):
21.	            min_dis = 1e10
22.	            for j in range(k):
23.	                dis = A[x, y, :] - centers[j, :]
24.	                dis = np.dot(dis, dis)
25.	                if dis < min_dis:
26.	                    min_dis = dis
27.	                    label[x, y] = j
28.	            loss[i] += min_dis
29.	            if i > 0 and abs(loss[i - 1] - loss[i]) < 1:
30.	                iteration = i
31.	                flag = 1
32.	                break
33.	        if flag:
34.	            break
35.	    if flag:
36.	        break
37.	
38.	    cluster_size = np.zeros(k)
39.	    new_center = np.zeros((k, 3))
40.	
41.	    for x in range(m):
42.	        for y in range(n):
43.	            lb = int(label[x, y])
44.	            cluster_size[lb] += 1
45.	            new_center[lb, :] += A[x, y, :]
46.	
47.	    for j in range(k):
48.	        if cluster_size[j] != 0:
49.	            centers[j, :] = new_center[j, :] / cluster_size[j]

6 . 把每一个点的像素的颜色变为它所属于的类的颜色
在这里插入图片描述

52.	 for x in range(m):
53.	    for y in range(n):
54.	        lb = int(label[x, y])
55.	        A[x, y, :] = centers[lb, :]
56.	画出进行完算法之后的图像以及损失

在这里插入图片描述

结论分析与体会:
在这个实验中,我深入了解了K-means聚类算法,并在图像数据上进行了实际应用。以下是我的结论和个人体会:
首先,通过观察损失函数随迭代次数的变化,我发现在一定迭代次数后,损失值趋于稳定,这表明算法在给定数据集上逐渐收敛。这对我理解算法的性能和收敛性提供了关键的见解。
在观察聚类效果时,我发现K-means算法成功地将图像分成了预期的簇,并且每个簇中的像素点具有相似的特征。通过可视化每个簇的中心和样本,我更清晰地了解了聚类的效果,这有助于评估算法在图像数据上的表现。
我还尝试了不同的初始聚类中心,并注意到算法对初始条件的敏感性。不同的初始中心可能导致不同的聚类结果,这使我认识到在实际应用中,选择合适的初始中心对于算法的性能至关重要。
通过尝试不同的聚类中心数量,我得以比较不同情况下的聚类效果。这有助于我理解K-means在不同问题中的适用性,并找到最佳的聚类中心数量,以达到最佳效果。
在思考算法的应用和局限性时,我认识到K-means算法在图像聚类以外可能也具有广泛的应用。然而,我也意识到算法对初始条件敏感,且对异常值敏感,这是在某些情况下需要谨慎考虑的局限性。
总的来说,通过这个实验,我不仅深入了解了K-means聚类算法的原理和实现细节,还学到了如何调整参数、优化算法以及处理不同情况。这为我今后在实际项目中应用聚类算法提供了有价值的经验教训。

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
from tqdm import tqdm
import random

# Read the image
A = np.array(Image.open("ex8Data/IMG_202311089677_248x248.jpg"))

print(A.shape)
# Display the original image
plt.figure()
plt.imshow(A.astype(np.uint8))
plt.title('original')
plt.show()

# Your further processing code here
m, n, color = A.shape

k = 3

centers = np.zeros((k, 3))
for i in range(k):
    a = random.randint(1, n - 1)
    b = random.randint(1, m - 1)
    centers[i, :] = A[a, b, :]

max_iter = 100
label = np.zeros((m, n))
loss = np.zeros(max_iter)

flag = 0
iteration = 100

for i in tqdm(range(max_iter)):
    for x in range(m):
        for y in range(n):
            min_dis = 1e10
            for j in range(k):
                dis = A[x, y, :] - centers[j, :]
                dis = np.dot(dis, dis)
                if dis < min_dis:
                    min_dis = dis
                    label[x, y] = j
            loss[i] += min_dis
            if i > 0 and abs(loss[i - 1] - loss[i]) < 1:
                iteration = i
                flag = 1
                break
        if flag:
            break
    if flag:
        break

    cluster_size = np.zeros(k)
    new_center = np.zeros((k, 3))

    for x in range(m):
        for y in range(n):
            lb = int(label[x, y])
            cluster_size[lb] += 1
            new_center[lb, :] += A[x, y, :]

    for j in range(k):
        if cluster_size[j] != 0:
            centers[j, :] = new_center[j, :] / cluster_size[j]

for x in range(m):
    for y in range(n):
        lb = int(label[x, y])
        A[x, y, :] = centers[lb, :]

# Display clustered image
plt.figure()
plt.imshow(A.astype(np.uint8))
plt.title('cluster into 16 RGB means')
plt.show()


# Plot loss function
plt.figure()
plt.plot(np.arange(0, iteration), loss[0:iteration], linewidth=2)
plt.xlabel('iteration')
plt.ylabel('loss')
plt.title('K-means loss function')
plt.show()
  • 41
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咕噜咕噜咕噜128

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值