Spark -- 基于RDD实现 KNN

Spark -- 基于RDD实现 KNN

上一篇 基于DataFrame实现KNN的过程中,由于中间使用了笛卡尔积,以及大规模的排序,对于运算的性能有较大影响,经过一定的调整,笔者找到一个相对较好的实现方法

  def runKnn(trainSet: DataFrame, testSet: DataFrame, k: Int, cl: String) = {

    val testFetures: RDD[Seq[Double]] = testSet
      .drop(cl).map(row => {
      val fetuers: Seq[Double] = row.mkString(",").split(",").map(_.toDouble)
      fetuers
    }).rdd

    val trainFetures: RDD[(String, Seq[Double])] = trainSet.map(row => {
      val cla = row.getAs[String](cl)
      val fetuers: Seq[Double] = row.mkString(",")
        .split(",").filter(NumberUtils.isNumber(_)).map(_.toDouble)
      (cla, fetuers)
    }).rdd

    // 将训练集广播
    val trainBroad = spark.sparkContext.broadcast(trainFetures.collect())

    val resRDD: RDD[Row] = testFetures.map(testTp => {
      //定义一个TreeSet之前 先自定义一个排序规则
      val orderRules: Ordering[(String, Double)] = Ordering.fromLessThan[(String, Double)](_._2 <= _._2)
      //新建一个空的set 传入排序规则
      var set: mutable.TreeSet[(String, Double)] = mutable.TreeSet.empty(orderRules)

      trainBroad.value.foreach(trainTp => {
        val dist = distance.Euclidean(testTp, trainTp._2)
        set += (trainTp._1 -> dist)
        // 设定了set的大小,排序的时候更高效
        if (set.size > k) set = set.slice(0, k) else set
      })

      // 获取 投票数最多的类  (一个Wordcount)
      val cla = set.toArray.groupBy(_._1)
        .map(t => (t._1, t._2.length)).maxBy(_._2)._1

      Row.merge(Row.fromSeq(testTp), Row(cla))

    })

    spark.createDataFrame(resRDD, trainSet.schema)

  }

算法测试

val iris = spark.read
      .option("header", true)
      .option("inferSchema", true)
      .csv(inputFile)

   // 将鸢尾花分成两部分:训练集和测试集
    val Array(testSet, trainSet) = iris.randomSplit(Array(0.3, 0.7), 1234L)

     val knnMode2 = new KNNRunner(spark)
    val res2 = knnMode2.runKnn(trainSet, testSet, 10, "class")
    
    
    res2.show(truncate = false)
    val check = udf((f1: String, f2: String) => {
      if (f1.equals(f2)) 1 else 0
    })
 
    res2.join(testSet.withColumnRenamed("class", "yclass"),
      Seq("sepalLength", "sepalWidth", "petalLength", "petalWidth"))
      .withColumn("check", check($"class", $"yclass"))
       .groupBy("check").count().show()
 
+-----------+----------+-----------+----------+---------------+
|sepalLength|sepalWidth|petalLength|petalWidth|class          |
+-----------+----------+-----------+----------+---------------+
|4.6        |3.2       |1.4        |0.2       |Iris-setosa    |
|4.8        |3.0       |1.4        |0.1       |Iris-setosa    |
|4.8        |3.4       |1.6        |0.2       |Iris-setosa    |

+-----+-----+
|check|count|
+-----+-----+
|    1|   53|
|    0|    2|
+-----+-----+

从结果看,两个实现过程是一致的,但是本文使用的方法更高效。

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

推荐阅读更多精彩内容