sklearn之k-means聚类算法

听了菜菜的sklearn算法而写的学习笔记

  • 概述
    • 无监督学习与有监督学习
    • 结构化数据与非结构化数据
    • 聚类算法与分类算法
    • sklearn中的聚类算法
  • KMeans一最简单的聚类算法
    • KMeans算法工作原理
      • 先导概念
      • 核心任务
      • 算法步骤
      • eg:kmeans将数据分为4个簇
    • 衡量KMeans算法效果的指标
      • 簇内误差平方和
        • 聚出的类应该有什么性质,有什么用处?
        • 什么是差异?
        • 以欧几里得距离为例衡量差异
        • 不同的距离对应着不同的质心和inertia
      • 算法复杂度
        • 时间复杂度
        • 空间复杂度
  • 类:sklearn.cluster.KMeans
    • 重要参数
      • k-means++寻找优秀初始化质心的原理
    • 一些其他的参数(选看)
    • 重要属性
    • 重要接口
    • eg.简单聚类
  • 函数:k_means
  • 聚类模型评估指标
      • 聚类,回归,分类的评价指标有哪些?
    • inertia(不建议用,不太准确)
    • 真实标签已知的情况下(不常用)
    • 真实标签未知的情况下(常用)
      • 轮廓系数
      • calinski-harabasz Index(CHI) 卡林斯基-哈拉巴斯指数
      • 其它的指标
  • 案例:聚类算法用于降维和矢量量化

概述

无监督学习与有监督学习

无监督学习

  • 定义:模型在训练时,只需要输入特征矩阵X,不需要输入标签y;
  • 典型无监督算法:PCA,聚类算法

有监督学习

  • 定义:模型在训练时,既需要X又需要y;
  • 典型有监督算法:决策树,随机森林,逻辑回归等

结构化数据与非结构化数据

  • 结构化数据也称作行数据,是由二维表结构来逻辑表达和实现的数据,严格地遵循数据格式与长度规范,主要通过关系型数据库进行存储和管理;
  • 非结构化数据是数据结构不规则或不完整,没有预定义的数据模型,不方便用数据库二维逻辑表来表现的数据。包括所有格式的办公文档、文本、图片、XML, HTML、各类报表、图像和音频/视频信息等等。

聚类算法与分类算法

聚类算法(无监督分类)

  • 目的:将其划分为多个有意义/有用的簇;
  • 功能:
    1. 基于业务需求或建模需求进行划分;
    2. 单纯地探索数据的自然结构和分布,即数据之间的联系;
    3. 降维和矢量量化:将高维特征压缩到一列当中,常常用于图像、声音、视频等非结构化数据的处理,大幅压缩数据量;
  • 学习类型:无监督学习;
  • 典型算法:k-means,DBSCAN,层次聚类,光谱聚类;
  • 输出:
    1. 聚类结果不确定,分出来的类不一定就是数据的真实分类;
    2. 同样的聚类,根据业务需求的不同,结果可能是好的,也可能不好。

分类算法

  • 目的:将数据进行单纯的分类;
  • 功能:对已经分类好的数据进行学习,学习好后再将新数据放入分类模型中对新数据进行分类;
  • 学习类型:有监督学习;
  • 典型算法:决策树,贝叶斯,逻辑回归;
  • 输出:
    1. 分类的结果是确定的,不根据业务或建模需求决定;
    2. 分类后模型的优劣客观易判断。

sklearn中的聚类算法

聚类算法在sklearn中有两种表现形式:

  • 类:通过实例化、训练并使用接口或属性调用结果;
  • 函数:只需要数据特征矩阵X和超参数就可以得出结果,就像数学中的函数一样,只要有自变量就能得出因变量;
    sklearn之k-means聚类算法_第1张图片

这篇blog中用的聚类算法就是:(中括号中的参数就是可填可不填)

  • 类:cluster.KMeans([n_clusters,init,…])
  • 函数:cluster.k_means(X,n_clusters,[,…])

