Python 聚类算法在矢量量化案例详解

关注微信公共号:小程在线

关注****博客:程志伟的博客

 

KMeans算法将一组N个样本的特征矩阵X划分为K个无交集的簇,直观上来看是簇是一组一组聚集在一起的数据,在一个簇中的数据就认为是同一类。就是聚类的结果表现。


簇中所有数据的均值 通常被称为这个簇的“质心”(centroids)。在一个二维平面中,一簇数据点的质心的横坐标就是这一簇数据点的横坐标的均值,质心的纵坐标就是这一簇数据点的纵坐标的均值。同理可推广至高维空间。

顺序 过程
1      随机抽取K个样本作为最初的质心
2      开始循环:
2.1   将每个样本点分配到离他们最近的质心,生成K个簇
2.2   对于每个簇,计算所有被分到该簇的样本点的平均值作为新的质心
3      当质心的位置不再发生变化,迭代停止,聚类完成

 

簇内误差平方和:
对于一个簇来说,所有样本点到质心的距离之和越小,我们就认为这个簇中的样本越相似,簇内差异就越小
 

from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt

#自己创建数据集
X, y = make_blobs(n_samples=500,n_features=2,centers=4,random_state=1)

fig, ax1 = plt.subplots(1)
ax1.scatter(X[:, 0], X[:, 1]
        ,marker='o' #点的形状
        ,s=8 #点的大小
        )
plt.show()

Python 聚类算法在矢量量化案例详解

全部一个颜色,查看这些点的分布
color = ["red","pink","orange","gray"]
fig, ax1 = plt.subplots(1)
for i in range(4):
    ax1.scatter(X[y==i, 0], X[y==i, 1]
    ,marker='o' #点的形状
    ,s=8 #点的大小
    ,c=color[i]
    )

plt.show()

Python 聚类算法在矢量量化案例详解

 

基于这个分布,我们来使用Kmeans进行聚类,首选选取3类
from sklearn.cluster import KMeans
n_clusters = 3
cluster = KMeans(n_clusters=n_clusters, random_state=0).fit(X)

 

#查看分类情况

y_pred = cluster.labels_
y_pred
Out[4]: 
array([0, 0, 2, 1, 2, 1, 2, 2, 2, 2, 0, 0, 2, 1, 2, 0, 2, 0, 1, 2, 2, 2,
       2, 1, 2, 2, 1, 1, 2, 2, 0, 1, 2, 0, 2, 0, 2, 2, 0, 2, 2, 2, 1, 2,
       ......
       1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 0, 2, 1, 2, 0, 1, 0, 1, 0, 2, 1, 1,
       0, 2, 2, 0, 2, 2, 2, 0, 2, 1, 2, 2, 0, 0, 0, 2])

 

#Kmeans也有predict和fit_predict函数,表示学习数据X并对X的类进行预测,和labels一模一样

pre = cluster.fit_predict(X)
pre == y_pred
Out[5]: 
array([ True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        ......
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True])

 

#当数据量太大时,不必使用所有的数据寻找质心,调用部分数据就可以,使用predict来调用,提高效率

#因为数据量太小的原因,结果不会太准确,但是当数据量增大时,可以提升准确度

cluster_smallsub = KMeans(n_clusters=n_clusters, random_state=0).fit(X[:200])
y_pred_ = cluster_smallsub.predict(X)
y_pred == y_pred_
Out[6]: 
array([False, False,  True, False,  True, False,  True,  True,  True,
        True, False, False,  True, False,  True, False,  True, False,
       False,  True,  True,  True,  True, False,  True,  True, False,
       ......
        True, False,  True,  True,  True, False,  True, False,  True,
        True, False, False, False,  True])

 

#确定质心的位置

centroid = cluster.cluster_centers_
centroid
Out[7]: 
array([[-7.09306648, -8.10994454],
       [-1.54234022,  4.43517599],
       [-8.0862351 , -3.5179868 ]])

centroid.shape
Out[8]: (3, 2)

 

#重要属性inertia_,查看总距离平方和

inertia = cluster.inertia_
inertia
Out[9]: 1903.4503741659223

 

#对聚类结果进行画图

