K-means
优缺点
优点:容易实现
缺点:可能收敛到局部最小值,在大规模数据集上收敛较慢
步骤
- 选择K个点作为初始聚类中心
- 计算其余所有点到聚类中心的距离,并把每个点划分到离它最近的聚类中心所在的聚类中去。计算距离常用欧几里得距离公式,也叫欧氏距离。查看距离的计算方法
- 重新计算每个聚类中所有点的平均值,并将其作为新的聚类中心点。
- 重复2、3步,直到聚类中心不再发生改变,或者算法达到预定的迭代次数,又或聚类中心的改变小于预先设定的阈值
使用后处理来提高聚类性能
局部最小值指结果还可以但并非最好结果,全局最小值是可能的最好结果
一种用于度量聚类效果的指标是SSE(误差平方和)。SSE值越小表示数据点越接近它们的质心。
后处理方法:将具有最大SSE值的簇划分成为两个簇;合并最近的质心,或者合并两个使得SSE增幅最小的质心。
二分K-Means算法
- 将所有点作为一个簇,然后将该簇一分为二;
- 之后选择其中一个簇继续进行划分,选择哪一个簇进行划分取决于对其划分是否可以最大程度降低SSE的值。
- 不断重复SSE的划分过程,直到得到用户指定的簇数目为止。
Spark实现KMeans
关键步骤
聚类个数K的选择
Spark MLlib 在 KMeansModel 类里提供了 computeCost 方法,该方法通过计算所有数据点到其最近的中心点的平方和来评估聚类的效果。一般来说,同样的迭代次数和算法跑的次数,这个值越小代表聚类的效果越好。但是在实际情况下,我们还要考虑到聚类结果的可解释性,不能一味的选择使 computeCost 结果值最小的那个 K。
初始聚类中心点的选择
Spark MLlib K-means算法的实现在初始聚类点的选择上,借鉴了K-means||的类K-means++实现。K-means++算法在初始点选择上遵循一个基本原则:初始聚类中心点相互之间的距离应该尽可能的远。基本步骤如下:
1. 从数据集中随机选择一个点作为第一个初始点
2. 计算数据集中所有点与最新选择的中心点的距离D(x)
3. 选择下一个中心点,使得
最大
4. 重复2、3步,直到K个初始点选择完成
MLlib的K-means实现
- 读取训练数据,调用KMeans.train方法对数据集进行聚类训练,方法返回KMeansModel实例
- 使用KMeansModel.predict方法对新的数据点进行所属聚类的预测
- 均方差(MSE),就是对各个实际存在评分的项,pow(预测评分-实际评分,2)的值进行累加,再除以项数。而均方根差(RMSE)就是MSE开根号。MSE/RMSE值越小说明预测结果越准确
参数
参数 | 含义 |
---|---|
k | 所需簇的数量。请注意,可以返回少于k个集群,例如,如果有少于k个不同的集群点 |
maxIterations | 运行的最大迭代次数。 |
initializationMode | 通过k-means ||指定随机初始化或初始化。 |
initializationSteps | 确定k-means ||中的步数算法。 |
epsilon | 确定我们认为k均值收敛的距离阈值。 |
initialModel | 用于初始化的可选集群中心集。如果提供此参数,则仅执行一次运行。 |
Spark_K-Means_Python
from __future__ import print_function
from numpy import array
from math import sqrt
from pyspark import SparkContext
from pyspark.mllib.clustering import KMeans, KMeansModel
if __name__ == "__main__":
sc = SparkContext(appName="KmeansExample")
# Load and parse the data
data = sc.textFile("kmeans_data.txt")
parsedData = data.map(lambda line:array([float(x) for x in line.split(' ')]))
# Build the Model(cluster the data)
clusters = KMeans.train(parsedData, 2, maxIterations=10, initializationMode="random")
print(clusters.clusterCenters)
print(clusters.predict([0.2, 0.2, 0.2]))
# Evaluate clustering by computing Within Set Sum of Squared Errors
def error(point):
center = clusters.centers[clusters.predict(point)]
return sqrt(sum([x**2 for x in (point - center)]))
WSSSE = parsedData.map(lambda point: error(point)).reduce(lambda x, y: x + y)
print("Within Set Sum of Squared Error = " + str(WSSSE))