K-means-算法核心原理
目录
K-means 算法核心原理
一、K-means 算法核心原理
1. 算法目标
将 n 个样本 划分到 k 个簇 中,使得每个样本到所属簇中心的 距离平方和最小 。
2. 数学公式
目标函数 (SSE,簇内平方误差):
J
∑ i
1 k ∑ x ∈ C i ∥ x − μ i ∥ 2 J = \sum_{i=1}^k \sum_{x \in C_i} |x - \mu_i|^2
J
=
i
=
1
∑
k
x
∈
C
i
∑
∥
x
−
μ
i
∥
2
其中:
C i C_i
C
i
表示第
i i
i 个簇
μ i \mu_i
μ
i
表示第
i i
i 个簇的质心
二、算法步骤详解
是
否
随机初始化k个质心
分配样本到最近质心
重新计算质心位置
质心是否变化?
输出聚类结果
三、Python 代码实现
1. 手动实现(理解原理)
import numpy as np
from sklearn.datasets import make_blobs
class KMeans:
def __init__(self, k=3, max_iter=100):
self.k = k
self.max_iter = max_iter
def fit(self, X):
# 随机初始化质心
self.centroids = X[np.random.choice(X.shape[0], self.k, replace=False)]
for _ in range(self.max_iter):
# 分配样本到最近质心
distances = np.sqrt(((X - self.centroids[:, np.newaxis])**2).sum(axis=2))
labels = np.argmin(distances, axis=0)
# 更新质心
new_centroids = np.array([X[labels == i].mean(axis=0) for i in range(self.k)])
# 收敛判断
if np.allclose(self.centroids, new_centroids):
break
self.centroids = new_centroids
return labels
# 生成测试数据
X, y = make_blobs(n_samples=300, centers=3, cluster_std=0.6, random_state=42)
# 使用手写模型
kmeans = KMeans(k=3)
labels = kmeans.fit(X)
2. Scikit-learn 生产级实现
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
# 数据标准化(重要!)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 建模
kmeans = KMeans(n_clusters=3, init='k-means++', n_init=10)
kmeans.fit(X_scaled)
labels = kmeans.labels_
四、关键参数解析
参数 | 作用 | 推荐值 |
---|---|---|
n_clusters | 指定簇的数量 K | 通过肘部法则确定 |
init | 初始化方法 | 'k-means++' (默认优化) |
n_init | 随机初始化的次数 | 10-50(避免局部最优) |
max_iter | 最大迭代次数 | 300-500(复杂数据) |
五、聚类质量评估
1. 轮廓系数 (Silhouette Score)
s
b − a max ( a , b ) s = \frac{b - a}{\max(a, b)}
s
=
max
(
a
,
b
)
b
−
a
a a
a :样本到同簇其他样本的平均距离
b b
b :样本到最近其他簇样本的平均距离
取值范围:[-1, 1],值越大越好
from sklearn.metrics import silhouette_score
score = silhouette_score(X_scaled, labels)
print(f"轮廓系数:{score:.2f}")
2. 肘部法则 (Elbow Method)
import matplotlib.pyplot as plt
sse = []
k_range = range(1, 10)
for k in k_range:
kmeans = KMeans(n_clusters=k)
kmeans.fit(X_scaled)
sse.append(kmeans.inertia_)
plt.plot(k_range, sse, 'bx-')
plt.xlabel('K')
plt.ylabel('SSE')
plt.title('肘部法则')
plt.show()
六、算法优缺点分析
优点 | 缺点 |
---|---|
简单高效,时间复杂度 O(nkt) | 需要预先指定 K 值 |
适合球形簇结构 | 对噪声和异常值敏感 |
可扩展性强(MiniBatch 变体) | 初始质心选择影响结果 |
结果易于解释 | 不适合非凸形状簇 |
七、工业级优化技巧
1. 数据预处理
标准化 :确保各特征量纲一致
降维 :对高维数据先用 PCA 降维
from sklearn.decomposition import PCA pca = PCA(n_components=0.95) X_pca = pca.fit_transform(X_scaled)
2. 改进初始化方法
使用 K-means++ (Scikit-learn 默认方法):
- 随机选择第一个质心
- 后续质心选择距离已有质心较远的点
3. 处理大数据集
使用 MiniBatch K-means :
from sklearn.cluster import MiniBatchKMeans
mb_kmeans = MiniBatchKMeans(n_clusters=3, batch_size=100)
mb_kmeans.fit(X_scaled)
八、应用案例:客户分群
1. 数据特征
- 年龄、消费金额、购买频率、浏览次数等
2. 实施步骤
数据清洗
特征标准化
PCA降维
K-means聚类
分析簇特征
制定营销策略
3. 分群结果分析
客户群 | 特征 | 营销策略 |
---|---|---|
群组1 | 高消费、低频次 | 推送高端产品 |
群组2 | 低消费、高频次 | 发放优惠券 |
群组3 | 中等消费、浏览量大 | 推荐热门商品 |
九、常见问题解答
Q1:如何选择最佳 K 值?
- 优先使用 轮廓系数 (定量评估)
- 结合 肘部法则 和业务理解
- 尝试 Gap Statistic 等高级方法
Q2:如何处理非球形数据?
使用 谱聚类 或 DBSCAN 替代
通过 核方法 将数据映射到高维空间
from sklearn.cluster import SpectralClustering spec = SpectralClustering(n_clusters=3, affinity='nearest_neighbors') labels = spec.fit_predict(X)
Q3:如何解释聚类结果?
分析每个簇的 特征分布
计算各特征的 簇间差异
df['cluster'] = labels print(df.groupby('cluster').mean())
十、进阶学习建议
- 深入研究 :K-means++ 初始化原理
- 对比算法 :学习 DBSCAN、层次聚类等
- 可视化工具 :掌握 Plotly、Seaborn 的聚类可视化方法
- 实战项目 :尝试电商用户分群、新闻主题聚类等案例