输入数据应注意:

  • 模块的算法可以采用不同类型的矩阵作为输入
  1. 所有方法可以输入[n_samples,n_features]的标准特征矩阵,该矩阵可从sklearn.feature_extraction模块中的类中获得;
  2. 对于亲和力传播、光谱聚类和DBSCAN,可以输入[n_samples,n_samples]的相似性矩阵,该矩阵可用sklearn.metrics.pairwise模块中的函数来获得。

KMeans一最简单的聚类算法

KMeans算法工作原理

先导概念

  • 簇:聚类的结果表现,将一个N样本的特征矩阵X分为k个簇,一个簇中的数据就被认为是一类;
  • 质心:簇中所有数据的均值μj即为"质心";(所有数据在每个轴坐标上的均值即为质心在该轴上的坐标)

核心任务

找出k个质心,将离这些质心最近的数据分到这些之心所代表的簇中。

算法步骤

  1. 随机抽取k个质心;
  2. {将样本点分给距离最近的质心,生成k个簇;
    对于每个簇,以每个簇的样本点的均值作为新质心;}
  3. 循环执行步骤2,直至质心位置不变。(当簇不再改变时,质心位置就不变)

eg:kmeans将数据分为4个簇

sklearn之k-means聚类算法_第2张图片

衡量KMeans算法效果的指标

簇内误差平方和

聚出的类应该有什么性质,有什么用处?

  • 簇内差异小(数据相似),簇间差异大(数据不同);类似于分箱应该达到的效果;
  • 研究每个簇中有什么性质,可根据这些性制定不同的策略。

什么是差异?

样本到其所在簇的质心的距离
sklearn之k-means聚类算法_第3张图片
注:余弦距离通常用来衡量文本和文本之间的差异。

以欧几里得距离为例衡量差异

簇内平方和(又叫"inertia"):
在这里插入图片描述
整体平方和(又叫"total inertia"):
在这里插入图片描述
total inertia越小,簇内样本越相似,聚类效果越好。

因此,kmeans希望找到让total inertia最小的质心 一 最优化问题。

  • 当质心不断变化时,total inertia越来越小,当total inertia最小时,质心不再改变。

注:kmeans中的total inertia类似于别的方法中的损失函数,但是要注意的是kmeans并没有损失函数这个概念。

不同的距离对应着不同的质心和inertia

距离 ~ 质心 ~ inertia:

欧几里得距离~ 均值 ~最小化每个样本点到质心的欧式距离之和;
曼哈顿距离 ~ 中位数 ~最小化每个样本点到质心曼哈顿距离之和;
余弦距离~ 均值 ~最小化每个样本点到质心的余弦距离之和

注:实验证明,使用不同的距离,就应该选用不同的质心和不同的inertia搭配,只要选对,就可以达到不错的聚类效果。

算法复杂度

时间复杂度

  • 平均时间复杂度:O(knT),其中,k:簇数,n:样本数,T:迭代次数;(相比之下,KNN的平均复杂度为O(n))
  • 最坏时间复杂度:O(n^((k+2)/p)),其中,n:样本数,p:特征总数;

空间复杂度

类:sklearn.cluster.KMeans

class  sklearn.cluster.KMeans (n_clusters=8, init=’k-means++, n_init=10, max_iter=300, tol=0.0001,
precompute_distances=’auto’, verbose=0, random_state=None, copy_x=True, n_jobs=None, algorithm=’auto’)

下面的参数的使用在例代码中都能看到(除了选看的那一部分参数)

重要参数

  • n_clusters:簇数k,默认为8,但一般我们都会取一个比8小的数;
  • init:初始化质心的方法,可取值如下
    1. “k-means++”:默认,以k-means++的方法为聚类选取更优秀的初始质心,以加速聚类;
    2. “random”:随机选取k个质心;
    3. 一个n维数组:数组的形状应该是(n_clusters,n_features)并给出初始质心。
plus = KMeans(n_clusters = 10).fit(X)
plus.n_iter_  #明显看出,k-means++迭代的次数小

#12
random = KMeans(n_clusters = 10,init="random",random_state=420).fit(X)
random.n_iter_

#19
  • random_state:控制每次质心随机初始化的随机数种子,random_state一样,初始化的质心就是一样的;
  • n_init:整数,默认10,若n_init的值是n,就选n个不同的随机种子并依次运行k-means算法,最终以输出最优的那个随机数种子作为n_init的值进行运算;
  • max_iter:最大迭代次数,会出现迭代次数用完但没有聚类完或没达到最大迭代次数就聚类完的情况,可以调用n_iter属性来得出真是迭代次数;
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)

#0.3952586444034157

random.n_iter_
#9
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)

#0.3401504537571701

random.n_iter_
#19
  • tol:浮点数,默认1e-4,两次迭代间的Inertia下降的量如果小于tol值,则停止迭代;

k-means++寻找优秀初始化质心的原理

  • 随机初始化质心,聚类结果易受初始化质心的影响;(eg:选取了一个质心,但是其距离其他的质心都很远,是个孤立点)

  • 思想:逐个选取k kk个簇中心,且离其它簇中心越远的样本点越有可能被选为下一个簇中心。

  • 具体实现步骤:
    1.从数据集X中随机(均匀分布)选取一个样本点作为第一个初始聚类中心ci;
    2.接着计算每个样本与当前已有聚类中心之间的最短距离,用D ( x )表示;然后计算每个样本点被选为下一个聚类中心的概率P ( x ),最后选择最大概率值所对应的样本点作为下一个簇中心;
    sklearn之k-means聚类算法_第4张图片

    3.重复步骤2,直至选出k个质心;

一些其他的参数(选看)

sklearn之k-means聚类算法_第5张图片
sklearn之k-means聚类算法_第6张图片

重要属性

  • labels:每个样本点对应的标签;
  • cluster_centers_:收敛到的质心的坐标;
  • inertia:簇内平方和;
  • n_iter_:实际迭代次数;

重要接口

  • fit(训练特征矩阵X,[训练用标签,sample_weight]):拟合训练模型;
  • predict(测试特征矩阵X,[sample_weight]):拟合好后把新的样本分到相应的类中;
  • fit_predict(训练特征矩阵X,[训练用标签,sample_weight]):相当于先fit后predict,只不过训练测试特征矩阵相同而已,计算质心,预测每个样本所在簇的索引并返回;
  • transform(任意特征矩阵X):将X转化到簇距离空间中,在新空间中,每个维度是样本到集群中心的距离;
  • fit_transform(训练特征矩阵X,[训练用标签,sample_weight]):相当于先fit后transform,聚类并将X转换到簇距离空间中并返回新空间的特征矩阵;
  • score(测试特征矩阵X,[训练用标签,sample_weight]):返回簇内平方和,簇内平方和越小越好,最佳为0,是一种模型评估指标;
  • get_params():获取类的参数;
  • set_params(n_clusters=… ,init=… ,…):重新设置参数

eg.简单聚类

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)#fig是画布,ax1是对象,对象在画布中,图画在对象上展现在画布中
ax1.scatter(X[:, 0], X[:, 1]
            ,marker='o'#点的形状
            ,s=8 #点的大小
           )
plt.show()

sklearn之k-means聚类算法_第7张图片

#展示这些点的分布
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()

sklearn之k-means聚类算法_第8张图片

#对这些数据使用聚类算法,看他的聚类效果怎么样
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
#结果太长,这里就不写了,是一个一维数组,里面只有0,1,2
pre = cluster.fit_predict(X)
pre == y_pred
#本来就是利用X来聚类的,聚类好后又作用于X肯定结果都是True

当样本量太大或特征数量太多时,计算起来很麻烦,为了简化计算,我们可以只用样本的一部分进行聚类,将聚类结果再作用于整个数据集,但是这样的聚类效果不确定好还是坏。

