一、 算法步骤
用数学方法来描述K-均值算法,算法又两个输入信息,一个是k, 表示选取的的聚类个数,另一个是训练数据集。
(1)随机选择k个聚类中心,。
(2)从1-m中遍历所有的数据集,计算分别到
的距离,记录距离最短的聚类中心点
,
, 然后把这个点分配给这个聚类,即令
。计算距离时,一般用
来计算。
(3)从1~k遍历所有的聚类中心,移动聚类中心的新位置到这个聚类的均值处,即,其中c表示分配这个聚类的训练样例点的个数,
表示属于
这个类的点。
(4)重复步骤(2),直到聚类中心不再移动为止。
二、最佳K的选择
用elbow图选择最佳的k。Elbow图 是一种用于绘制聚类数量(K)与对应聚类模型整体评估指标(通常是簇内平方和)之间关系的折线图。其核心思想是:随着聚类数K的增加,每个簇内的样本会越来越“紧凑”,模型的表现指标会不断改善。但改善的幅度会在某个点出现急剧下降,之后趋于平缓。这个转折点形如人的“肘部”,故得名“肘部法则”。该点对应的K值通常被认为是最佳的聚类数量。
最常用于绘制Elbow图的指标是 WCSS。
· 定义:数据集中每个点到其所属簇的质心(中心点)的距离平方和的总和。
· 计算公式:
WCSS = Σ(对于每个簇k) Σ(对于簇k中的每个点i) || x_i - c_k ||²
其中,x_i 是簇k中的一个数据点,c_k 是簇k的质心。
· 直观理解:WCSS衡量了簇的紧凑程度。WCSS值越小,说明簇内的点离中心越近,簇越紧密。
· 变化规律:当K=1时,WCSS最大。随着K值增加,每个簇包含的点更少、更紧凑,因此WCSS会单调递减。因此目标时找到WCSS下降速度突然变换的那个“转折点”。
1. 选择K的范围:通常选择一个合理的范围,例如 K=1 到 K=10 或 15。
2. 对每个K值进行聚类:对于范围内的每一个K值,运行K-Means算法(或其它聚类算法)。
3. 计算每个K对应的WCSS:保存每次聚类结果的WCSS值。
4. 绘图:以K值为横坐标,对应的WCSS值为纵坐标,绘制折线图。
5. 寻找“肘部”:观察图形,找到曲线从“陡峭”转向“平缓”的“转折点。该点对应的K值就是通过肘部法则推荐的最佳聚类数。
同时可以用轮廓系数佐证:
轮廓系数由以下两个指标构成:
a: 一个样本与其所在一个聚类里其他样本的平均距离。
b: 一个样本与其距离最近的下一个聚类里的样本的平均距离。
最终计算公式: s(轮廓系数) = ,值介于[-1,1]之间,-1表示完全错误的聚类,1表示完美的聚类,0表示聚类重叠。
三、实例代码
实例1:
# 生成聚类数据并写入文件
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 设置随机种子以便于重现
np.random.seed(42)
# 生成数据
num_samples = 500 # 样本数量
num_features = 2 # 特征数量
# 生成聚类数据
X = np.random.rand(num_samples, num_features)
# 添加一些聚类中心 为了方便演示而添加
centers = np.array([[0.2, 0.3], [0.8, 0.7], [0.5, 0.5]])
for center in centers:
X = np.vstack([X, np.random.randn(90, num_features) * 0.1 + center])
# 创建DataFrame
df = pd.DataFrame(X, columns=['Feature1', 'Feature2' ])
plt.xlabel('feature1')
plt.ylabel('feature2')
plt.plot(df['Feature1'], df['Feature2'], 'o')
# 保存到Excel文件
excel_file = 'clustering_data.xlsx'
df.to_excel(excel_file, index=False)
print(f"数据已保存到 {excel_file}")
结果:

from sklearn.cluster import KMeans
#搜索最佳K值 通过显示 elbow图 选择
data = pd.read_excel('clustering_data.xlsx') # 默认读取第一个sheet
print(data.head()) # 预览数据
# '利用簇内距离平方和 选择k'
SSE = [] # 存放每次结果的误差平方和
for k in range(1, 9):
estimator = KMeans(n_clusters=k) # 构造聚类器
estimator.fit(np.array(data[['Feature1', 'Feature2']]))
SSE.append(estimator.inertia_) # sum of squared errors
X = range(1, 9)
plt.xlabel('k')
plt.ylabel('SSE')
plt.plot(X, SSE, 'o-')
plt.show()
结果:

用轮廓系数佐证:
# 用轮廓系数选择K值
from sklearn.metrics import silhouette_score
#用来正常显示中文标签
plt.rcParams['font.sans-serif']=['SimHei']
Scores= []
for k in range(2, 9):
estimator = KMeans(n_clusters=k) # 构造聚类器
estimator.fit(np.array(data[['Feature1', 'Feature2']]))
Scores.append(silhouette_score(np.array(np.array(data[['Feature1', 'Feature2']])), estimator.labels_, metric='euclidean'))
# print(Scores)
X = range(2, 9)
plt.xlabel('k')
plt.ylabel('轮廓系数')
plt.plot(X, Scores, 'o-')
plt.show()
结果:

可见聚类簇数在5是最佳的,3、4是可选的。
实例2:
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
#生成实验数据 预设簇数为5;
from sklearn.datasets import make_blobs
X, y = make_blobs(n_samples=200,
n_features=2,
centers=5,
cluster_std=1,
center_box=(-10.0, 10.0),
shuffle=True,
random_state=1);
#展示数据
plt.figure(figsize=(6,4), dpi=144)
plt.xticks(())
plt.yticks(())
plt.scatter(X[:, 0], X[:, 1], s=20, marker='o');
生成的示例数据:

# '利用SSE选择k'
SSE = [] # 存放每次结果的误差平方和
for k in range(1, 9):
estimator = KMeans(n_clusters=k) # 构造聚类器
estimator.fit(X)
SSE.append(estimator.inertia_) # sum of squared errors
X = range(1, 9)
plt.xlabel('k')
plt.ylabel('SSE')
plt.plot(X, SSE, 'o-')
plt.show()
用elbow图确定最佳k为5:

簇类结果展示:

# 用轮廓系数选择K值或佐证K值
from sklearn.metrics import silhoukette_score
#用来正常显示中文标签
plt.rcParams['font.sans-serif']=['SimHei']
Scores= []
for k in range(2, 9):
estimator = KMeans(n_clusters=k) # 构造聚类器
estimator.fit(np.array(data[['Feature1', 'Feature2']]))
Scores.append(silhouette_score(np.array(np.array(data[['Feature1', 'Feature2']])), estimator.labels_, metric='euclidean'))
# print(Scores)
X = range(2, 9)
plt.xlabel('k')
plt.ylabel('轮廓系数')
plt.plot(X, Scores, 'o-')
plt.show()
结合elbow图,在轮廓系数图中,选取最佳k为5。



1万+

被折叠的 条评论
为什么被折叠?



