当前位置: 首页 > news >正文

K-Means聚类算法

k均值聚类

k均值聚类是最简单也最常用的聚类算法,它试图找到代表数据特定区域的簇中心每个簇中心设置为所分配的所有数据点的平均值,如果簇的分配不再变化,那么算法结束。

无监督学习:给出的标签不具有先验意义

在make_blobs数据集上使用k均值聚类算法,并输出用训练的无监督学习模型产生的预测结果:

from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans

X, y = make_blobs(random_state=1)
kmeans = KMeans(n_clusters=3)
kmeans.fit(X)

print(kmeans.predict(X))

👇这个结果给出的仅是簇标签,无先验含义。如,通过k均值聚类分类出的人物肖像,需要查看肖像才知道是你的哪位朋友。

[1 0 0 0 2 2 2 0 1 1 0 0 2 1 2 2 2 1 0 0 2 0 2 1 0 2 2 1 1 2 1 1 2 1 0 2 0
 0 0 2 2 0 1 0 0 2 1 1 1 1 0 2 2 2 1 2 0 0 1 1 0 2 2 0 0 2 1 2 1 0 0 0 2 1
 1 0 2 2 1 0 1 0 0 2 1 1 1 1 0 1 2 1 1 0 0 2 2 1 2 1]

给出其预测边界:

mglearn.discrete_scatter(X[:, 0], X[:, 1], kmeans.labels_, markers='o')
mglearn.discrete_scatter(
 kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], [0, 1, 2],
 markers='^', markeredgewidth=2)

在这里插入图片描述
👆由于设置簇的个数为3,因此最终分为3簇,簇中心使用🔺表示。

查看不同聚类中心个数对聚类结果的影响

分别设置聚类中心个数为2个和5个:

import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 2, figsize=(10, 5))
# 使用2个簇中心:
kmeans = KMeans(n_clusters=2)
kmeans.fit(X)
assignments = kmeans.labels_
mglearn.discrete_scatter(X[:, 0], X[:, 1], assignments, ax=axes[0])
# 使用5个簇中心:
kmeans = KMeans(n_clusters=5)
kmeans.fit(X)
assignments = kmeans.labels_
mglearn.discrete_scatter(X[:, 0], X[:, 1], assignments, ax=axes[1])

在这里插入图片描述
由于k均值聚类事先不知道聚类中心的个数,因此给出的聚类结果大概率会由于聚类中心个数的变化而改变。
之前看过一篇半监督学习模式下的K-Means聚类方法,大意是事先知道聚类中心的个数并人为地设置好,再进行聚类。当然,聚类中心的个数也可以通过肘部法则求得。

KMeans的局限

  • K均值聚类认为每个簇的半径大致相同。
  • K均值聚类还假设所有方向的簇都同等重要。
    因此改变簇的密度,会导致K均值效果下降。
X_varied, y_varied = make_blobs(n_samples=200,
 cluster_std=[1.0, 2.5, 0.5],
 random_state=170)
y_pred = KMeans(n_clusters=3, random_state=0).fit_predict(X_varied)
mglearn.discrete_scatter(X_varied[:, 0], X_varied[:, 1], y_pred)
plt.legend(["cluster 0", "cluster 1", "cluster 2"], loc='best')
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")

在这里插入图片描述
分为三簇,但是K均值的效果下降。

K均值无法识别非球形簇

# 生成一些随机分组数据
import numpy as np
X, y = make_blobs(random_state=170, n_samples=600)
rng = np.random.RandomState(74)
# 变换数据使其拉长
transformation = rng.normal(size=(2, 2))

X = np.dot(X, transformation)
# 将数据聚类成3个簇
kmeans = KMeans(n_clusters=3)
kmeans.fit(X)
y_pred = kmeans.predict(X)
# 画出簇分配和簇中心
plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap=mglearn.cm3)
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1],
 marker='^', c=[0, 1, 2], s=100, linewidth=2, cmap=mglearn.cm3)
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")