cluster_smallsub = KMeans(n_clusters=n_clusters, random_state=0).fit(X[:200])
y_pred_ = cluster_smallsub.predict(X)
y_pred == y_pred_
#因为用少量样本聚出来的类的效果不一定特别好,所以结果会出现很多False
centroid = cluster.cluster_centers_
centroid
#array([[-7.09306648, -8.10994454],
#      [-1.54234022,  4.43517599],
#      [-8.0862351 , -3.5179868 ]])

函数:k_means

sklearn.cluster.k_means (X, n_clusters, sample_weight=None, init=’k-means++, precompute_distances=’auto’,
n_init=10, max_iter=300, verbose=False, tol=0.0001, random_state=None, copy_x=True, n_jobs=None,
algorithm=’auto’, return_n_iter=False)

eg.

#函数k均值聚类
from sklearn.cluster import k_means
k_means(X,4,return_n_iter=True)#依次返回质心坐标,每个样本对应的簇标签,inertia及最佳迭代次数(结果太长了,这里就不写了)

聚类模型评估指标

聚类,回归,分类的评价指标有哪些?

  • 分类:评价较简单,分类结果有正误之分,可以使用预测的准确率、混淆矩阵、ROC曲线等进行评估;
  • 回归:SSE均方误差、损失函数;
  • 聚类:以下几个都是

inertia(不建议用,不太准确)

inertia并不是越小越好,inertia不适合作为指标的原因有以下几点:

  1. inertia非有界,没有参考,因此你并不知道这个数值是不是真的小;
  2. 计算易受特征总数的影响;若特征总数过多,计算起来很费劲;
  3. 易受超参数k的影响,k越大,inertia一定会越来越小;
  4. inertia对数据分布有假设(假设数据服从凸分布),且假设数据是各向同性的(即数据的属性在不同的方向上有不同的含义);所以使用Inertia作为评估指标,会让聚类算法在一些细长簇,环形簇,或者不规则形状的流形时表现不佳;

k对inertia的影响:

n_clusters = 4
cluster_ = KMeans(n_clusters=n_clusters, random_state=0).fit(X)
inertia_ = cluster_.inertia_
inertia_
#908.3855684760603
n_clusters = 5
cluster_ = KMeans(n_clusters=n_clusters, random_state=0).fit(X)
inertia_ = cluster_.inertia_
inertia_
#811.0841324482416
n_clusters = 6
cluster_ = KMeans(n_clusters=n_clusters, random_state=0).fit(X)
inertia_ = cluster_.inertia_
inertia_
#733.1538350083074

#通过上面的例子可以发现,n_clusters越大,inertia_越小,但是我们并不能仅靠越来越多的聚类数来实现好的聚类效果,类数越少聚类效果越好才是我们应该追求的目标。
#同时也说明了inertia_并不是一个好的模型聚类效果评价指标

k均值聚类算法在一些细长簇,环形簇,或者不规则形状的流形上的表现:
sklearn之k-means聚类算法_第9张图片

真实标签已知的情况下(不常用)

这种情况很少出现,如果出现了一般都用分类方法,但是也有需要用聚类算法的;
sklearn之k-means聚类算法_第10张图片

真实标签未知的情况下(常用)

轮廓系数

  • 对没有真实标签的数据进行探索,也不知道正确答案;
  • 这种情况下,完全依赖于评价簇内的稠密程度(簇内差异小)和簇间的离散程度(簇外差异大)来评估聚类的效果;
  • 轮廓系数是对每个样本定义的,也能用来衡量:
    1. 样本与簇中其它样本的相似度a,即样本与同一簇中所有其他点之间的平均距离;
    2. 样本与其它簇中的样本的相似度b,即样本与下一个最近的簇中所有点之间的平均距离;
    3. 我们希望b>a,且越大越好;
  • 单个样本的轮廓系数:
    在这里插入图片描述
    等价于sklearn之k-means聚类算法_第11张图片
    s∈(-1,1)
  1. s>0,聚类效果好;特别地,s→1,a相对于b越小,聚类效果越好;
  2. s=0,两个簇的相似度一致,两个簇应该合成一个;
  3. s<0,聚类效果差;
  4. 若一个簇中大多数样本都有很高的轮廓系数,则总轮廓系数大,平均轮廓系数大,聚类效果好;
  5. 若一个簇中大多数样本都为低轮廓系数或负轮廓系数,则聚类效果不是很好,原因可能是簇数k设置得过大或过小;
  • sklearn中计算轮廓系数的方法:模块metrics中的类
    1. silhouette_score:平均轮廓系数;
    2. silhouette_samples:每个样本自己的轮廓系数;
