《scikit-learn》KMeans

至于聚类的地含义,以及我们熟悉的KMeans算法,基于层次的,基于密度的,我们之前都是学习过的,就不多说了,这里说一些在scikit-learn中是如何使用的,且说一些其他方面的。

一:代码直接开整

第一步,我们先自己造一些二维数据,并且用图画出来。

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

# 自己创造一个数据集,
# 自己创造一个,一千个样本的数据,每个数据是2个特征,一共有4个中心
x, y = make_blobs(n_samples=1000, n_features=2, centers=4, random_state=54)
print(x.shape)
print(y.shape)
print(y[0:8])  # 返回的y呢就是以0为开始整数。

fig, ax1 = plt.subplots(1)  # 生成子图的数量,第一个是画布,第二个是对象
ax1.scatter(x[:, 0], x[:, 1],
            marker='o',  # 点形状
            s=8)  # 点大小
plt.title('original plain samples')
plt.show()

# 如果我们想看看点的分布的话,也可以画出来的,只是这正是我们聚类偶有做的事情啊。
# color = ['red', 'black', 'green', 'blue']
# 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.title('original classified samples')
# plt.show()

在这里插入图片描述

第二步,我们建立KMeans模型进行拟合且就结果进行画图展示

# 开始聚类操作下
from sklearn.cluster import KMeans

n_clusters = 4
cluster = KMeans(n_clusters=n_clusters, random_state=9)
cluster = cluster.fit(x)  # 训练

pred = cluster.labels_
print(pred[0:8])  # 每个样本对应的结果
print(cluster.cluster_centers_)  # 返回得到的几个质心
print(cluster.inertia_)  # 总距离(所有点到各自质心的距离)的平方和,不是合适的模型评估指标

y_pred = cluster.fit_predict(x)
print(y_pred[0:8])  # 每个样本对应的结果

# 具体效果咋样,我们可视化一下看看
color = ['red', 'black', 'green', 'blue']
fig, ax1 = plt.subplots(1)  # 生成子图的数量,第一个是画布,第二个是对象
for i in range(4):
    ax1.scatter(x[y_pred == i, 0], x[y_pred == i, 1],  # 使用布尔索引
                marker='o',  # 点形状
                s=8,  # 点大小
                c=color[i])  # 设置点颜色
# 单独把质心画出来
ax1.scatter(cluster.cluster_centers_[:, 0], cluster.cluster_centers_[:, 1],  # 使用布尔索引
            marker='x',  # 点形状
            s=15,  # 点大小
            c='yellow')  # 设置点颜色

plt.title('the result after KMeans')
plt.show()

在这里插入图片描述

二:评估指标
1:我们使用轮廓系数来衡量,好的聚类算法的表现是,簇内的是很相似很近的,簇外就是越差异越远越好。
样本与自身所在簇中的其他样本相似度a:等于样本与同簇中其他所有点的平均距离。
样本与其他簇中样本的相似度b:等于样本与其最近的一个其他簇中所有点的平均距离。
因此轮廓系数是:
在这里插入图片描述

这个公式可以理解成:
在这里插入图片描述

这个s值是处在[-1, 1]之间的,很明显,我们希望a越小越好,且b越大越好。因此,s值越接近于1越好,越接近于-1越不好。

要声明的是,轮廓系数是到按照每个样本进行计算的,也就是每个样本都是有个轮廓系数哈。如果一个簇大多数样本的轮廓系数很高,那么平均值就会很高,那么模型聚类就很好。
我们用代码进行尝试看看

# 衡量模型好坏的指标
from sklearn.metrics import silhouette_score
from sklearn.metrics import silhouette_samples

# 经过上面的计算,我们有了原始特征矩阵数据x,y,以及我们预测的y_pred

print(silhouette_score(x, y_pred))  # 计算轮廓系数,第一个是特征矩阵(样本坐标),第二个是聚类的结果
print(silhouette_score(x, cluster.labels_))  # 计算轮廓系数

silhouette_results = silhouette_samples(x, y_pred)
print(silhouette_results.shape)  # 展示每个样本的轮廓系数
print(silhouette_results.mean())  # 展示每个样本的轮廓系数综合后的平均值,就是silhouette_score的值。

2:Calinski-Harabaz指数
在这里插入图片描述

因此我们希望其值越大越好啊。其效果也快,比轮廓系数计算快。

from sklearn.metrics import calinski_harabasz_score

print(calinski_harabasz_score(x, y_pred))
print(calinski_harabasz_score(x, cluster.labels_))

这里为什么要学习衡量指标呢,就是为了调整超参数使用的。

三:一些重要的参数
KMeans的第一步就是初始化质心,随机放置的效果也会不一样,最后会直接影响效果的,也会影响模型运行时间。

新的方法可以使KMeans++,他们开发出一个算法,使得初始化质心彼此远离,从而得到更加可靠的。我们的参数init,可以输入random,kmeans++,或一个n维数组(用户自行决定质心,维度是n_cluster X n_features),一般我们保持默认kmeans++不动即可。

random_state就是质心随机初始化的种子,指定了的话,控制每次初始化质心都在相同的位置。

如果不指定随机数种子,就按按照n_init来使用多个随机种子来运行多次,选择最好的。这个参数就是n_init,默认是10,我们可以增加这个次数,次数越大,KMeans运行时间越长。

如何让迭代停止呢?
max_iter:可以让迭代提前终止,最大的迭代次数。
tol:如过两次迭代之间Inertial下降的量小于该值就结束掉迭代,基本已经不会有大变化了。它是浮点数,默认是1e-4。

四:聚类用于压缩,矢量量化。
KMeans的一个应用就是将非结构化数据(图像声音等)进行矢量量化,非结构化数据往往占用比较大的存储空间,数据量大,运算缓慢,我们希望在保证数据质量的情况下,尽可能减少数据的大小,简化结构化数据的结构。

降维自带压缩属性。
我们之前学习过的特征选择,是选择出有价值的贡献最大的特征。
之前学习的PCA,是聚合特征信息,从而创造出更低维度价值更高的特征。

矢量量化就是在同等样本量上压缩信息的大小,不改变样本数目,也不改变特征数目。
举个例子,我们有40个样本有40个不同的样本信息,假如我们把他们进行效果很好的聚类,后面发现,他们属于4个簇,我们就用每个簇的质心俩替换/代表/表示该簇内所有样本信息,这样话,我们只需要四组信息就表示了40个样本的信息,我们只需要保存这个四个质心的信息,有点四舍五入的感觉哈。

这样一来,信息量会被压缩到很小,但是损失的信息又不大。
我们举个例子,压缩一个图像,比如我们选取RGB图像,压缩到64个质心。用64个质心来替换每个像素。

from sklearn.datasets import load_sample_image  # 导入图片数据的类

from sklearn.cluster import KMeans
from sklearn.utils import shuffle  # 洗牌,打乱数据顺序的函数。

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# 加载图片来试一试
china = load_sample_image('china.jpg')
print(china.dtype)  # 数组类型是uint8,0~255
print(china.shape)  # (427, 640, 3),看来是RGB类型的数据。长度是427,宽度是640。RGB三通道

# 我们调整下数据形状
newimage = china.reshape(-1, 3)
print(newimage.shape)  # (273280, 3),一张图片全部行程了一列,序列化了。RGB三通道也就是一个像素是三个值,一个像素3个特征。

uniquePiexls = pd.DataFrame(newimage).drop_duplicates()
print(uniquePiexls.shape)  # 哎呀(96615, 3),说明重复度很大嘛。

# 图片的数据查看了,来看看效果。
plt.figure(figsize=(15, 15))
plt.title('original image')
plt.imshow(china)
plt.show()






# 加入哈,我们压缩到64个簇,计算每个原始样本到质心们的距离,找出最新的质心,然后用质心的数据来替换原始数据的值。我们可以观察原始数据的效果。
n_clusters = 64

# 预处理一下,所有的数字都压缩到了[0,1]之间
china = np.array(china, dtype=np.float64) / china.max()
print(china.shape)
print((china > 1).sum())
print((china < 0).sum())