color = ["red","pink","orange","gray"]
fig, ax1 = plt.subplots(1)
for i in range(n_clusters):
    ax1.scatter(X[y_pred==i, 0], X[y_pred==i, 1]
    ,marker='o'
    ,s=8
    ,c=color[i]
    )

ax1.scatter(centroid[:,0],centroid[:,1]
    ,marker="x"
    ,s=15
    ,c="black")
plt.show()

Python 聚类算法在矢量量化案例详解

 

#把簇的类似改成4类,查看总距离平方和

n_clusters = 4
cluster_ = KMeans(n_clusters=n_clusters, random_state=0).fit(X)
inertia_ = cluster_.inertia_
inertia_
Out[11]: 908.3855684760613

 

#把簇的类似改成5类,查看总距离平方和

n_clusters = 5
cluster_ = KMeans(n_clusters=n_clusters, random_state=0).fit(X)
inertia_ = cluster_.inertia_
inertia_
Out[12]: 811.0841324482415

 

#把簇的类似改成6类,查看总距离平方和

n_clusters = 6
cluster_ = KMeans(n_clusters=n_clusters, random_state=0).fit(X)
inertia_ = cluster_.inertia_
inertia_
Out[13]: 733.153835008308

可以看出簇的数越大,总距离平方和越少。极限时,簇的个数为500,总距离平方和为0,不能对簇做出最优选择。

 

#聚类算法的模型评估指标
#当真实标签未知的时候:轮廓系数

在sklearn中,我们使用模块metrics中的类silhouette_score来计算轮廓系数,它返回的是一个数据集中,所有样
本的轮廓系数的均值。但我们还有同在metrics模块中的silhouette_sample,它的参数与轮廓系数一致,但返回的
是数据集中每个样本自己的轮廓系数
 

 

from sklearn.metrics import silhouette_score
from sklearn.metrics import silhouette_samples

X.shape
Out[15]: (500, 2)

 

#簇等于6时的轮廓系数

silhouette_score(X,y_pred)
Out[16]: 0.5882004012129721

 

#簇等于4时的轮廓系数

n_clusters = 4
cluster_ = KMeans(n_clusters=n_clusters, random_state=0).fit(X)
inertia_ = cluster_.inertia_
inertia_
silhouette_score(X,cluster_.labels_)
Out[17]: 0.6505186632729437

 

#簇等于5时的轮廓系数

n_clusters = 5
cluster_ = KMeans(n_clusters=n_clusters, random_state=0).fit(X)
inertia_ = cluster_.inertia_
inertia_
silhouette_score(X,cluster_.labels_)
Out[18]: 0.5746932321727457

 

#数据集中每个样本自己的轮廓系数的个数与平均值

silhouette_samples(X,y_pred).shape
Out[19]: (500,)

silhouette_samples(X,y_pred).mean()
Out[20]: 0.5882004012129721

 

#当真实标签未知的时候:Calinski-Harabaz Index

from sklearn.metrics import calinski_harabaz_score
calinski_harabaz_score(X, y_pred)
H:\Anaconda3\lib\site-packages\sklearn\utils\deprecation.py:85: DeprecationWarning: Function calinski_harabaz_score is deprecated; Function 'calinski_harabaz_score' has been renamed to 'calinski_harabasz_score' and will be removed in version 0.23.
  warnings.warn(msg, category=DeprecationWarning)
Out[21]: 1809.991966958033

 

#卡林斯基-哈拉巴斯指数越高越好,比起轮廓系数,它有一个巨大的优点,就是计算非常快速

t0 = time()
calinski_harabaz_score(X, y_pred)
time() - t0
H:\Anaconda3\lib\site-packages\sklearn\utils\deprecation.py:85: DeprecationWarning: Function calinski_harabaz_score is deprecated; Function 'calinski_harabaz_score' has been renamed to 'calinski_harabasz_score' and will be removed in version 0.23.
  warnings.warn(msg, category=DeprecationWarning)
Out[23]: 0.0009794235229492188

t0 = time()
silhouette_score(X,y_pred)
time() - t0
Out[24]: 0.009987354278564453

import datetime
datetime.datetime.fromtimestamp(t0).strftime("%Y-%m-%d %H:%M:%S")
Out[25]: '2020-03-30 22:01:27'

 

案例:基于轮廓系数来选择n_clusters

 