from sklearn.metrics import silhouette_score
from sklearn.metrics import silhouette_samples

silhouette_score(X,y_pred)#在上面的例子中,y_pred是聚成3类得出的标签
#0.5882004012129721

silhouette_score(X,cluster_.labels_)#在上面的例子中,cluster_.labels_是聚成6类得出的标签
#0.5150064498560357

silhouette_samples(X,y_pred)
#每个样本的轮廓系数都返回了,内容太长,这里不写了
  • 轮廓系数的优点:

    1. 取值有界,对聚类效果有一个参考;
    2. 对数据的分布没有假设,因此在很多数据集上都能表现得很好;
  • 轮廓系数的缺点:在凸性类上表现出"虚高"(即返回的分数比真实轮廓系数高),例如,基于密度进行的聚类,通过DBSCAN获得的聚类结果等;

  • 基于轮廓系数选择合适的n_clusters:

from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_samples, silhouette_score

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

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 on sample data "
                  "with n_clusters = %d" % n_clusters),
                 fontsize=14, fontweight='bold')
    plt.show()

For n_clusters = 2 The average silhouette_score is : 0.7049787496083262
sklearn之k-means聚类算法_第12张图片
For n_clusters = 3 The average silhouette_score is : 0.5882004012129721
sklearn之k-means聚类算法_第13张图片
For n_clusters = 4 The average silhouette_score is : 0.6505186632729437
sklearn之k-means聚类算法_第14张图片
For n_clusters = 5 The average silhouette_score is : 0.56376469026194
sklearn之k-means聚类算法_第15张图片
For n_clusters = 6 The average silhouette_score is : 0.4504666294372765
sklearn之k-means聚类算法_第16张图片
For n_clusters = 7 The average silhouette_score is : 0.39092211029930857

sklearn之k-means聚类算法_第17张图片
从上面的结果看出,聚成4类最好。

calinski-harabasz Index(CHI) 卡林斯基-哈拉巴斯指数

卡林斯基-哈拉巴斯指数s(k):
在这里插入图片描述
其中,

  • N:数据集样本量;
  • k:簇数;
  • Wk:组内离散矩阵(一个簇内数据的协方差矩阵);
  • Bk:组件离散矩阵(不同簇之间的协方差矩阵);
  • Tr(A):矩阵A的迹(主对角线元素之和);

并且:

  • 组间离散程度越高,Tr(Bk)越大;
  • 组内离散程度越低,Tr(Wk)越小;
  • 因此,我们希望CHI越大越好;

CHI的优点:计算快;

#使用时间戳计算运行时间来显式表示calinski_harabasz_score的计算比轮廓系数的计算快得多
from time import time
t0 = time()
calinski_harabasz_score(X, y_pred)
time() - t0

#0.000997304916381836
t0 = time()
silhouette_score(X,y_pred)
time() - t0

#0.005983591079711914
#将时间戳转化为易懂的形式
import datetime
datetime.datetime.fromtimestamp(t0).strftime("%Y-%m-%d %H:%M:%S")

#'2021-05-29 15:23:25'

CHI的缺点:

  1. 指数无界;
  2. 在凸数据集上会表现出"虚高";

其它的指标

  • Davies-Bouldin 戴维斯-布尔丁指数
  • Contingency Matrix 权变矩阵

