java学习视频 Logstash Apache 电力杆 深度图像 winforms npm stl Draggabilly teamviewer验证被拒绝 python程序界面 idea生成main方法 安卓程序源代码 h5下拉刷新 kubernetes官网 python循环 python语言入门 python编程题 python中的map函数 python读取本地文件 java中continue java如何配置环境变量 javaabstract java线程停止 java游戏开发 js四舍五入 matlab2016a安装教程 冬青鼠 dg分区 计算机网络自顶向下 dota改键工具 dnf武极刷图加点 iar下载 js分页 我的世界透视 pr怎么放大视频画面 pr蒙版怎么用 linux解压命令 ftp客户端软件 黑道圣徒4去马赛克补丁
当前位置: 首页 > 学习教程  > 编程语言

《scikit-learn》KMeans

2021/2/13 18:19:01 文章标签: 测试文章如有侵权请发送至邮箱809451989@qq.com投诉后文章立即删除

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

至于聚类的地含义,以及我们熟悉的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压缩后的
在这里插入图片描述


本文链接: http://www.dtmao.cc/news_show_700234.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?