早期机器学习 - K-Means
K-means 聚类
- 输入类的数目和特征向量,输出类使平方误差最小
方法
# 导入 numpy 和 matplotlib.pyplot
import numpy as np
import matplotlib.pyplot as plt
# 随机生成数据
np.random.seed(0)
# np.vtack: 沿着竖直方向将矩阵堆叠起来
# np.random.normal: 生成正态分布的随机数, loc: 均值, scale: 标准差, size: 生成的随机数的形状, 100行2列
data = np.vstack([
np.random.normal(loc=[0, 0], scale=1, size=(100, 2)),
np.random.normal(loc=[5, 5], scale=1, size=(100, 2)),
np.random.normal(loc=[10, 10], scale=1, size=(100, 2)),
])
# 可视化数据
# plt.scatter(data[:, 0], data[:, 1], s=5) # x 轴是第一列, y 轴是第二列, s: 点的大小
# plt.show()
# 实现 k_means(data, k, max_iters=100) 函数, 返回 labels, centroids
def k_means(data, k, max_iters=100):
# 随机初始化聚类中心
centroids = data[np.random.choice(len(data), k, replace=False)]
for _ in range(max_iters):
# 计算每个样本点到聚类中心的距离
distances = np.linalg.norm(data[:, np.newaxis] - centroids, axis=2)
# 分配聚类
labels = np.argmin(distances, axis=1)
# 计算新的聚类中心
new_centroids = np.array([data[labels == i].mean(axis=0) for i in range(k)])
# 如果新的聚类中心和旧的聚类中心相同, 则停止迭代
if np.all(centroids == new_centroids):
break
centroids = new_centroids
return labels, centroids
# 设置聚类数量
k = 3
# 运行 k-means 算法
labels, centroids = k_means(data, k)
# 可视化聚类结果
plt.scatter(data[:, 0], data[:, 1], c=labels, s=5)
plt.scatter(centroids[:, 0], centroids[:, 1], c='r', s=50)
plt.show()
改进
- 对于不同的k都尝试聚类 - Bisectional k-means
- 排除噪声,尝试多种初值组合
质量评价
- RLHF
- 纯度 Purity
- 对形成的聚类\displaystyle r, 若其中真属于类\displaystyle i的有\displaystyle n_{r}^i, 纯度\displaystyle P(S_{r})=\frac{1}{n_{r}}\max n_{r}^i
- 整个结果 \displaystyle Purity = \sum_{r=1}^k \frac{n_{r}}{n}P(S_{r})
- F值 F-measure:\displaystyle precision 和 \displaystyle recall 的调和平均