n_clusters = 4


#创建一个画布,2个图,
fig, (ax1, ax2) = plt.subplots(1, 2)
fig.set_size_inches(18, 7)

#第一个图是轮廓系数图像,由各个簇的轮廓系数组成的条形图,横坐标是轮廓系数,纵坐标是每个样本
#轮廓系数在[-1,1]之间,但是要大于0,效果好
#设置横坐标
ax1.set_xlim([-0.1, 1])

#纵坐标从0开始,最大值是x.shape(0)的取值
#每个簇排在一起,但是有间隙
ax1.set_ylim([0, X.shape[0] + (n_clusters + 1) * 10])

#开始建模
clusterer = KMeans(n_clusters=n_clusters, random_state=10).fit(X)
cluster_labels = clusterer.labels_

#silhouette_score返回得是所有样本点的均值
#矩阵X和聚类完毕之后的标签
silhouette_avg = silhouette_score(X, cluster_labels)
print("For n_clusters =", n_clusters,
      "The average silhouette_score is :", silhouette_avg)

#silhouette_samples返回每个样本的轮廓系数
sample_silhouette_values = silhouette_samples(X, cluster_labels)

#Y轴的初始值
y_lower = 10


#对每个簇进行循环
for i in range(n_clusters):
    #从每个样本的轮廓系数结果中抽取第i个簇的轮廓系数,并进行排序
    ith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == i]
    #注意,.sort会直接改掉原数据的顺序
    ith_cluster_silhouette_values.sort()
    #查看簇中究竟有多少个样本
    size_cluster_i = ith_cluster_silhouette_values.shape[0]
    #一个簇在y州的取值是由初始值(y_lower)开始,到初始值加上这个簇中的样本数量结束(y_upper)
    y_upper = y_lower + size_cluster_i
    
    #用i的浮点数除以n_clusters,在不同的i下生成不同的小数,以确保所有的簇都有不同的颜色
    color = cm.nipy_spectral(float(i)/n_clusters)
    #fill_between是让一个范围的柱状图都统一颜色的函数,
    #fill_betweenx的范围是在纵坐标上,参数输入(纵坐标的下限,纵坐标的上限,X轴上的取值,柱状图的颜色)
    ax1.fill_betweenx(np.arange(y_lower, y_upper)
                      ,ith_cluster_silhouette_values
                      ,facecolor=color
                      ,alpha=0.7)
    #为每个簇的轮廓系数写上编号,并让簇的编号显示在坐标轴每个条形图的中间位置
    #text参数(要显示编号位置的横坐标,纵坐标,编号内容)
    ax1.text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))
    #为下一个簇计算新的y轴上的初始值,每一次迭代后y再加上10以保证不同簇的图像之间显示有空隙
    y_lower = y_upper + 10
    
ax1.set_title("The silhouette plot for the various clusters.")
ax1.set_xlabel("The silhouette coefficient values")
ax1.set_ylabel("Cluster label")


# 把整个数据集上的轮廓系数的均值以虚线形式放入图中
ax1.axvline(x=silhouette_avg, color="red", linestyle="--")


#让y轴不显示任何刻度
ax1.set_yticks([])


#让X轴上的刻度显示为规定的列表
ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])

#开始处理第二个图,首先获取新的颜色,由于没有循环需要一次性生成多个小数来获取多个颜色
#cluster_labels.astype(float) 生成浮点数,nipy_spectral只能用浮点数,500个值只有4个颜色
colors = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)
ax2.scatter(X[:, 0], X[:, 1],marker='o',s=8,c=colors)


#把生成的质心放在图像中
centers = clusterer.cluster_centers_

ax2.scatter(centers[:, 0], centers[:, 1], marker='x',c="red", alpha=1, s=200)
ax2.set_title("The visualization of the clustered data.")
ax2.set_xlabel("Feature space for the 1st feature")
ax2.set_ylabel("Feature space for the 2nd feature")


#为整个图设置标题
plt.suptitle(("Silhouette analysis for KMeans clustering on sample data "
              "with n_clusters = %d" % n_clusters),
             fontsize=14, fontweight='bold')

plt.show()

 

