Spark Kmeans聚类算法由来原理方法示例源码分析 点击这里免费看全文
文章目录
K-means++ 是一种改进的 K-means 聚类算法,旨在选择更好的初始聚类中心点。以下是 Spark 中 K-means++ 的全面介绍
由来
传统的 K-means 算法是通过随机选择初始聚类中心点来开始聚类过程。然而,随机选择的初始中心可能导致收敛到局部最优解的风险增加,即结果聚类质量较差。
为了解决这个问题,Arthur 和 Vassilvitskii 在 2007 年提出了 K-means++ 算法。它使用一种概率性的方法来选择初始聚类中心,从而使得初始中心能够更好地代表数据集,减少陷入局部最优解的可能性。
原理
K-means++ 的初始化过程如下:
- 从数据集中随机选择一个样本作为第一个聚类中心。
- 对于每个样本,计算它与已选择的聚类中心的最短距离(即到最近的聚类中心的距离)。
- 根据每个样本与已选择的聚类中心的最短距离,以概率分布的方式选择下一个聚类中心。距离较远的样本被选择为下一个聚类中心的概率较大。
- 重复步骤 2 和 3,直到选择出 k 个聚类中心。
K-means++ 的核心思想是通过引入概率选择机制,使得选择的初始聚类中心在整个数据集中分布更加均匀。这样做的好处是能够更好地代表数据集,从而改善最终聚类结果的质量。
在 Spark 中,K-means++ 算法被用作默认的初始化算法,它可以通过设置 initMode
参数为 "k-means||"
来启用。通过使用 K-means++ 初始化算法,Spark 能够提供更可靠和高质量的聚类结果。
示例RDD版
import org.apache.spark.mllib.clustering.{
KMeans, KMeansModel}
import org.apache.spark.mllib.linalg.Vectors
// Load and parse the data
val data = sc.textFile("data/mllib/kmeans_data.txt")
val parsedData = data.map(s => Vectors.dense(s.split(' ').map(_.toDouble))).cache()
// Cluster the data into two classes using KMeans
val numClusters = 2
val numIterations = 20
val clusters = KMeans.train(parsedData, numClusters, numIterations)
// Evaluate clustering by computing Within Set Sum of Squared Errors
val WSSSE = clusters.computeCost(parsedData)
println(s"Within Set Sum of Squared Errors = $WSSSE")
// Save and load model
clusters.save(sc, "target/org/apache/spark/KMeansExample/KMeansModel")
val sameModel = KMeansModel.load(sc, "target/org/apache/spark/KMeansExample/KMeansModel")
示例DataFrame版本
import org.apache.spark.ml.clustering.KMeans
import org.apache.spark.ml.evaluation.ClusteringEvaluator
// Loads data.
val dataset = spark.read.format("libsvm").load("data/mllib/sample_kmeans_data.txt")
// Trains a k-means model.
val kmeans = new KMeans().setK(2).setSeed(1L)
val model = kmeans.fit(dataset)
// Make predictions
val predictions = model.transform(dataset)
// Evaluate clustering by computing Silhouette score
val evaluator = new ClusteringEvaluator()
val silhouette = evaluator.evaluate(predictions)
println(s"Silhouette with squared euclidean distance = $silhouette")
// Shows the result.
println("Cluster Centers: ")
model.clusterCenters.foreach(println)
方法详细说明
-
load
:从指定路径加载 KMeans 模型。load(path: String): KMeansModel
- 从指定路径加载保存的 KMeans 模型。
- 参数:
path
:模型的保存路径。
- 返回值:KMeansModel 对象,表示加载的 KMeans 模型。
-
read
:返回一个用于读取 KMeans 模型的 MLReader 对象。read(): MLReader[KMeansModel]
- 返回一个用于读取 KMeans 模型的 MLReader 对象。
- 返回值:MLReader[KMeansModel] 对象,用于读取 KMeans 模型。
-
k
:获取聚类数目(k)的参数。k: IntParam
- 获取聚类数目(k)的参数。注意,实际返回的聚类数目可能少于 k,例如如果数据集中的不同点数量少于 k。
- 返回值:IntParam 对象,表示聚类数目。
-
initMode
:获取初始化算法的参数。initMode: Param[String]
- 获取初始化算法的参数。可以选择 “random” 以随机选择初始聚类中心,或选择 “k-means||” 使用 k-means++ 的并行变种算法。
- 返回值:Param[String] 对象,表示初始化算法。
-
initSteps
:获取 k-means|| 初始化模式的步数参数。initSteps: IntParam
- 获取 k-means|| 初始化模式的步数参数。这是一个高级设置,通常默认值 2 已经足够。
- 返回值:IntParam 对象,表示初始化步数。
-
solver
:获取优化方法的参数。solver: Param[String]
- 获取用于优化的方法的参数。支持的选项有:“auto”、“row” 和 “block”。默认为 “auto”。
- 返回值:Param[String] 对象,表示优化方法。
-
maxBlockSizeInMB
:获取将输入数据堆叠到块中的最大内存限制的参数。maxBlockSizeInMB: DoubleParam
- 获取将输入数据堆叠到块中的最大内存限制的参数。默认值为 0.0,表示自动选择最佳值。
- 返回值:DoubleParam 对象,表示最大内存限制。
-
weightCol
:获取权重列名的参数。weightCol: Param[String]
- 获取权重列名的参数。如果未设置或为空,则将所有实例权重视为 1.0。
- 返回值:Param[String] 对象,表示权重列名。
-
distanceMeasure
:获取距离度量的参数。distanceMeasure: Param[String]
- 获取距离度量的参数。支持的选项有:“euclidean” 和 “cosine”。
- 返回值:Param[String] 对象,表示距离度量。
-
tol
:获取迭代算法的收敛容忍度的参数。tol: DoubleParam
- 获取迭代算法的收敛容忍度的参数。必须大于等于 0。
- 返回值:DoubleParam 对象,表示容忍度。
-
predictionCol
:获取预测结果列名的参数。predictionCol: Param[String]
- 获取预测结果列名的参数。
- 返回值:Param[String] 对象,表示预测结果列名。
-
seed
:获取随机种子的参数。seed: LongParam
- 获取随机种子的参数。
- 返回值:LongParam 对象,表示随机种子。
-
featuresCol
:获取特征列名的参数。featuresCol: Param[String]
- 获取特征列名的参数。
- 返回值:Param[String] 对象,表示特征列名。
-
maxIter
:获取最大迭代次数的参数。maxIter: IntParam
- 获取最大迭代次数的参数。必须大于等于 0。
- 返回值:IntParam 对象,表示最大迭代次数。
-
uid
:获取对象的唯一 ID。uid: String
- 获取对象及其派生对象的不可变唯一 ID。
- 返回值:String,表示对象的唯一 ID。
-
copy
:创建一个具有相同 UID 和额外参数的当前实例的副本。copy(extra: ParamMap): KMeans
- 创建当前实例的副本,并带有相同的 UID 和额外的参数。
- 参数:
extra
:ParamMap 对象,用于指定额外的参数。
- 返回值:KMeans 对象的副本。
-
fit
:将模型应用于输入数据,拟合出一个模型。fit(dataset: Dataset[_]): KMeansModel
- 将模型应用于输入数据,并拟合出一个 KMeansModel 模型。
- 参数:
dataset
:要拟合的输入数据集。
- 返回值:KMeansModel 对象,表示拟合得到的 KMeans 模型。
-
transformSchema
:检查转换的有效性,并根据输入模式推导出输出模式。transformSchema(schema: StructType): StructType
- 检查转换的有效性,并根据输入模式推导出输出模式。
- 参数:
schema
:输入数据的模式。
- 返回值:StructType 对象,表示输出数据的模式。
中文源码
object KMeans
/**
* 用于调用K-means聚类的顶层方法。
*/
@Since("0.8.0")
object KMeans {
// 初始化模式名称
@Since("0.8.0")
val RANDOM = "随机"
@Since("0.8.0")
val K_MEANS_PARALLEL = "k-means||"
/**
* 使用给定的参数训练一个K-means模型。
*
* @param data 训练数据点,作为`Vector`类型的RDD。
* @param k 要创建的簇的数量。
* @param maxIterations 允许的最大迭代次数。
* @param initializationMode 初始化算法。可以是"random"或"k-means||"。(默认值:"k-means||")
* @param seed 随机种子用于簇初始化。默认是基于系统时间生成种子。
*/
@Since("2.1.0")
def train(
data: RDD[Vector],
k: Int,
maxIterations: Int,
initializationMode: String,
seed: Long): KMeansModel = {
new KMeans().setK(k)
.setMaxIterations(maxIterations)
.setInitializationMode(initializationMode)
.setSeed(seed)
.run(data)
}
/**
* 使用给定的参数训练一个K-means模型。
*
* @param data 训练数据点,作为`Vector`类型的RDD。
* @param k 要创建的簇的数量。
* @param maxIterations 允许的最大迭代次数。
* @param initializationMode 初始化算法。可以是"random"或"k-means||"。(默认值:"k-means||")
*/
@Since("2.1.0")
def train(
data: RDD[Vector],
k: Int,
maxIterations: Int,
initializationMode: String): KMeansModel = {
new KMeans().setK(k)
.setMaxIterations(maxIterations)
.setInitializationMode(initializationMode)
.run(data)
}
/**
* 使用给定的参数训练一个K-means模型。
*
* @param data 训练数据点,作为`Vector`类型的RDD。
* @param k 要创建的簇的数量。
* @param maxIterations 允许的最大迭代次数。
* @param runs 从Spark 2.0.0开始,此参数不起作用。
* @param initializationMode 初始化算法。可以是"random"或"k-means||"。(默认值:"k-means||")
* @param seed 随机种子用于簇初始化。默认是基于系统时间生成种子。
*/
@Since("1.3.0")
@deprecated("使用不带'runs'参数的train方法", "2.1.0")
def train(
data: RDD[Vector],
k: Int,
maxIterations: Int,
runs: Int,
initializationMode: String,
seed: Long): KMeansModel = {
new KMeans().setK(k)
.setMaxIterations(maxIterations)
.setInitializationMode(initializationMode)
.setSeed(seed)
.run(data)
}
/**
* 使用给定的参数训练一个K-means模型。
*
* @param data 训练数据点,作为`Vector`类型的RDD。
* @param k 要创建的簇的数量。
* @param maxIterations 允许的最大迭代次数。
* @param runs 从Spark 2.0.0开始,此参数不起作用。
* @param initializationMode 初始化算法。可以是"random"或"k-means||"。(默认值:"k-means||")
*/
@Since("0.8.0")
@deprecated("使用不带'runs'参数的train方法", "2.1.0")
def train(
data: RDD[Vector],
k: Int,
maxIterations: Int,
runs: Int,
initializationMode: String): KMeansModel = {
new KMeans().setK(k)
.setMaxIterations(maxIterations)
.setInitializationMode(initializationMode)
.run(data)
}
/**
* 使用指定的参数和未指定参数的默认值训练一个K-means模型。
*/
@Since("0.8.0")
def train(
data: RDD[Vector],
k: Int,
maxIterations: Int): KMeansModel = {
new KMeans().setK(k)
.setMaxIterations(maxIterations)
.run(data)
}
/**
* 使用指定的参数和未指定参数的默认值训练一个K-means模型。
*/
@Since("0.8.0")
@deprecated("使用不带'runs'参数的train方法", "2.1.0"