## Spark实现Canopy聚类算法

Spark实现Canopy聚类算法

为什么需要Canopy算法

Canopy算法一般是为其他聚类算法的一种聚类方法,常用的聚类如 K-means 等聚类算法都需要事先k值(即聚类个数),并且会随机选择k个初始聚类中心。这种实现指定的k和随机初始化的聚类中心不仅会降低聚类算法的效率,而且得到的结果也可能是局部最优的。Canopy算法就可以解决以上问题。

Canopy算法的步骤

Canopy算法的核心步骤如下:

  1. 给定一组待聚类的数据集D;
  2. 给定两个阈值 T1,T2 且T1 > T2;
  3. 随机选择D中的一个数据d作为中心,并将d从D中移除;
  4. 计算D中所有点到d的距离distance;
  5. 将所有distance < T1的点归到以d为中心的canopy1类中;
  6. 将所有distance < T2的点从D中移除;
  7. 重复步骤4-6,直到D为空,形成多个Canopy类。

从Canopy算法实现的步骤来看,Canopy算法的优点明显,同时也存在一定的缺点:就是要事先指定合适的T1 和 T2

Canopy聚类过程如图所示:


Canopy聚类过程

代码实现

本案例以鸢尾花数据集为例

 // 数据加载
    val irisData = spark.read
      .option("header", true)
      .option("inferSchema", true)
      .csv(inputFile)

 ////////////////////////数据预处理//////////////////////////////
    val schema = irisData.schema
    val fts = schema.filterNot(_.name == """class""").map(_.name).toArray

    // 特征处理
    val amountVectorAssembler: VectorAssembler = new VectorAssembler()
      .setInputCols(fts)
      .setOutputCol("features")

    val ftsDF = amountVectorAssembler
      .transform(irisData)
      .select("features")


   // 计算欧式距离
    def Euclidean(p1: Seq[Double], p2: Seq[Double]) = {
      var distant = 0d
      for (i <- 0 until p1.length) {
        distant += pow(p1(i) - p2(i), 2)
      }
      sqrt(distant)
    }

   // Canopy聚类算法过程
   def ConapyRunner(df: DataFrame, t1: Double, t2: Double) = {

      var flag = true
      var cluster = 0 // ClusterId Canopy类的Id

      // 结果表的Schema信息
      val schemaOfResult: StructType = df.schema
        .add("conapyId", IntegerType) //增加一列表示类id的字段

      // 创建一个空DF 用于接收结果
      var resultDF =
        spark.createDataFrame(spark.sparkContext.emptyRDD[Row], schemaOfResult)

      var dfcopy = df

      while (flag) {

        cluster += 1

        // 随机选择一个初始点p 为了方便计算 在这里选择第一个点作为初始点
        val d = dfcopy.head.getAs[DenseVector]("features")

        //定义距离计算的自定义函数(默认为欧式距离)
        val distanceUDF = udf((vec: DenseVector) => {
          val distance = Euclidean(vec.toArray, d.toArray)
          //输出结果模式匹配
          (distance < t1, distance < t2)
        })

        val distanceDF = dfcopy
          .withColumn("distance", distanceUDF($"features"))
          .withColumn("t2threshold", $"distance".getField("_2"))
          .withColumn("t1threshold", $"distance".getField("_1"))

        // 将距离小于t1的输出 同时剔除的还有初始点d
        resultDF = resultDF.union(
          distanceDF
            .where($"t1threshold")
            .select($"features", lit(cluster) as "cluster")
        )

        // 将距离小于T2的点从数据集移除
        dfcopy = distanceDF
          .where(!$"t2threshold")
          .select($"features")

        // 判断df是否已经为空 df为空时 结束循环
        flag = !dfcopy.isEmpty

      }

      // 返回聚类结果集
      resultDF

    }

  // 聚类方法调用
   val dd = ConapyRunner(ftsDF, 4, 1.5)

    dd.show()

结果查看(已省略部分展示结果)

+-----------------+--------+
|         features|conapyId|
+-----------------+--------+
|[5.1,3.5,1.4,0.2]|       1|
|[4.9,3.0,1.4,0.2]|       1|
|[5.6,2.5,3.9,1.1]|       2|
|[5.9,3.2,4.8,1.8]|       2|
+-----------------+--------+

从算法可以得知,使用Canopy聚类时,产生的各类之间可能是有交集的,数据集的Canopy划分完成后,类似于下图:


Canopy聚类结果

参考资料:

https://www.deeplearn.me/1765.html
https://www.cnblogs.com/jamesf/p/4751565.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352

推荐阅读更多精彩内容