#将上述过程包装称循环
for n_clusters in [2,3,4,5,6,7]:
    n_clusters = n_clusters
    fig, (ax1, ax2) = plt.subplots(1, 2)
    fig.set_size_inches(18, 7)
    ax1.set_xlim([-0.1, 1])
    ax1.set_ylim([0, X.shape[0] + (n_clusters + 1) * 10])
    clusterer = KMeans(n_clusters=n_clusters, random_state=10).fit(X)
    cluster_labels = clusterer.labels_
    silhouette_avg = silhouette_score(X, cluster_labels)
    print("For n_clusters =", n_clusters,"The average silhouette_score is :", silhouette_avg)
    sample_silhouette_values = silhouette_samples(X, cluster_labels)
    y_lower = 10
    for i in range(n_clusters):
        ith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == i]
        ith_cluster_silhouette_values.sort()
        size_cluster_i = ith_cluster_silhouette_values.shape[0]
        y_upper = y_lower + size_cluster_i
        color = cm.nipy_spectral(float(i)/n_clusters)
        ax1.fill_betweenx(np.arange(y_lower, y_upper)
                          ,ith_cluster_silhouette_values
                          ,facecolor=color
                          ,alpha=0.7)
        ax1.text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))
        y_lower = y_upper + 10
    ax1.set_title("The silhouette plot for the various clusters.")
    ax1.set_xlabel("The silhouette coefficient values")
    ax1.set_ylabel("Cluster label")
    ax1.axvline(x=silhouette_avg, color="red", linestyle="--")
    ax1.set_yticks([])
    ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])

    colors = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)
    ax2.scatter(X[:, 0], X[:, 1],marker='o',s=8,c=colors)
    centers = clusterer.cluster_centers_
    # Draw white circles at cluster centers
    ax2.scatter(centers[:, 0], centers[:, 1], marker='x',c="red", alpha=1, s=200)
    ax2.set_title("The visualization of the clustered data.")
    ax2.set_xlabel("Feature space for the 1st feature")
    ax2.set_ylabel("Feature space for the 2nd feature")
    plt.suptitle(("Silhouette analysis for KMeans clustering"
                  "with n_clusters = %d" % n_clusters),fontsize=14, fontweight='bold')
    plt.show()

For n_clusters = 2 The average silhouette_score is : 0.7049787496083262

Python 聚类算法在矢量量化案例详解

For n_clusters = 3 The average silhouette_score is : 0.5882004012129721

Python 聚类算法在矢量量化案例详解

For n_clusters = 4 The average silhouette_score is : 0.6505186632729437

Python 聚类算法在矢量量化案例详解

For n_clusters = 5 The average silhouette_score is : 0.56376469026194

Python 聚类算法在矢量量化案例详解

For n_clusters = 6 The average silhouette_score is : 0.4504666294372765

Python 聚类算法在矢量量化案例详解

For n_clusters = 7 The average silhouette_score is : 0.39092211029930857

Python 聚类算法在矢量量化案例详解

 

当簇等于2时,可以看出有一个簇的明显高于平均值,当实施精准营销时,可以只考虑该类人员的特征。

当簇等于4时,也可以把数据分成很好的类。

 

 

重要参数init & random_state & n_init

init 默认输入"kmeans++":一种为K均值聚类选择初始聚类中心的聪明的办法,以加速收敛。如果输入了n维数组,数组的形状应
该是(n_clusters,n_features)并给出初始质心。
plus = KMeans(n_clusters = 10).fit(X)
plus.n_iter_
Out[28]: 17

random = KMeans(n_clusters = 10,init="random",random_state=420).fit(X)
random.n_iter_
Out[29]: 19

 

重要参数max_iter & tol:让迭代停下来

max_iter:整数,默认300,单次运行的k-means算法的最大迭代次数
tol:浮点数,默认1e-4,两次迭代间Inertia下降的量,如果两次迭代之间Inertia下降的值小于tol所设定的值,迭代就会停下
 

random = KMeans(n_clusters = 10,init="random",max_iter=10,random_state=420).fit(X)
y_pred_max10 = random.labels_
silhouette_score(X,y_pred_max10)
Out[30]: 0.3952586444034157

random = KMeans(n_clusters = 10,init="random",max_iter=20,random_state=420).fit(X)
y_pred_max20 = random.labels_
silhouette_score(X,y_pred_max20)
Out[31]: 0.3401504537571701

 

 