在这里插入图片描述
👆真实的簇与K均值分出来的簇。
另一个例子:

# 生成模拟的two_moons数据(这次的噪声较小)
from sklearn.datasets import make_moons
X, y = make_moons(n_samples=200, noise=0.05, random_state=0)
# 将数据聚类成2个簇
kmeans = KMeans(n_clusters=2)
kmeans.fit(X)
y_pred = kmeans.predict(X)
# 画出簇分配和簇中心
plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap=mglearn.cm2, s=60)
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1],
 marker='^', c=[mglearn.cm2(0), mglearn.cm2(1)], s=100, linewidth=2)
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")

在这里插入图片描述

PCA、NMF和K-Means在人脸识别图像重建上的对比

PCA:主成分分析。
NMF:非负矩阵分解。
可以理解为,二者都能够进行特征提取和数据降维,并都有助于数据可视化。

from sklearn.datasets import fetch_lfw_people
from sklearn.model_selection import train_test_split
from sklearn.decomposition import PCA, NMF

people = fetch_lfw_people(min_faces_per_person=20, resize=0.7)
image_shape = people.images[0].shape

mask = np.zeros(people.target.shape, dtype=np.bool)
for target in np.unique(people.target):
    mask[np.where(people.target == target)[0][:50]] = 1
X_people = people.data[mask]
y_people = people.target[mask]
X_people = X_people / 255.

X_train, X_test, y_train, y_test = train_test_split(
 X_people, y_people, stratify=y_people, random_state=0)
nmf = NMF(n_components=100, random_state=0)
nmf.fit(X_train)
pca = PCA(n_components=100, random_state=0)
pca.fit(X_train)
kmeans = KMeans(n_clusters=100, random_state=0)
kmeans.fit(X_train)
X_reconstructed_pca = pca.inverse_transform(pca.transform(X_test))
X_reconstructed_kmeans = kmeans.cluster_centers_[kmeans.predict(X_test)]
X_reconstructed_nmf = np.dot(nmf.transform(X_test), nmf.components_)

fig, axes = plt.subplots(3, 5, figsize=(8, 8),
 subplot_kw={'xticks': (), 'yticks': ()})
fig.suptitle("Extracted Components")
for ax, comp_kmeans, comp_pca, comp_nmf in zip(
 axes.T, kmeans.cluster_centers_, pca.components_, nmf.components_):
    ax[0].imshow(comp_kmeans.reshape(image_shape))
    ax[1].imshow(comp_pca.reshape(image_shape), cmap='viridis')
    ax[2].imshow(comp_nmf.reshape(image_shape))
axes[0, 0].set_ylabel("kmeans")
axes[1, 0].set_ylabel("pca")
axes[2, 0].set_ylabel("nmf")
fig, axes = plt.subplots(4, 5, subplot_kw={'xticks': (), 'yticks': ()},
 figsize=(8, 8))
fig.suptitle("Reconstructions")
for ax, orig, rec_kmeans, rec_pca, rec_nmf in zip(
 axes.T, X_test, X_reconstructed_kmeans, X_reconstructed_pca,
 X_reconstructed_nmf):
    ax[0].imshow(orig.reshape(image_shape))
    ax[1].imshow(rec_kmeans.reshape(image_shape))
    ax[2].imshow(rec_pca.reshape(image_shape))
    ax[3].imshow(rec_nmf.reshape(image_shape))
axes[0, 0].set_ylabel("original")
axes[1, 0].set_ylabel("kmeans")
axes[2, 0].set_ylabel("pca")
axes[3, 0].set_ylabel("nmf")

在这里插入图片描述
👆三种方法提取到的特征。
在这里插入图片描述
👆通过上述三种方法重建的图像。对于k均值,重建就是在训练集上找到最近的簇中心。

利用KMeans做矢量化:可以用输入维度更多的簇来对数据编码

