聚類屬於無監督學習,就是對大量未標註的數據集就,按數據的內在相似性將數據集劃分爲多個類別,使類別內的數據相似度較大而類別間的數據相似度較小。
1.K-Means算法實現
算法實現:
- 未聚類的初始點集;
- 隨機選取兩個點作爲聚類中心;
- 計算每個點到聚類中心的距離,並聚類到離該點最近的聚類中去;
- 計算每個聚類中所有點的座標平均值,並將這個平均值作爲新的聚類中心;
- 重複(3),計算每個點到聚類中心的距離,並聚類到離該點最近的聚類中去;
- 重複(4),計算每個聚類中所有點的座標平均值,並將這個平均值作爲新的聚類中心。
K-Means結束條件:直到類中心不再進行大範圍移動或者聚類迭代次數達到要求爲止。
2.相似度計算方法
1.歐式距離
2.餘弦距離
3.K的初始位置
- 從輸入的數據點集合中隨機選擇一個點作爲第一個聚類中心。
- 對於數據集中的每一個點x,計算它與最近聚類中心(指已選擇的聚類中心)的聚離D(x)。
- 選擇一個新的數據點作爲新的聚類中心,選擇的原則是:D(x)較大的點,被選取作爲聚類中心的概率較大。
- 重複2和3直到k個聚類中心被選出來。
- 利用這k個初始的聚類中心來運行標準的K-Means算法。
4.K-Means的優劣
優點:
1)是解決聚類問題的一種經典算法,簡答、快速。
2)是處理大數據集,該算法保持可伸縮性和高效率。
3)當結果簇是密集的,它的效果較好。
缺點:
1)必須事先給出k(要生成的簇的數目),而且對初值敏感,對於不同的初始值,可能會導致不同結果。
2)對噪聲和孤立點數據敏感。
5.代碼實現
package com.dengdan
import org.apache.spark.mllib.clustering.{KMeans, KMeansModel}
import org.apache.spark.mllib.linalg.Vectors
import org.apache.spark.{SparkConf, SparkContext}
object KmeansCluster extends App {
val sc = new SparkContext(new SparkConf().setMaster("local[4]").setAppName("K-Means"))
//加載數據
val path = "D:\\idea_workspace2020\\spark\\sparkMLib\\kmeans\\src\\main\\resources\\data.txt"
val data = sc.textFile(path)
val parsedData = data.map(s => Vectors.dense(s.split(' ').map(_.toDouble))).cache()
//通過KMeans將數據分成兩個陣營
val numClusters = 2
val numIterations = 20
val clusters = KMeans.train(parsedData, numClusters, numIterations)
//輸出當前的聚類中心
clusters.clusterCenters.foreach(println _)
//進行預測
val index = clusters.predict(Vectors.dense(Array(8.9, 7.2, 9.0)))
println(s"Vector[8.9, 7.2, 9.0]屬於聚類索引爲${index} 中心座標爲:${clusters.clusterCenters(index)}")
//計算誤差平方和
val WSSSE = clusters.computeCost(parsedData)
println(s"誤差平方和= ${WSSSE}")
//模型存儲位置
var modelPath = "target/tmp/KMeansModel"
//保存模型
clusters.save(sc, modelPath)
//加載模型
val sameModel = KMeansModel.load(sc, modelPath)
sc.stop()
}