Advertisement

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

阅读量:

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

实验题目: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'))
    
    
    python
    
    

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

  1. 然后显示这张图片
复制代码
	    # Display the original image
    4.	plt.figure()
    5.	plt.imshow(A.astype(np.uint8))
    6.	plt.title('original')
    7.	plt.show()
    
    
    python
    
    
在这里插入图片描述

如图所示:

  1. 随机取16个点作为16个聚簇的中心
复制代码
	 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, :]
    
    
    python
    
    
  1. 设置迭代的次数,和每一个像素点属于的label
复制代码
	  max_iter = 100
    13.	label = np.zeros((m, n))
    14.	loss = np.zeros(max_iter)
    15.	
    16.	flag = 0
    17.	iteration = 0
    
    
    python
    
    

进行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),则认为算法已经收敛,提前结束迭代。
更新聚类中心:
计算每个聚类中的像素点数量和各个维度上的和。
更新聚类中心为各个维度上的平均值。
如果提前结束迭代,则跳出外层循环。

复制代码
	  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]
    
    
    python
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-07-13/vFAS5NRc7hE4xOHUgYjmyud9naI3.png)

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

复制代码
	 for x in range(m):
    53.	    for y in range(n):
    54.	        lb = int(label[x, y])
    55.	        A[x, y, :] = centers[lb, :]
    56.	画出进行完算法之后的图像以及损失
    
    
    python
    
    
在这里插入图片描述

结论分析与体会:
在这个实验中,我深入了解了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()
    
    
    python
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-07-13/ySjb9uYRUnwPrVxcQ1XOGskMef4A.png)

全部评论 (0)

还没有任何评论哟~