热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

算法在ros中应用_SparkMLlib中KMeans聚类算法的解析和应用

聚类算法是机器学习中的一种无监督学习算法,它在数据科学领域应用场景很广泛,比如基于用户购买行为、兴趣等来构建推荐系统。核心思想可以理解为,

聚类算法是机器学习中的一种无监督学习算法,它在数据科学领域应用场景很广泛,比如基于用户购买行为、兴趣等来构建推荐系统。

核心思想可以理解为,在给定的数据集中(数据集中的每个元素有可被观察的n个属性),使用聚类算法将数据集划分为k个子集,并且要求每个子集内部的元素之间的差异度尽可能低,而不同子集元素的差异度尽可能高。简而言之,就是通过聚类算法处理给定的数据集,将具有相同或类似的属性(特征)的数据划分为一组,并且不同组之间的属性相差会比较大。

K-Means算法是聚类算法中应用比较广泛的一种聚类算法,比较容易理解且易于实现。

"标准" K-Means算法

KMeans算法的基本思想是随机给定K个初始簇中心,按照最邻近原则把待分类样本点分到各个簇。然后按平均法重新计算各个簇的质心,从而确定新的簇心。一直迭代,直到簇心的移动距离小于某个给定的值或者满足已定条件。主要分为4个步骤:

  1. 为要聚类的点寻找聚类中心,比如随机选择K个点作为初始聚类中心
  2. 计算每个点到聚类中心的距离,将每个点划分到离该点最近的聚类中去
  3. 计算每个聚类中所有点的坐标平均值,并将这个平均值作为新的聚类中心
  4. 反复执行第2步和第3步,直到聚类中心不再改变或者聚类次数达到设定迭代上限或者达到指定的容错范围

示例图:

a242d00cf965f9e6e9f9add306f59565.png

KMeans算法在做聚类分析的过程中主要有两个难题:初始聚类中心的选择和聚类个数K的选择。

Spark MLlib对KMeans的实现分析

Spark MLlib针对"标准"KMeans的问题,在实现自己的KMeans上主要做了如下核心优化:

1. 选择合适的初始中心点

Spark MLlib在初始中心点的选择上,有两种算法:

随机选择:依据给的种子seed,随机选择K个随机中心点

k-means||:默认的算法

val RANDOM = "random"
val K_MEANS_PARALLEL = "k-means||"

2. 计算样本属于哪一个中心点时对距离计算的优化

假设中心点是(a1,b1),要计算的点是(a2,b2),那么Spark MLlib采取的计算方法是(记为lowerBoundOfSqDist):

8f577879112b8ce76916785f4911c69f.png

对比欧几里得距离(记为EuclideanDist):

a1ed551f6750a3be54883d204888d1a7.png

可轻易证明lowerBoundOfSqDist小于或等于EuclideanDist,并且计算lowerBoundOfSqDist很方便,只需处理中心点和要计算的点的L2范数。那么在实际处理中就分两种情况:

  • 当lowerBoundOfSqDist大于"最近距离"(之前计算好的,记为bestdistance),那么可以推导欧式距离也大于bestdistance,不需要计算欧式距离,省去了很多计算工作
  • 当lowerBoundOfSqDist小于bestdistance,则会调用fastSquaredDistance进行距离的快速计算

关于fastSquaredDistance:

首先计算一个精度:
val precisionBound1 = 2.0 * EPSILON * sumSquaredNorm / (normDiff * normDiff + EPSILON)
if (precisionBound1 } else if (v1.isInstanceOf[SparseVector] || v2.isInstanceOf[SparseVector]) {val dotValue = dot(v1, v2)sqDist = math.max(sumSquaredNorm - 2.0 * dotValue, 0.0)val precisionBound2 = EPSILON * (sumSquaredNorm + 2.0 * math.abs(dotValue)) /(sqDist + EPSILON)if (precisionBound2 > precision) {sqDist = Vectors.sqdist(v1, v2)}
} else {sqDist = Vectors.sqdist(v1, v2)
}
//精度不满足要求时,则进行Vectors.sqdist(v1, v2)的处理,即原始的距离计算

Spark MLlib中KMeans相关源码分析

基于mllib包下的KMeans相关源码涉及的类和方法(ml包下与下面略有不同,比如涉及到的fit方法):

  1. KMeans类和伴生对象
  2. train方法:根据设置的KMeans聚类参数,构建KMeans聚类,并执行run方法进行训练
  3. run方法:主要调用runAlgorithm方法进行聚类中心点等的核心计算,返回KMeansModel
  4. initialModel:可以直接设置KMeansModel作为初始化聚类中心选择,也支持随机和k-means || 生成中心点
  5. predict:预测样本属于哪个"类"
  6. computeCost:通过计算数据集中所有的点到最近中心点的平方和来衡量聚类效果。一般同样的迭代次数,cost值越小,说明聚类效果越好。
    注意:该方法在Spark 2.4.X版本已经过时,并且会在Spark 3.0.0被移除,具体取代方法可以查看ClusteringEvaluator

