K-Means 算法的主要缺点:算法性能受类别个数 k 值、初始点值、异常点值影响很大。本文针对以上 k-means 算法主要缺点,详解 k-means 算法优化方案。
一、make_blobs 函数库
make_blobs() 是 sklearn.datasets 中的一个函数,主要功能是:生成聚类数据集。
主要参数:
(1)n_samples:样本数据量,默认值 100;
(2)n_features:样本维度,默认值 2;
(3)centers:聚类中心的个数,可以理解为 label 的种类数,默认值 3;
(4)cluster_std:数据集的标准差,默认值 1.0;
(5)shuffle:洗牌操作,boolean 类型,默认值 True;
(6)random_state:随机数种子,设置不同的种子会产生不同的样本集合。
(参考:
sklearn 中的 make_blobs()函数详解
)
(参考:
sklearn中的make_blobs的用法
)
二、K-Means 算法优化方案
1. 解决 k-means 算法性能受异常点影响较大
(1)数据预处理
k-means 的本质是基于欧氏距离的数据划分算法,均值和方差大的维度将对数据的聚类产生决定性影响。所以未做归一化处理和统一单位的数据是无法直接参与运算和比较的。常见的数据预处理方式有:数据归一化、数据标准化。
(参考:
【机器学习】K-means(非常详细)
)
常见的数据归一化和标准化方法详见:
【20210914】【数据分析】使用Python对数据进行标准化(归一化)
(2)异常值检测
离群点或噪声数据会对均值产生较大影响,很容易导致中心偏移,所以要首先进行异常点检测。
(参考:
异常点检测算法小结
)
(参考:
四种检测异常值的常用技术简述
)
(参考:
有哪些比较好的做异常值检测的方法?
)
2. 解决 k-means 算法性能受模型参数 k 影响较大(参数调优)
(1)手肘法
(参考:
kmeans最优k值的确定方法-手肘法和轮廓系数法
)
手肘法的核心思想:
随着聚类数 k 的增大,样本划分会更加精细,每个簇的聚合程度会逐渐提高,那么误差平方和 SSE 自然会逐渐减小。
当 k 小于真实聚类数时,增大 k 值会大幅增加每个簇的聚合程度,所以 SSE 的下降幅度会很大;当 k 到达真实聚类数时,再增加 k 所得到的聚合程度会迅速变小,所以 SSE 的下降幅度会骤减,最终趋于平缓。拐点处就对应了最优的真实聚类数。
功能:使用手肘法,寻找最优的 k-means 算法参数 k
import numpy as np
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
import warnings
warnings.filterwarnings('ignore')
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
#导入数据集
x, y = make_blobs(n_samples=500, n_features=2, centers=4, random_state=1)
# 作图查看数据集分布
plt.figure()
plt.scatter(x[:, 0], x[:, 1], c=y)
plt.show()
# 使用手肘法确认 k-means 算法最优参数
k = np.arange(1, 11)
inertia = []
for i in k:
model = KMeans(n_clusters=i)
model.fit(x)
y_pre = model.predict(x)
centroid = model.cluster_centers_
inertia.append(model.inertia_)
# 绘制当前模型下的聚类中心
plt.figure()
plt.scatter(x[:, 0], x[:, 1], c=y_pre)
plt.scatter(centroid[:, 0], centroid[:, 1], marker='x', s=100, c='black')
plt.show()
# 绘制样本离最近聚类中心距离总和(inertias)
plt.figure()
plt.plot(inertia)
plt.xlabel('k')
plt.ylabel('距离和')
plt.title('不同k值下,样本点到质心的距离之和')
plt.show()
手肘法的核心指标:SSE(sum of squared errors, 误差平方和)。
其中,Ci 表示第 i 个簇;p 是 Ci 中的样本点;mi 是 Ci 的质心(Ci 中所有样本的均值);SSE 是所有样本的聚类误差,代表了聚类效果的好坏。
手肘法的缺点在于不够自动化,参数选择需要人工看,有一些数据集的手肘曲线也不太容易确定参数 k。对此,有优化的参数确定方法 —— 斜率判断法。该方法认为斜率基本不变的点为最优的模型参数:找到第一个与下一个点之间斜率小于一个阈值的点,把这个点作为拐点。(参考:
kmeans的手肘法
)
(2)轮廓系数(silhouette coefficient)
定义样本 i 的轮廓系数:
其中,ai 为样本 i 的簇内不相似度,物理意义为:样本 i 到同簇其他样本的平均距离;bij 为样本 i 的簇间不相似度,物理意义为:样本 i 到其他某簇 Cj 的所有样本的平均距离。ai 越小,说明样本 i 越应该被聚类到该簇;bi 越大,表示样本 i 越不属于其他簇。
轮廓系数范围为 [-1, 1],该值越大越合理;si 接近 1,说明样本 i 聚类合理;si 接近 -1,说明样本 i 更应该分类到其他的簇;si 近似为 0,表示该样本 i 在两个簇的边界上。
sklearn.metrics.silhouette_score 为 sklearn 中求轮廓系数的 API。
(参考:
kmeans最优k值的确定方法-手肘法和轮廓系数法
)
# 使用轮廓系数法,确认 k-means 算法最优参数
k = np.arange(2, 11)
silhouette_scores = []
for i in k:
model = KMeans(n_clusters=i)
model.fit(x)
y_pre = model.predict(x)
centroid = model.cluster_centers_
silhouette_scores.append(metrics.silhouette_score(x, y_pre))
# 绘制当前模型下的聚类中心
plt.figure()
plt.scatter(x[:, 0], x[:, 1], c=y_pre)
plt.scatter(centroid[:, 0], centroid[:, 1], marker='x', s=100, c='black')
plt.show()
# 绘制不同 k 值下的轮廓系数曲线
K = list(range(2, 11))
plt.figure()
plt.plot(K, silhouette_scores)
plt.xlabel('k')
plt.ylabel('轮廓系数')
plt.title('不同k值下的轮廓系数')
plt.show()
# 使用最优的k参数,训练k-means模型,并预测
model_best = KMeans(n_clusters=4)
model_best.fit(x)
y_pre_best = model_best.predict(x)
# 绘制聚类结果
plt.figure()
plt.scatter(x[:, 0], x[:, 1], c=y_pre_best)
plt.show()
(参考:
sklearn之聚类评估指标---轮廓系数
)
(参考:
聚类性能评估-轮廓系数
)
(参考:
样本轮廓系数(原理、sklearn.metrics.silhouette_score、silhouette_samples参数介绍)
)
(3)其他方法
另外还有:mclust包、Nbclust包、Calinsky criterion、Gap Statistic、PAM、Affinity propagation(AP) clustering、clustergram、层次聚类等方法。
(参考:
【机器学习】确定最佳聚类数目的10种方法
)
3. 解决 k-means 算法性能受初始点选取影响较大(算法调优)
k-means 算法的初始簇中心是随机选取的,因此最终求得的簇的划分与随机选取的簇中心有关,这可能造成多种 k 个簇的划分情况,这是因为 k-means 算法收敛到了局部最小值,而非全局最小值。
(1)二分 k-means 算法
二分 k-means 算法解决 k-means 算法对初始簇心比较敏感的问题,是一种弱化初始质心的一种算法。
从二分 k-means 算法原理出发,相较普通 k-means,二分 k-means 算法不需要一次性初始化所有的簇中心,而是首先初始化一个,经过多次迭代得到其他的簇中心。这样做的好处在于不会收敛到局部最小值。具体思路步骤如下:
第一步:将所有样本作为一个簇,放在一个队列中;
第二步:从队列中选择一个簇进行 k-means (k=2) 算法划分,划分为两个簇,并将划分生成的子簇放在队列中;
第三步:循环迭代第二步,直到达到循环结束条件(结束条件通常有:簇的个数、最小 SSE、迭代次数等);
循环结束之后,队列中的簇就是最终得分类簇集合。
(从队列中选择簇进行二分,一般有两种方式:选择 SSE 最大的簇、选择样本数量最多的簇。)
(参考:
05 聚类算法 - 二分K-Means、K-Means++、K-Means||、Canopy、Mini Batch K-Means算法
)
(参考:
kmeans算法理解及代码实现
)
(2)k-means++ 算法
k-means++ 解决 k-means 算法对初始簇心比较敏感的问题,它和 k-means 算法的主要区别在于对初始 k 个簇心的选择方面:k-means 算法随即给定初始簇心,k-means++ 采用一些列步骤给定 k 个初始簇心:
第一步:从样本集中任选一个样本作为第一个聚类中心;
第二步:计算其余每个点 xi 到已有聚类中心点的距离和 D(xi),并以一定概率选择新的聚类中心;(这种方式使得离得越远的样本,越容易被选取为新的聚类中心,满足我们的需求)
第三步:重复第二步,直到找到 k 个聚类中心点;
第四步:使用找到的 k 个聚类中心点,进行 k-means 算法迭代。
(k-means 算法不可并行,第 k 个聚类中心的选择依赖前 k-1 个聚类中心。)
(参考:
05 聚类算法 - 二分K-Means、K-Means++、K-Means||、Canopy、Mini Batch K-Means算法
)
(参考:
【机器学习】K-means(非常详细)
)
(3)Mini-Batch k-means 算法
Mini-Batch k-means 算法解决 k-means 算法收敛需要一定时间的问题,是 k-means 算法的一种优化方式,它采用
小规模的数据子集
(每次训练使用的数据集是随机抽取的数据子集),减少了计算时间,同时试图优化目标函数。
Mini-Batch k-means 算法可以减少 k-means 算法的收敛时间,聚类效果略差于标准 k-means 算法。算法步骤如下:
第一步:首先选取部分数据集,使用 k-means 算法构建出 k 个聚簇点的模型;
第二步:继续抽取训练数据集中的部分数据集样本数据,并将其添加到模型中,分配给距离最近的簇中心点;
第三步:更新簇的质心;
循环第二步和第三步,直到达到循环结束条件。
(参考:
05 聚类算法 - 二分K-Means、K-Means++、K-Means||、Canopy、Mini Batch K-Means算法
)
三、K-Means 算法模型评估
k-means 算法评估分为两种:外部评估和内部评估。
外部评估用于真实的分群 label 已知的情况;内部评估用于真实的分群 label 未知的情况。
外部评估有:Homogeneity,completeness,v-measure,Fowlkes-Mallows scores 等;
内部评估有:轮廓系数、DBI 戴维森堡丁指数、Calinski Harabasz Index 等。
(参考:
这是一份全面的聚类算法及其改进的算法总结
)
(参考:
常用聚类(K-means,DBSCAN)以及聚类的度量指标
)
四、知识点
1. 使用轮廓系数评估 k-means 算法性能时,k 要从 2 开始选,选择 1 会报错:ValueError: Number of labels is 1. Valid values are 2 to n_samples - 1 (inclusive)
(参考:
ValueError:标签数为1.使用silhouette_score时,有效值为2到n_samples-1(包括1)(ValueError: Number of labels is 1. Valid values are 2 to n_samples - 1 (inclusive) when using silhouette_score)
)
(参考:
聚类学习-轮廓系数
)
K-Means 算法的主要缺点:算法性能受类别个数 k 值、初始点值、异常点值影响很大。本文针对以上 k-means 算法主要缺点,详解 k-means 算法优化方案。一、make_blobs 函数库 make_blobs() 是 sklearn.datasets 中的一个函数,主要功能是:生成聚类数据集。 主要参数: (1)n_samples:样本数据量,默认值 100; (2)n_features:样本维度,默认.........
数据分析通常需要分析师使用某种类型的数据来测试
算法
的效率/性能。
在这种情况下,重点不是像我们之前看到的那样回答一些分析问题,而是测试一些
机器
学习假设,例如,比较两种不同的
算法
,看看哪一种
算法
的准确性更高。
在这种情况下,分析师通常会处理他们自己生成的合成随机数据。
本实验和接下来的课程将重点介绍一些数据生成技术,您可以稍后使用这些技术来学习新
算法
,同时又不会过多地沉迷于领域知识。
确定数据科学家想要生成数据集的原因
为分类问题生成数据集
为回归问题生成数据集
练习数据集
练习数据集允许测试和调试
算法
并测试其稳健性。
它们还用于理解
算法
响应模型
参数
变化的行为,正如我们将在一些
算法
中看到的那样。
以下是此类数据集优于现实世界数据集的一些原因:
快速简便的生成
节省数据收集时间和精力
可预测的结果
对结果有更高的信心
数据集可以重复随机化以检查多种情况下的性能
简单的数据类型——更容易可视化数据和结果
在本课中,我们将介绍一些可以帮助我们生成随机数据集的
Python
make
_
blob
s()
import matplotlib.pyplot as plt
# 从sklearn中直接生成聚类数据
from sklearn.datasets.samples_generator import
make
_
blob
s
# 引入scipy中的距离函数,默认欧氏距离
from scipy.spatial.distance import cdist
# 1.数据加载
x, y =
make
_
blob
s(n_samples=100, centers=6, random_state=1234
1.从
make
_
blob
s中抽取出500个数据并使用散点图
进行
观察。
import matplotlib.pyplot as plt
from sklearn.datasets import
make
_
blob
s
data =
make
_
blob
s(n_samples=500, centers=5, random_state=8)
X, y = data
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.spring, edgecolors='k')
plt.show()
2.使用KNeighborsClassifier训练数据集。
from sklearn.datasets import
make
_
blob
s
# 导入KNN分类器
from sklearn.neighbors import KNeighborsClassifier
# 导入数据集拆分工具
from sklearn.model_selection import train_test_split
# 分类是判断样本属于那一类 回归判断样本是一个连续
值
或者范围
# 生成样本是200 分类为2的数据集
一、
make
_
blob
s简介
scikit中的
make
_
blob
s方法常被用来生成聚类
算法
的测试数据,直观地说,
make
_
blob
s会根据用户指定的特征数量、中心点数量、范围等来生成几类数据,这些数据可用于测试聚类
算法
的效果。
二、函数原型
sklearn.datasets.
make
_
blob
s(n_samples=100, n_features=2, centers=3, clust...
make
_
blob
s方法:
sklearn.datasets.
make
_
blob
s(n_samples=100,n_features=2,centers=3, cluster_std=1.0,center_box=(-10.0,10.0),shuffle=True,random_state=None)
make
_
blob
s函数是为聚类产生数据集,产生一个数据集和相应的标签
n_samples:表示数据样本点个数,默认
值
100
n_features:是每个样本的特征(或
属性
)数,也表示数据的维度,默认
值
是2
数据分析通常需要分析师使用某种类型的数据来测试
算法
的效率/性能。
在这种情况下,重点不是像我们之前看到的那样回答一些分析问题,而是测试一些
机器
学习假设,例如,比较两种不同的
算法
,看看哪一种
算法
的准确性更高。
在这种情况下,分析师通常会处理他们自己生成的合成随机数据。
本实验和接下来的课程将重点介绍一些数据生成技术,您可以稍后使用这些技术来学习新
算法
,同时又不会过多地沉迷于领域知识。
确定数据科学家想要生成数据集的原因
为分类问题生成数据集
为回归问题生成数据集
练习数据集
练习数据集允许测试和调试
算法
并测试其稳健性。
它们还用于理解
算法
响应模型
参数
变化的行为,正如我们将在一些
算法
中看到的那样。
以下是此类数据集优于现实世界数据集的一些原因:
快速简便的生成
节省数据收集时间和精力
可预测的结果
对结果有更高的信心
数据集可以重复随机化以检查多种情况下的性能
简单的数据类型——更容易可视化数据和结果
在本课中,我们将介绍一些可以帮助我们生成随机数据集的
Python
make
_
blob
s()
sklearn中的
make
_
blob
s函数可以生成数据集,具体如下:
调用
make
_
blob
s
from sklearn.datasets import
make
_
blob
s
make
_
blob
s的用法
data, label =
make
_
blob
s(n_features=2, n_samples=100, centers=3, random_state=3, cluster_std=[0.8...
# 生成数据集
X, y =
make
_
blob
s(n_samples=150, n_features=2, centers=3, cluster_std=0.5, shuffle=True, random_state=0)
# 使用KMeans
算法
进行
聚类
kmeans = KMeans(n_clusters=3, random_state=0)
kmeans.fit(X)
# 输出聚类结果
print(kmeans.labels_)
其中,
make
_
blob
s函数用于生成数据集,
参数
含义如下:
- n_samples:生成的样本数,默认为100;
- n_features:生成的特征数,默认为2;
- centers:生成的类别数或中心点数,默认为3;
- cluster_std:每个类别的标准差,默认为1.0;
- shuffle:是否打乱样本顺序,默认为True;
- random_state:随机数种子,用于重现实验结果。
KMeans
算法
用于对数据
进行
聚类,
参数
含义如下:
- n_clusters:聚类的类别数;
- random_state:随机数种子,用于重现实验结果。
最后,输出的聚类结果为每个样本所属的类别标签。
【20211123】【Python】修改list/array中的某些数值时,报错TypeError: can only assign an iterable,原因分析及正确的操作方式
【20210825】【数据分析】两个向量做相关性分析时,需不需要统一量纲?
派大星还是海绵宝宝:
【20220627】【信号处理】自相关函数的定义、计算方法及应用
xiurongchen: