美文网首页
Spark实现 -- Kmeans聚类算法

Spark实现 -- Kmeans聚类算法

作者: k_wzzc | 来源:发表于2018-11-28 23:34 被阅读0次

Spark实现 -- Kmeans聚类算法

Kmeans简介

Kmeans是最常用的聚类算法,也是十大经典的数据挖掘算法之一。聚类的思想用一句话概括就是“物以类聚,人以群分”。kmeans算法作为最基础的算法之一,基本上每本数据挖掘的书都会讲到,这里就不在啰嗦了。本文主要结合实现原理利用Spark实现一下过程。

算法实现步骤

step1 首先随机选取k个样本点最为初始聚类中心
step2 计算每个样本到聚类中心的距离,将该样本归属到最近的聚类中心
step3 将每个类的点的均值作为新的聚类中心
step4 重复2、3步骤直到代价函数不再发生较大大变化或达到迭代次数

Kmeans动态过程

Kmeans动态过程 --图片来源维基百科
图片来源:维基百科

代码实现

// 定义一个方法 传入的参数是 数据集、K、最大迭代次数、代价函数变化阈值
// 其中 最大迭代次数和代价函数变化阈值是设定了默认值,可以根据需要做相应更改
  def train(data: RDD[Seq[Double]], k: Int, maxIter: Int = 40, tol: Double = 1e-4) = {

    val sc: SparkContext = data.sparkContext

    var i = 0 // 迭代次数
    var cost = 0D //初始的代价函数
    var convergence = false   //判断收敛,即代价函数变化小于阈值tol
    
    // step1 :随机选取 k个初始聚类中心
    var initk: Array[(Seq[Double], Int)] = data.takeSample(false, k, Random.nextLong()).zip(Range(0, k))

    var res: RDD[(Seq[Double], Int)] = null

    while (i < maxIter && !convergence) {

      val bcCenters = sc.broadcast(initk)

      val centers: Array[(Seq[Double], Int)] = bcCenters.value

      val clustered: RDD[(Int, (Double, Seq[Double], Int))] = data.mapPartitions(points => {

        val listBuffer = new ListBuffer[(Int, (Double, Seq[Double], Int))]()

    // 计算每个样本点到各个聚类中心的距离
        points.foreach { point =>

          // 计算聚类id以及最小距离平方和、样本点、1
          val cost: (Int, (Double, Seq[Double], Int)) = centers.map(ct => {

            ct._2 -> (math.pow(distance.Euclidean(ct._1, point), 2), point, 1)

          }).minBy(_._2._1)  // 将该样本归属到最近的聚类中心
          listBuffer.append(cost)
        }

        listBuffer.toIterator

      })
      //
      val mpartition: Array[(Int, (Double, Seq[Double]))] = clustered
        .reduceByKey((a, b) => {
          val cost = a._1 + b._1   //代价函数
          val count = a._3 + b._3   // 每个类的样本数累加
          val newCenters = a._2.zip(b._2).map(tp => tp._1 + tp._2)    // 新的聚类中心点集
          (cost, newCenters, count)
        })
        .map {
          case (clusterId, (costs, point, count)) =>
            clusterId -> (costs, point.map(_ / count))   // 新的聚类中心 
        }
        .collect()

      val newCost = mpartition.map(_._2._1).sum   // 代价函数

      convergence =  math.abs(newCost - cost) <= tol    // 判断收敛,即代价函数变化是否小于小于阈值tol

    // 变换新的代价函数
      cost = newCost
      
      // 变换初始聚类中心
      initk = mpartition.map(tp => (tp._2._2, tp._1))

    // 聚类结果 返回样本点以及所属类的id
      res = clustered.map(tp=>(tp._2._2,tp._1))

      i += 1
    }

    // 返回聚类结果
    res

  }

算法调用 :为了方便,本案例使用的数据集还是鸢尾花数据集

 val dataset = spark.read.textFile("F:\\DataSource\\iris.csv")
      .rdd.map(_.split(",").filter(NumberUtils.isNumber _).map(_.toDouble))
      .filter(!_.isEmpty).map(_.toSeq)

    val kmeans = new Kmeans2()

    val res: RDD[(Seq[Double], Int)] = kmeans.train(dataset, 3)
    
    res.sample(false, 0.1, 1234L)
      .map(tp => (tp._1.mkString(","), tp._2))
      .foreach(println)

聚类结果

(4.8,3.0,1.4,0.3,0)
(4.6,3.2,1.4,0.2,0)
(6.0,3.4,4.5,1.6,2)
(5.6,2.7,4.2,1.3,2)
(7.1,3.0,5.9,2.1,1)
(7.2,3.2,6.0,1.8,1)
······

根据笔者的检验来看,聚类出来的结果和源数据的分类还是有些许差别。所以通过本案例说明:每个方法都有它自身的使用场景,每个数据集都有自身的属性因此每个都有不同的解决方法,没有最好,只有更好。工具固然可以帮我们解决问题,但是掌握工具能帮我们有效的解决问题。

不足之处

因为初始聚类中心是随机选择,因此可能会让结果陷入局部最优,有学者就此问题提出了很多优化方法,例如kmeans++、Kernel K-means等方法。有兴趣的朋友们可以看看 。

如有不当之处,欢迎指正

相关文章

  • Spark实现 -- Kmeans聚类算法

    Spark实现 -- Kmeans聚类算法 Kmeans简介 Kmeans是最常用的聚类算法,也是十大经典的数据挖...

  • Pyspark实现KMeans机器学习聚类算法(一)

    Pyspark实现KMeans机器学习聚类算法(一) 环境配置:spark 2.1.1python 3.5.2IP...

  • kmeans算法

    kmeans算法 简介kmeans算法 kmeans算法又称k平均或k均值算法,一种已知聚类类别数的聚类算法。 它...

  • 简单KMEANS聚类实现

    简单KMEANS聚类实现 使用Kmeans进行聚类,分别聚成234类

  • Clustering

    本文结构安排 经典聚类算法:线性聚类 Kmeans 经典聚类算法:非线性聚类 DBSCAN、谱聚类 新兴聚类算法:...

  • Kmeans聚类算法简介(有点枯燥)

    1. Kmeans聚类算法简介 由于具有出色的速度和良好的可扩展性,Kmeans聚类算法算得上是最著名的聚类方法。...

  • Kmeans聚类算法简介

    1. Kmeans聚类算法简介 由于具有出色的速度和良好的可扩展性,Kmeans聚类算法算得上是最著名的聚类方法。...

  • ## Spark实现Canopy聚类算法

    Spark实现Canopy聚类算法 为什么需要Canopy算法 Canopy算法一般是为其他聚类算法的一种聚类方法...

  • 简单聚类算法

    一些聚类算法 Birch层次聚类 ,KMeans原形算法 ,AGNES层次算法, DBSCAN密度算法, LVQ原...

  • K均值聚类及代码实现

    KMeans聚类 在聚类算法中,最出名的应该就是k均值聚类(KMeans)了,几乎所有的数据挖掘/机器学习书籍都会...

网友评论

      本文标题:Spark实现 -- Kmeans聚类算法

      本文链接:https://www.haomeiwen.com/subject/hqitcqtx.html