1 K-means算法
K-means是最普及的聚类算法,算法接受一个未标记的数据集,然后将数据聚类成不同的组。
它是一个迭代算法,假设我们想要将数据聚类成 n 个组,其方法为:
- 选择K个随机的点,称为聚类中心
- 对于数据集中的每一个数据,按照距离K个中心点的距离,将其与距离最近的中心点关联起来,与同一个中心点关联的所有点聚成一类
- 计算每一类的平均值,将该类所关联的中心点移动到平均值的位置
- 重复步骤2-3,直至中心点不再变化
伪代码表示为:
Repeat {
for i = 1 to m
c(i) := 当前样本x(i)与k个聚类中心中距离最近的索引 index (form 1 to K) of cluster centroid closest to x(i)
for k = 1 to K
μk := k聚类中样本的均值,即聚类中心 average (mean) of points assigned to cluster k
}
1.1 优化目标
用μ^1,μ^2,...,μ^k 来表示聚类中心,用c^(1),c^(2),...,c^(m)来存储与第i个实例数据最近的聚类中心的索引,μ_(c^(i))表示当前样本x^(i)所处的簇中心,其代价函数与优化目标如下图所示
由上图可知,K-means算法的优化目标即是找出使得代价函数最小的c^(i)和μ^(i)
1.2 随机初始化
在运行 K-均值算法之前,首先要随机初始化所有的聚类中心点
1. 选择K<m,即聚类中心点的个数要小于所有训练集实例的数量
2. 随机选择K个训练实例(x^(i)),然后令K个聚类中心分别与这K个训练示例相等
K-means的一个问题为,他有可能会停留在一个局部最小值处,解决这个问题的方法如下:
多次运行 K-均值算法,每一次都重新进行随机初始化,最后再比较多次运行 K-means的结果,选择代价函数最小的结果。
这种方法在 较小的时候(2-10)还是可行的,但是如果 较大,这么做也可能不会有明显地改善。
1.3 选择聚类数
一个是肘部法则,不断改变K值,计算每一个K的代价,如下图左所示,如若出现了一个类似于肘关节的拐点的话,那么就采用该K值,但如果像下图右所示,是较为光滑的曲线的话,就不能用肘部法则去选择K值。
大多数情况下聚类个数都是根据各训练示例可视化之后手动选择的
2 实现方法
2.1 将各样本点分簇
def find_closest_centroids(X, centroids):m = X.shape[0]k = centroids.shape[0]idx = np.zeros(m) # idx[i]为距离样本i最近的集聚中心的索引for i in range(m):min_dist = 1000000 #每计算完一个样本点后需要将最短距重新初始化 for j in range(k):dist = np.sum((X[i,:] - centroids[j,:]) ** 2) #代价函数if dist < min_dist:min_dist = distidx[i] = jreturn idx
2.2 计算各簇的所有样本的平均值
def compute_centroids(X, idx, k): #k为聚类中心个数m, n = X.shape centroids = np.zeros((k, n)) #聚类中心为(k,n)for i in range(k):indices = np.where(idx == i) #为i簇的各样本点的索引centroids[i,:] = (np.sum(X[indices,:], axis=1) / len(indices[0])).ravel() #len(indices[0])为样本点的数量,axis=1为按列相加 return centroid
2.3 随机初始化
def init_centroids(X, k):m, n = X.shapecentroids = np.zeros((k, n))idx = np.random.randint(0, m, k)for i in range(k):centroids[i,:] = X[idx[i],:] #随机选择训练示例作为聚类中心return centroids
2.4 聚类算法实现
def run_k_means(X, initial_centroids, max_iters):m, n = X.shapek = initial_centroids.shape[0]idx = np.zeros(m)centroids = initial_centroidsfor i in range(max_iters):idx = find_closest_centroids(X, centroids)centroids = compute_centroids(X, idx, k)return idx, centroids# 使用sklearn实现
from sklearn.cluster import KMeans #导入kmeans库model = KMeans(n_clusters=16, n_init=100, n_jobs=-1)
model.fit(data) #用数据拟合分类器模型
centroids = model.cluster_centers_
C = model.predict(data) #输出输入数据的预测结果
笔记参考资料:fengdu78/Coursera-ML-AndrewNg-Notes: 吴恩达老师的机器学习课程个人笔记