主要看一下train和runAlgorithm的核心源码:

def train(// 数据样本data: RDD[Vector],// 聚类数量k: Int,// 最大迭代次数maxIterations: Int,// 初始化中心,支持"random"或者"k-means||"initializationMode: String,// 初始化时的随机种子seed: Long): KMeansModel = {new KMeans().setK(k).setMaxIterations(maxIterations).setInitializationMode(initializationMode).setSeed(seed).run(data)
}

/*** Implementation of K-Means algorithm.*/private def runAlgorithm( data: RDD[VectorWithNorm],instr: Option[Instrumentation]): KMeansModel = {val sc = data.sparkContextval initStartTime = System.nanoTime()val distanceMeasureInstance = DistanceMeasure.decodeFromString(this.distanceMeasure)val centers = initialModel match {case Some(kMeansCenters) =>kMeansCenters.clusterCenters.map(new VectorWithNorm(_))case None =>if (initializationMode == KMeans.RANDOM) {// randominitRandom(data)} else {// k-means||initKMeansParallel(data, distanceMeasureInstance)}}val initTimeInSeconds = (System.nanoTime() - initStartTime) / 1e9logInfo(f"Initialization with $initializationMode took $initTimeInSeconds%.3f seconds.")var converged = falsevar cost = 0.0var iteration = 0val iterationStartTime = System.nanoTime()instr.foreach(_.logNumFeatures(centers.head.vector.size))// Execute iterations of Lloyd's algorithm until converged// Kmeans迭代执行,计算每个样本属于哪个中心点,中心点累加的样本值以及计数。然后根据中心点的所有样本数据进行中心点的更新,并且比较更新前的数值,根据两者距离判断是否完成//迭代次数小于最大迭代次数,并行计算的中心点还没有收敛while (iteration // 当前聚类中心val thisCenters = bcCenters.value// 中心点的维度val dims = thisCenters.head.vector.sizeval sums = Array.fill(thisCenters.length)(Vectors.zeros(dims))val counts = Array.fill(thisCenters.length)(0L)points.foreach { point =>// 通过当前的聚类中心点,找出最近的聚类中心点// findClosest是为了计算bestDistance,参考上述Spark对距离计算的优化val (bestCenter, cost) = distanceMeasureInstance.findClosest(thisCenters, point)costAccum.add(cost)distanceMeasureInstance.updateClusterSum(point, sums(bestCenter))counts(bestCenter) += 1}counts.indices.filter(counts(_) > 0).map(j => (j, (sums(j), counts(j)))).iterator}.reduceByKey { case ((sum1, count1), (sum2, count2)) =>axpy(1.0, sum2, sum1)(sum1, count1 + count2)}.collectAsMap()if (iteration == 0) {instr.foreach(_.logNumExamples(collected.values.map(_._2).sum))}val newCenters = collected.mapValues { case (sum, count) =>distanceMeasureInstance.centroid(sum, count)}bcCenters.destroy(blocking = false)// Update the cluster centers and costsconverged = truenewCenters.foreach { case (j, newCenter) =>if (converged &&!distanceMeasureInstance.isCenterConverged(centers(j), newCenter, epsilon)) {// 距离大于,则说明中心点位置改变converged = false}// 更新中心点centers(j) = newCenter}cost = costAccum.valueiteration += 1}val iterationTimeInSeconds = (System.nanoTime() - iterationStartTime) / 1e9logInfo(f"Iterations took $iterationTimeInSeconds%.3f seconds.")if (iteration == maxIterations) {logInfo(s"KMeans reached the max number of iterations: $maxIterations.")} else {logInfo(s"KMeans converged in $iteration iterations.")}logInfo(s"The cost is $cost.")new KMeansModel(centers.map(_.vector), distanceMeasure, cost, iteration)}

Spark MLlib的KMeans应用示例

  1. 准备数据

诺丹姆吉本斯主教中学(Notre Dame-Bishop Gibbons School) 71 0 0 283047.0 13289.0
海景基督高中(Ocean View Christian Academy) 45 0 0 276403.0 13289.0
卡弗里学院(Calvary Baptist Academy) 58 0 0 227567.0 13289.0
...

2. 示例代码

//将加载的rdd数据,每一条变成一个向量,整个数据集变成矩阵
val parsedata &#61; rdd.map { case Row(schoolid, schoolname, locationid, school_type, zs, fee, byj) &#61;>//"特征因子":学校位置id,学校类型,住宿方式,学费,备用金val features &#61; Array[Double](locationid.toString.toDouble, school_type.toString.toDouble, zs.toString.toDouble, fee.toString.toDouble, byj.toString.toDouble)//将数组变成机器学习中的向量Vectors.dense(features)}.cache() //默认缓存到内存中&#xff0c;可以调用persist()指定缓存到哪//用kmeans对样本向量进行训练得到模型//聚类中心val numclusters &#61; List(3, 6, 9)//指定最大迭代次数val numIters &#61; List(10, 15, 20)var bestModel: Option[KMeansModel] &#61; Nonevar bestCluster &#61; 0var bestIter &#61; 0val bestRmse &#61; Double.MaxValuefor (c <- numclusters; i <- numIters) {val model &#61; KMeans.train(parsedata, c, i)//集内均方差总和(WSSSE)&#xff0c;一般可以通过增加类簇的个数 k 来减小误差&#xff0c;一般越小越好&#xff08;有可能出现过拟合&#xff09;val d &#61; model.computeCost(parsedata)println("选择K:" &#43; (c, i, d))if (d //提取到每一行的特征值val features &#61; Array[Double](locationid.toString.toDouble, school_type.toString.toDouble, zs.toString.toDouble, fee.toString.toDouble, byj.toString.toDouble)//将特征值转换成特征向量val linevector &#61; Vectors.dense(features)//将向量输入model中进行预测&#xff0c;得到预测值val prediction &#61; bestModel.get.predict(linevector)//返回每一行结果((sid,sname),所属类别)((schoolid.toString, schoolname.toString), prediction)}//中心点/*val centers: Array[linalg.Vector] &#61; model.clusterCenterscenters.foreach(println)*///按照所属"类别"分组&#xff0c;并根据"类别"排序&#xff0c;然后保存到数据库// saveData2Mysql是封装好的保存数据到mysql的方法resrdd.groupBy(_._2).sortBy(_._1).foreachPartition(saveData2Mysql(_))

上述示例只是一个简单的demo&#xff0c;实际应用中会更复杂&#xff0c;牵涉到数据的预处理&#xff0c;比如对数据进行量化、归一化&#xff0c;以及如何调参以获取最优训练模型。

推荐文章&#xff1a;

Spark实现推荐系统中的相似度算法

关于一些技术点的随笔记录&#xff08;二&#xff09;

Spark存储Parquet数据到Hive&#xff0c;对map、array、struct字段类型的处理

Kafka中sequence IO、PageCache、SendFile的应用详解

对Spark硬件配置的建议​mp.weixin.qq.com

关注微信公众号&#xff1a;大数据学习与分享&#xff0c;获取更多技术干货



推荐阅读
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 十大经典排序算法动图演示+Python实现
    本文介绍了十大经典排序算法的原理、演示和Python实现。排序算法分为内部排序和外部排序,常见的内部排序算法有插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。文章还解释了时间复杂度和稳定性的概念,并提供了相关的名词解释。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
  • 用Vue实现的Demo商品管理效果图及实现代码
    本文介绍了一个使用Vue实现的Demo商品管理的效果图及实现代码。 ... [详细]
  • Iamtryingtocreateanarrayofstructinstanceslikethis:我试图创建一个这样的struct实例数组:letinstallers: ... [详细]
  • 学习SLAM的女生,很酷
    本文介绍了学习SLAM的女生的故事,她们选择SLAM作为研究方向,面临各种学习挑战,但坚持不懈,最终获得成功。文章鼓励未来想走科研道路的女生勇敢追求自己的梦想,同时提到了一位正在英国攻读硕士学位的女生与SLAM结缘的经历。 ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • Activiti7流程定义开发笔记
    本文介绍了Activiti7流程定义的开发笔记,包括流程定义的概念、使用activiti-explorer和activiti-eclipse-designer进行建模的方式,以及生成流程图的方法。还介绍了流程定义部署的概念和步骤,包括将bpmn和png文件添加部署到activiti数据库中的方法,以及使用ZIP包进行部署的方式。同时还提到了activiti.cfg.xml文件的作用。 ... [详细]
  • 本文分析了Wince程序内存和存储内存的分布及作用。Wince内存包括系统内存、对象存储和程序内存,其中系统内存占用了一部分SDRAM,而剩下的30M为程序内存和存储内存。对象存储是嵌入式wince操作系统中的一个新概念,常用于消费电子设备中。此外,文章还介绍了主电源和后备电池在操作系统中的作用。 ... [详细]
  • 本文介绍了GTK+中的GObject对象系统,该系统是基于GLib和C语言完成的面向对象的框架,提供了灵活、可扩展且易于映射到其他语言的特性。其中最重要的是GType,它是GLib运行时类型认证和管理系统的基础,通过注册和管理基本数据类型、用户定义对象和界面类型来实现对象的继承。文章详细解释了GObject系统中对象的三个部分:唯一的ID标识、类结构和实例结构。 ... [详细]
author-avatar
mobiledu2502889415
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有