您现在的位置是:首页 > 文章详情

Spark-K-Means算法

日期:2016-06-19点击:411

机器学习算法大体分为三类:监督学习(supervised learning)、无监督学习(unsupervised learning)和半监督学习(semi-supervised learning)。监督学习是指我们利用带有类别属性标注的数据去训练、学习,用于预测未知数据的类别属性。例如,根据用户之前的购物行为去预测用户是否会购买某一商品。常用的算法有决策树,支持向量机SVM,朴素贝叶斯分类器,K-近邻算法KNN,线性回归和逻辑回归等.无监督学习是指在无人工干预的情况下将数据按照相似程度划分,而聚类算法就是非常典型的无监督学习方法,通常要处理的数据没有标签信息,可以通过计算数据之间的相似性来自动划分类别。

K-Means算法

算法的思想是初始随机给定K个簇中心,按照距离最近原则把待分类的样本点分到各个簇,然后按平均法重新计算各个簇的质心,从而确定新的簇心,迭代计算,直到簇心的移动距离小于某个给定的误差值。使用算法描述语言,只要四个步骤:

任意选择K个点作为初始聚类中心;
计算每个样本点到聚类中心的距离,将每个样本点划分到离该点最近的聚类中去;
计算每个聚类中所有点的坐标平均值,并将这个平均值作为新的聚类中心;
反复执行2、3,直到聚类中心的移动小于某误差值或者聚类次数达到要求为止。

这里计算距离的方法通常是计算欧几里得距离,假设中心点center是(x1, y1),需要计算的样本点point是(x2, y2):

另外,给出损失函数(Cost Function),每一次选取好新的中心点,我们就要计算一下当前选好的中心点损失为多少,这个损失代表着偏移量,越大说明当前聚类的效果越差,计算公式称为(Within-Cluster Sum of Squares, WCSS):

其中,xi表示某一对象,ck表示该对象所属类别的中心点。整个式子的含义就是对各个类别下的对象,求对象与中心点的欧式距离的平方,把所有的平方求和就是L(C)。

测试数据: 0.0 0.0 0.1 0.1 0.2 0.2 3.0 3.0 3.1 3.1 3.2 3.2 9.0 9.0 9.1 9.1 9.2 9.2
import org.apache.spark.mllib.clustering.KMeans import org.apache.spark.mllib.linalg.Vectors import org.apache.spark.{SparkConf, SparkContext} object KMeansTest { def main(args: Array[String]) { val conf = new SparkConf() val sc = new SparkContext(conf) val data =sc.textFile(args(0)) val parsedData =data.map(s => Vectors.dense(s.split(' ').map(_.trim.toDouble))).cache() //设置簇的个数为3 val numClusters =3 //迭代20次 val numIterations= 20 //运行10次,选出最优解 val runs=10 //设置初始K选取方式为k-means++ val initMode = "k-means||" val clusters = new KMeans(). setInitializationMode(initMode). setK(numClusters). setMaxIterations(numIterations). run(parsedData) //打印出测试数据属于哪个簇 println(parsedData.map(v=> v.toString() + " belong to cluster :" +clusters.predict(v)).collect().mkString("\n")) // Evaluateclustering by computing Within Set Sum of Squared Errors val WSSSE = clusters.computeCost(parsedData) println("WithinSet Sum of Squared Errors = " + WSSSE) val a21 =clusters.predict(Vectors.dense(1.2,1.3)) val a22 =clusters.predict(Vectors.dense(4.1,4.2)) //打印出中心点 println("Clustercenters:") for (center <-clusters.clusterCenters) { println(" "+ center) } println("Prediction of (1.2,1.3)-->"+a21) println("Prediction of (4.1,4.2)-->"+a22) } }
提交spark执行(standalone): spark-submit --class KMeansTest --master local[4] KMeansTest.jar ../data/kmeans_data.txt

K-Means算法有两个重大缺陷:

K-Means属于无监督学习,最大的特别和优势在于模型的建立不需要训练数据。在日常工作中,很多情况下没有办法事先获取到有效的训练数据,这时采用K-Means是一个不错的选择。K值是预先给定的,属于预先知识,很多情况下K值的估计是非常困难的,对于像计算全部微信用户的交往圈这样的场景就完全的没办法用K-Means进行。对于可以确定K值不会太大但不明确精确的K值的场景,可以进行迭代运算,然后找出Cost Function最小时所对应的K值,这个值往往能较好的描述有多少个簇类。
K-Means算法对初始选取的聚类中心点是敏感的,不同的随机种子点得到的聚类结果完全不同。可以用K-Means++算法来解决这个问题
K-Means++算法选择初始聚类中心的思想是:初始的聚类中心之间的相互距离要尽可能远。算法步骤如下:

随机挑选一个点作为第一个聚类中心;
对于每一个点x,计算和其最近的一个聚类中心的距离D(x),将所有距离求和得到Sum(D(x));
然后,再取一个随机值,用权重的方式来取计算下一个“种子点”。这个算法的思想是,先取一个能落在Sum(D(x))中的随机值Random,然后用Random -= D(x),直到其<=0,此时的点就是下一个“种子点”(其思想是,D(x)较大的点,被选取作为聚类中心的概率较大);
重复2和3,直到K个聚类中心被选出来;
利用这K个初始聚类中心进行K-Means算法。

Spark的MLlib库中也支持K-Means++初始化方法,只需增加初始模式设置:

val initMode = "k-means||" val clusters = new KMeans(). setInitializationMode(initMode). setK(numClusters). setMaxIterations(numIterations). run(parsedData)
原文链接:https://yq.aliyun.com/articles/232595
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章