image_array = np.reshape(china, (-1, 3))
print(image_array.shape)

# 上模型
# 训练方式一:太慢了
# kmeans = KMeans(n_clusters=n_clusters, random_state=12).fit(image_array)
# print(kmeans.cluster_centers_.shape)

# 训练方式二:先使用部分数据找出质心,再使用这些质心预测所有点,这样快多了啊
image_array_samples = shuffle(image_array)[:5000]  # 比如先使用5000个像素样本来搞事情
kmeans = KMeans(n_clusters=n_clusters, random_state=12).fit(image_array_samples)
print(kmeans.cluster_centers_.shape)

# 然后预测出所有的像素点的值
labels = kmeans.predict(image_array)  # 生成了簇的质心的簇索引。
print(labels.shape)

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

image_kmeans = kmeans.cluster_centers_[labels]
print(image_kmeans.shape)
image_kmeans = image_kmeans * china.max()  # 恢复到0-255
image_kmeans = image_kmeans.reshape(china.shape[0], china.shape[1], china.shape[2])  # 转换到三维。此时图像只有64个像素重复了。

plt.figure(figsize=(15, 15))
plt.title('after kmeans')
plt.imshow(image_kmeans)
plt.show()

# 至此我们把图像进行了压缩,我们只需要存储labels的序列,以及所有的质心,kmeans.cluster_centers_即可保存原始的图像。

原始图如下:
在这里插入图片描述

经过kmeans压缩后的
在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
本程序是在python中完成,基于sklearn.cluster中的k-means聚类包来实现数据的聚类,对于里面使用的数据格式如下:(注意更改程序中的相关参数) 138 0 124 1 127 2 129 3 119 4 127 5 124 6 120 7 123 8 147 9 188 10 212 11 229 12 240 13 240 14 241 15 240 16 242 17 174 18 130 19 132 20 119 21 48 22 37 23 49 0 42 1 34 2 26 3 20 4 21 5 23 6 13 7 19 8 18 9 36 10 25 11 20 12 19 13 19 14 5 15 29 16 22 17 13 18 46 19 15 20 8 21 33 22 41 23 69 0 56 1 49 2 40 3 52 4 62 5 54 6 32 7 38 8 44 9 55 10 70 11 74 12 105 13 107 14 56 15 55 16 65 17 100 18 195 19 136 20 87 21 64 22 77 23 61 0 53 1 47 2 33 3 34 4 28 5 41 6 40 7 38 8 33 9 26 10 31 11 31 12 13 13 17 14 17 15 25 16 17 17 17 18 14 19 16 20 17 21 29 22 44 23 37 0 32 1 34 2 26 3 23 4 25 5 25 6 27 7 30 8 25 9 17 10 12 11 12 12 12 13 7 14 6 15 6 16 12 17 12 18 39 19 34 20 32 21 34 22 35 23 33 0 57 1 81 2 77 3 68 4 61 5 60 6 56 7 67 8 102 9 89 10 62 11 57 12 57 13 64 14 62 15 69 16 81 17 77 18 64 19 62 20 79 21 75 22 57 23 73 0 88 1 75 2 70 3 77 4 73 5 72 6 76 7 76 8 74 9 98 10 90 11 90 12 85 13 79 14 79 15 88 16 88 17 81 18 84 19 89 20 79 21 68 22 55 23 63 0 62 1 58 2 58 3 56 4 60 5 56 6 56 7 58 8 56 9 65 10 61 11 60 12 60 13 61 14 65 15 55 16 56 17 61 18 64 19 69 20 83 21 87 22 84 23 41 0 35 1 38 2 45 3 44 4 49 5 55 6 47 7 47 8 29 9 14 10 12 11 4 12 10 13 9 14 7 15 7 16 11 17 12 18 14 19 22 20 29 21 23 22 33 23 34 0 38 1 38 2 37 3 37 4 34 5 24 6 47 7 70 8 41 9 6 10 23 11 4 12 15 13 3 14 28 15 17 16 31 17 39 18 42 19 54 20 47 21 68 22

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值