案例:聚类算法用于降维和矢量量化

  1. 导入库
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 #将一个序列:字典,列表,图片等打乱重排的函数
  1. 导入数据,探索数据
china = load_sample_image("china.jpg")
china

china.dtype  #一般图片的数据类型都是'uint8'
#dtype('uint8')

china.shape   #三维:长度*宽度*像素,像素是三个数,由三个数决定一个颜色
#(427, 640, 3)

china[0][0]
#array([174, 201, 231], dtype=uint8)

newimage = china.reshape((427 * 640,3)) #将所有数据拉成一行,方便下面进行颜色个数的判断

import pandas as pd
pd.DataFrame(newimage).drop_duplicates().shape #去除重复值来查看有多少种颜色,发现有9万多种

plt.figure(figsize=(15,15))
plt.imshow(china) #imshow显示三维数组形成的图片(图1)

flower = load_sample_image("flower.jpg")
plt.figure(figsize=(15,15))
plt.imshow(flower) #(图2)

sklearn之k-means聚类算法_第18张图片
sklearn之k-means聚类算法_第19张图片
处理完后发现有9w多种颜色,我们想把它压缩至64种颜色,可用聚类算法;

  1. 决定超参数,数据预处理
n_clusters = 64
china = np.array(china, dtype=np.float64) / china.max()
w, h, d = original_shape = tuple(china.shape)

assert d == 3,"一个格子中的特征数目不等于3种"  #如果不等于3就报错,所报的错误就是后面的字符串的内容
image_array = np.reshape(china, (w * h, d))  #将所有数据拉成一行

image_array
'''
array([[0.68235294, 0.78823529, 0.90588235],
       [0.68235294, 0.78823529, 0.90588235],
       [0.68235294, 0.78823529, 0.90588235],
       ...,
       [0.16862745, 0.19215686, 0.15294118],
       [0.05098039, 0.08235294, 0.02352941],
       [0.05882353, 0.09411765, 0.02745098]])
'''

image_array.shape
#(273280, 3)

注:reshape的函数解释

a = np.random.random((2,4))
a
'''array([[0.43516089, 0.8142793 , 0.08701465, 0.14891459],
          [0.6404939 , 0.8470681 , 0.89773921, 0.78202351]])'''
a.reshape((4,2))
'''array([[0.43516089, 0.8142793 ],
       [0.08701465, 0.14891459],
       [0.6404939 , 0.8470681 ],
       [0.89773921, 0.78202351]])'''
np.reshape(a,(4,2))
#答案与上一个一样

np.reshape(a,(2,2,2))
'''array([[[0.43516089, 0.8142793 ],
        [0.08701465, 0.14891459]],

       [[0.6404939 , 0.8470681 ],
        [0.89773921, 0.78202351]]])'''
np.reshape(a,(3,2))  #报错,无论有几维,只要维度之积不变,就可以reshape
  1. 对数据进行K-Means的矢量量化
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_
#返回64个质心坐标

labels = kmeans.predict(image_array)
labels.shape
#(273280,)

image_kmeans = image_array.copy()
for i in range(w*h):
    image_kmeans[i] = kmeans.cluster_centers_[labels[i]]
image_kmeans
'''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
#(64, 3)

image_kmeans = image_kmeans.reshape(w,h,d)  #从二维变回三维
image_kmeans.shape
#(427, 640, 3)
  1. 对数据进行随机的矢量量化
centroid_random = shuffle(image_array, random_state=0)[:n_clusters]
labels_random = pairwise_distances_argmin(centroid_random,image_array,axis=0)

labels_random.shape
#(273280,)

centroid_random
#返回64个质心的坐标

len(set(labels_random))  #集合之后,重复数据被除,结果只有64个数据
#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
#(427, 640, 3)
  1. 将原图,按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()

sklearn之k-means聚类算法_第20张图片
sklearn之k-means聚类算法_第21张图片
sklearn之k-means聚类算法_第22张图片

你可能感兴趣的:(python机器学习)