TL;DR
场景:用二维 testSet 验证自写 K-Means,再切到 sklearn KMeans 跑真实数据并理解关键参数与 labels_。
结论:自写版重点在数据形状与标签列约定;sklearn 重点在 n_clusters 选择、收敛与版本参数兼容(algorithm=‘auto’ 风险)。
产出:可复用的验证流程(读数→可视化→聚类→质心可视化)+ KMeans 参数与常见错误速查卡。
算法验证
函数编写完成后,先以 testSet 数据集测试模型运行效果(为了可以直观看出聚类效果,此处采用一个二维数据集进行验证)。testSet 数据集是一个二维数据集,每个观测值都只有两个特征,且数据之间采用空格进行分隔,因此可以使用 pd.read_table() 函数进行读取。
testSet = pd.read_table('testSet.txt', header=None)
testSet.head()
testSet.shape
然后利用二维平面图观察其分布情况:
plt.scatter(testSet.iloc[:,0], testSet.iloc[:,1]);
可以大概看出数据大概分布在空间的四个角上,后续我们对此进行验证。然后利用我们刚才编写的 K-Means 算法对其进行聚类,在执行算法之前需要添加一列虚拟标签列:
label = pd.DataFrame(np.zeros(testSet.shape[0]).reshape(-1, 1))
test_set = pd.concat([testSet, label], axis=1, ignore_index = True)
test_set.head()
带入算法进行计算,根据二维平面坐标点的分布特征,我们可以考虑设置四个质心,即将其分为四个簇:
test_cent, test_cluster = kMeans(test_set, 4)
test_cent
test_cluster.head()
将分类结果进行可视化展示:
import matplotlib.pyplot as plt
# 绘制聚类点
plt.scatter(test_cluster.iloc[:, 0], test_cluster.iloc[:, 1], c=test_cluster.iloc[:, -1], cmap='viridis')
# 绘制聚类中心
plt.scatter(test_cent[:, 0], test_cent[:, 1], color='red', marker='x', s=100)
plt.title('Cluster Plot with Centroids')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.show()
sklearn实现 K-Means
from sklearn.cluster import KMeans
# KMeans 初始化示例
kmeans = KMeans(
n_clusters=8, # 聚类数量
init='k-means++', # 初始化质心的方法
n_init=10, # KMeans 算法重新运行的次数
max_iter=300, # 最大迭代次数
tol=0.0001, # 容忍度,控制收敛的阈值
verbose=0, # 控制输出日志的详细程度
random_state=None, # 随机种子控制聚类的随机性
copy_x=True, # 是否复制 X 数据
algorithm='auto' # 使用的 KMeans 算法,'auto' 已弃用,建议使用 'lloyd'
)
n_clusters
n_clusters 是 K-Means 中的 k ,表示着我们告诉模型我们要分几类,这是 K-Means当中唯一一个必填的参数,默认为 8 类,但通常我们聚类结果是一个小于 8 的结果,通常,在开始聚类的之前,我们并不知道 n_clusters 究竟是多少,因此我们要对它进行探索。
cluster.labels
重要属性 labels_,查看聚好的类别,每个样本所对应的类:
from sklearn.cluster import KMeans
from sklearn.datasets import load_breast_cancer
import numpy as np
# 加载数据集
data = load_breast_cancer()
X = data.data
# 定义聚类的簇数
n_clusters = 3
# 使用KMeans进行聚类
cluster = KMeans(n_clusters=n_clusters, random_state=0).fit(X)
# 获取聚类结果的标签
y_pred = cluster.labels_
# 输出聚类的标签
print(y_pred)
predict 和 fit_predict
- predict:表示学习数据 X 并对 X 的类进行预测
- fit_predict:不需要分类器.fit()之后都可以预测
# 对于全数据而言
# 分类器 fit().predict 的结果 = 分类器.fit_predict(X) = cluster.labels
错误速查
| 症状 | 根因 | 修复 |
|---|---|---|
| K-Means 聚类结果异常/全被分到一类 | 输入数据列约定不一致 | 检查 kMeans 内部对特征列的切片逻辑 |
| sklearn KMeans 报弃用/警告 | algorithm=‘auto’ 在新版本中可能弃用 | 将 algorithm 改为 ‘lloyd’ |
| make_blobs centers=4,但后续按”两类 y=0/1”绘图 | 示例逻辑不一致 | 统一为”4 簇示例”并说明 y 的取值范围 |
| 聚类图颜色混乱/看不出簇 | c 参数传入的标签列 dtype 不符合预期 | 确保标签列是整数类别;绘图前显式转 int |
| 结果不可复现:每次运行质心不同 | random_state=None | 固定 random_state;必要时增大 n_init |