当前位置: 首页 > 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
  • 2017 年终总结 —— 在路上
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • express如何解决request entity too large问题
  • isset在php5.6-和php7.0+的一些差异
  • Java比较器对数组,集合排序
  • Java到底能干嘛?
  • Python连接Oracle
  • Spring-boot 启动时碰到的错误
  • Vim Clutch | 面向脚踏板编程……
  • vue学习系列(二)vue-cli
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 力扣(LeetCode)357
  • 排序算法之--选择排序
  • 我感觉这是史上最牛的防sql注入方法类
  • 小而合理的前端理论:rscss和rsjs
  • 怎么将电脑中的声音录制成WAV格式
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • #微信小程序:微信小程序常见的配置传值
  • (007)XHTML文档之标题——h1~h6
  • (52)只出现一次的数字III
  • (ros//EnvironmentVariables)ros环境变量
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (附源码)计算机毕业设计ssm电影分享网站
  • (附源码)计算机毕业设计ssm基于Internet快递柜管理系统
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • (三)终结任务
  • (一)Spring Cloud 直击微服务作用、架构应用、hystrix降级
  • (一)使用Mybatis实现在student数据库中插入一个学生信息
  • (转) 深度模型优化性能 调参
  • (转)拼包函数及网络封包的异常处理(含代码)
  • .MSSQLSERVER 导入导出 命令集--堪称经典,值得借鉴!
  • .NET CORE Aws S3 使用
  • .NET Framework Client Profile - a Subset of the .NET Framework Redistribution
  • @Data注解的作用
  • [ linux ] linux 命令英文全称及解释
  • [ vulhub漏洞复现篇 ] Apache Flink目录遍历(CVE-2020-17519)
  • []T 还是 []*T, 这是一个问题
  • [20170713] 无法访问SQL Server
  • [8-27]正则表达式、扩展表达式以及相关实战
  • [BZOJ1178][Apio2009]CONVENTION会议中心