#聚类算法用于降维,KMeans的矢量量化应用

    矢量量化的降维是在同等样本量上压缩信息的大小,即不改变特征的数目也不改变样本的数目,只改变在这些特征下的样本上的信息量。

 

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import pairwise_distances_argmin

 #对两个序列中的点进行距离匹配的函数
from sklearn.datasets import load_sample_image

 #导入图片数据所用的类
from sklearn.utils import shuffle

 

china = load_sample_image("china.jpg")
china
Out[33]: 
array([[[174, 201, 231],
        [174, 201, 231],
        [174, 201, 231],
        ...,
        [250, 251, 255],
        [250, 251, 255],
        [250, 251, 255]],

       [[172, 199, 229],
        [173, 200, 230],
        [173, 200, 230],
        ...,
        [251, 252, 255],
        [251, 252, 255],
        [251, 252, 255]],

       [[174, 201, 231],
        [174, 201, 231],
        [174, 201, 231],
        ...,
        [252, 253, 255],
        [252, 253, 255],
        [252, 253, 255]],

       ...,

       [[ 88,  80,   7],
        [147, 138,  69],
        [122, 116,  38],
        ...,
        [ 39,  42,  33],
        [  8,  14,   2],
        [  6,  12,   0]],

       [[122, 112,  41],
        [129, 120,  53],
        [118, 112,  36],
        ...,
        [  9,  12,   3],
        [  9,  15,   3],
        [ 16,  24,   9]],

       [[116, 103,  35],
        [104,  93,  31],
        [108, 102,  28],
        ...,
        [ 43,  49,  39],
        [ 13,  21,   6],
        [ 15,  24,   7]]], dtype=uint8)

china.dtype
Out[34]: dtype('uint8')

china.shape
Out[35]: (427, 640, 3)

china[0][0]
Out[36]: array([174, 201, 231], dtype=uint8)

newimage = china.reshape((427 * 640,3))
newimage.shape
Out[37]: (273280, 3)

import pandas as pd
pd.DataFrame(newimage).drop_duplicates().shape
Out[38]: (96615, 3)

plt.figure(figsize=(15,15))
plt.imshow(china)
Out[39]: <matplotlib.image.AxesImage at 0x1d286ad0f28>
Python 聚类算法在矢量量化案例详解

flower = load_sample_image("flower.jpg")
plt.figure(figsize=(15,15))
plt.imshow(flower)
Out[40]: <matplotlib.image.AxesImage at 0x1d286b43278>

Python 聚类算法在矢量量化案例详解

 

3. 决定超参数,数据预处理
china = np.array(china, dtype=np.float64) / china.max()
w, h, d = original_shape = tuple(china.shape)
w, h, d
Out[42]: (427, 640, 3)

 

#设置d=3,不等于3报错

assert d == 3

d_ = 5
assert d_ == 3, "一个格子中的特征数目不等于3种"
Traceback (most recent call last):

  File "<ipython-input-44-6bfdf4addbf4>", line 2, in <module>
    assert d_ == 3, "一个格子中的特征数目不等于3种"

AssertionError: 一个格子中的特征数目不等于3种

 

#reshape改变数据结果,只要总数据量不变,维度都可以变化

a = np.random.random((2,4))
a
Out[45]: 
array([[0.17545705, 0.61403347, 0.65398707, 0.32697789],
       [0.84574926, 0.42294712, 0.33591104, 0.49572982]])

a.reshape((4,2))
Out[46]: 
array([[0.17545705, 0.61403347],
       [0.65398707, 0.32697789],
       [0.84574926, 0.42294712],
       [0.33591104, 0.49572982]])

a.reshape((4,2))
Out[47]: 
array([[0.17545705, 0.61403347],
       [0.65398707, 0.32697789],
       [0.84574926, 0.42294712],
       [0.33591104, 0.49572982]])

np.reshape(a,(4,2))
Out[48]: 
array([[0.17545705, 0.61403347],
       [0.65398707, 0.32697789],
       [0.84574926, 0.42294712],
       [0.33591104, 0.49572982]])