对于two_moons数据集(上例中两个半月牙),由于只有两个维度,因此PCA和NMF失效(显然对二维数据作特征提取毫无意义,如果降低维度成为一维,那么将完全破坏原先的数据)。但是可以通过加入更多的簇中心(本例中n = 10),可以用k均值找到一种更具表现力的数据表示方法。

X, y = make_moons(n_samples=200, noise=0.05, random_state=0)
kmeans = KMeans(n_clusters=10, random_state=0)
kmeans.fit(X)
y_pred = kmeans.predict(X)
plt.scatter(X[:, 0], X[:, 1], c=y_pred, s=60, cmap='Paired')
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s=60,
 marker='^', c=range(kmeans.n_clusters), linewidth=2, cmap='Paired')
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")
print("Cluster memberships:\n{}".format(y_pred))

在这里插入图片描述
👆设置200个样本点,组成两个半月牙。设置聚类的个数为10,来对数据进行聚类,结果如上图。此时,将到每个簇中心的距离作为特征,还可以得到一种更强有力的数据表示(通过kmeans构造了交叉项)。此时,应用线性模型,可以对两个月牙进行分类。

相关文章:

  • golang 切片(slice)简单使用
  • SQL Server Reporting Services
  • 加速迈入云原生时代,国产数据库行业要变天
  • PMP每日一练 | 考试不迷路-9.1(包含敏捷+多选)
  • 一体式城市内涝监测站
  • 【高等数学基础进阶】定积分应用
  • RabbitMQ基本使用一
  • CentOS 7.2 正确安装 MySQL 5.6.35
  • 计算机组成与设计-第五章 memory hierarchy(一)
  • 软考高级系统架构设计师系列论文二:论软件的性能优化设计
  • 【CircuitPython】RaspberryPi Pico RP2040 自定义机械键盘实例
  • CentOS7.6安装Rabbitmq
  • 谁说文艺青年开花店必亏,我用3年时间挣了20万
  • 11种增加访问者在网站上平均停留时间的技巧
  • centos7.6 yum安装 elasticsearch
  • ES6指北【2】—— 箭头函数
  • 【Linux系统编程】快速查找errno错误码信息
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • 2017-08-04 前端日报
  • Apache Zeppelin在Apache Trafodion上的可视化
  • create-react-app项目添加less配置
  • ERLANG 网工修炼笔记 ---- UDP
  • go append函数以及写入
  • Java程序员幽默爆笑锦集
  • JS字符串转数字方法总结
  • opencv python Meanshift 和 Camshift
  • Promise初体验
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • vue 配置sass、scss全局变量
  • XForms - 更强大的Form
  • 第2章 网络文档
  • 买一台 iPhone X,还是创建一家未来的独角兽?
  • 少走弯路,给Java 1~5 年程序员的建议
  • 我的面试准备过程--容器(更新中)
  • Java数据解析之JSON
  • ​草莓熊python turtle绘图代码(玫瑰花版)附源代码
  • !!java web学习笔记(一到五)
  • (16)UiBot:智能化软件机器人(以头歌抓取课程数据为例)
  • (20050108)又读《平凡的世界》
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (二)JAVA使用POI操作excel
  • (附源码)ssm高校志愿者服务系统 毕业设计 011648
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (五)Python 垃圾回收机制
  • ***php进行支付宝开发中return_url和notify_url的区别分析
  • ***测试-HTTP方法
  • .\OBJ\test1.axf: Error: L6230W: Ignoring --entry command. Cannot find argumen 'Reset_Handler'
  • .net 按比例显示图片的缩略图
  • .NET 常见的偏门问题
  • .net 开发怎么实现前后端分离_前后端分离:分离式开发和一体式发布
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献
  • .net 生成二级域名
  • .NET/C# 使用 #if 和 Conditional 特性来按条件编译代码的不同原理和适用场景
  • .Net中的集合