np.reshape(a,(2,2,2))
Out[49]: 
array([[[0.17545705, 0.61403347],
        [0.65398707, 0.32697789]],

       [[0.84574926, 0.42294712],
        [0.33591104, 0.49572982]]])

np.reshape(a,(3,2))
Traceback (most recent call last):

  File "<ipython-input-50-a620d2495b00>", line 1, in <module>
    np.reshape(a,(3,2))

  File "H:\Anaconda3\lib\site-packages\numpy\core\fromnumeric.py", line 292, in reshape
    return _wrapfunc(a, 'reshape', newshape, order=order)

  File "H:\Anaconda3\lib\site-packages\numpy\core\fromnumeric.py", line 56, in _wrapfunc
    return getattr(obj, method)(*args, **kwds)

ValueError: cannot reshape array of size 8 into shape (3,2)


image_array = np.reshape(china, (w * h, d))
image_array
image_array.shape
Out[51]: (273280, 3)

n_clusters = 64
china = np.array(china, dtype=np.float64) / china.max()
w, h, d = original_shape = tuple(china.shape)
assert d == 3
image_array = np.reshape(china, (w * h, d))

 

4. 对数据进行K-Means的矢量量化
 #首先,使用1000个数据找出质心

image_array_sample = shuffle(image_array, random_state=0)[:1000]
kmeans = KMeans(n_clusters=n_clusters, random_state=0).fit(image_array_sample)
kmeans.cluster_centers_
Out[53]: 
array([[0.62570806, 0.60261438, 0.53028322],
       [0.15546218, 0.1557423 , 0.12829132],
       ......
       [0.73524384, 0.82021116, 0.91925591],
       [0.20627451, 0.07816993, 0.07660131]])

kmeans.cluster_centers_.shape
Out[54]: (64, 3)

 

#找出质心之后,对所有点数据进行聚类

labels = kmeans.predict(image_array)
labels.shape
Out[55]: (273280,)

 

#使用质心来替换所有的样本

image_kmeans = image_array.copy()

for i in range(w*h):
    image_kmeans[i] = kmeans.cluster_centers_[labels[i]]

 

#查看新图片的信息 

image_kmeans
Out[58]: 
array([[0.73524384, 0.82021116, 0.91925591],
       [0.73524384, 0.82021116, 0.91925591],
       [0.73524384, 0.82021116, 0.91925591],
       ...,
       [0.15546218, 0.1557423 , 0.12829132],
       [0.07058824, 0.0754637 , 0.0508744 ],
       [0.07058824, 0.0754637 , 0.0508744 ]])

 

#去重

pd.DataFrame(image_kmeans).drop_duplicates().shape
Out[59]: (64, 3)

 

#恢复图片

image_kmeans = image_kmeans.reshape(w,h,d)
image_kmeans.shape
Out[60]: (427, 640, 3)

 

 

5. 对数据进行随机的矢量量化

centroid_random = shuffle(image_array, random_state=0)[:n_clusters]
labels_random = pairwise_distances_argmin(centroid_random,image_array,axis=0)
labels_random.shape
Out[61]: (273280,)

len(set(labels_random))
Out[62]: 64

 

#使用随机质心替换样本

image_random = image_array.copy()
for i in range(w*h):
    image_random[i] = centroid_random[labels_random[i]]

 

#恢复图片 

image_random = image_random.reshape(w,h,d)
image_random.shape
Out[64]: (427, 640, 3)

 

6. 将原图,按KMeans矢量量化和随机矢量量化的图像绘制出来

plt.figure(figsize=(10,10))
plt.axis('off')
plt.title('Original image (96,615 colors)')
plt.imshow(china)

plt.figure(figsize=(10,10))
plt.axis('off')
plt.title('Quantized image (64 colors, K-Means)')
plt.imshow(image_kmeans)

plt.figure(figsize=(10,10))
plt.axis('off')
plt.title('Quantized image (64 colors, Random)')
plt.imshow(image_random)
plt.show()

Python 聚类算法在矢量量化案例详解Python 聚类算法在矢量量化案例详解Python 聚类算法在矢量量化案例详解

第一张为原图,第二张为聚类之后的图,第三张是随机质心的图;

从以上的三幅图中可以看出,第二张聚类之后在塔的颜色上没有明显缺失,天空出现锯齿形,第三张的塔的颜色发生变化。