【Spark】使用spark进行K-means分析

由于思路比较简单,而且代码我写的很详细了,直接贴代码吧。Mark.

/**
 * @autor phh
 * 相似度通常以对象到类质心的距离作为相似性的评价指标
 * 算法流程如下:
 * 1、从n个数据对象中选取k个不同的点作为初始质心,每个质心看成是一个类别的标识点
 * 2、然后将数据集中的每一个点划分到距离最近的一个知心所对应的类别
 * 3、完成一次聚类后根据此次聚类的结果重新计算各个类别的新质心
 * 4、如果新的质心和之前的质心距离大于某个阈值,那么说明现在的聚类结果还没有达到最佳结果,继续直到不再变化
 */
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.calcite.rel.core.Collect
import akka.dispatch.Foreach

object Kmeans {
  def main(args:Array[String]){
    if(args.length < 0){
      System.err.println("usag error input and output");
    }
    
    val input = args(0) ;
    
    val conf = new SparkConf().setAppName("Kmeans-test").setMaster("local")
    val sc = new SparkContext(conf)
    
    
    //k指代聚类结果生成的类别个数
    val k=2
    //制定结束条件:要么距离阈值为0.1,要么最大迭代次数为5
    val e=0.1
    val maxIterations = 5
    //起始迭代是0
    var iteration =0

    //将数据从input中读取使用map生成K/V格式:
    //???
    val data = sc.textFile(input).map(x=>x.split(" ").map(_.toDouble)).cache
    println(data);
    //定义一个数组来保存质心
    var centers:Array[Array[Double]]=null
    
    //随机选取两个输入数据作为质心
    do{
      //???
      centers = data.takeSample(true, 2, System.nanoTime().toInt )
    }while(centers.map(_.deep).toSet.size != k)
      
    def euclideanDistance(xs:Array[Double],ys:Array[Double])={
      Math.sqrt((xs zip ys).map{
        case (x,y)=>Math.pow(y-x,2)
      }.sum)
    }
    
    var changed =true
    val dims =centers(0).length
    while(changed && iteration<maxIterations){
      iteration= iteration + 1 
      changed =false
    }
    
    val pointWithClass =data.map({point=>
      val closestCenterIndex =centers.zipWithIndex.map({case (center,
          index)=>{
            val distance =euclideanDistance(point, center)
            (distance,index)
            }}).reduce((d1,d2)=>if(d1._1>d2._2) d2 else d1)._2
            (closestCenterIndex,(point, 1))
          })
          val totalContribs =pointWithClass.reduceByKey({case ((xs,c1),(ys,c2))=>
            ((xs zip ys).map{case (x,y)=>x+y},c1+c2)}).collect
            
            val newCenters =totalContribs.map{
      case (centerIndex, (sum, counts))=>
        (centerIndex,sum.map(_/counts))}.sortBy(_._1).map(_._2)
        for(i<-0 until k){
          if(euclideanDistance(centers(i), newCenters(i))>e){
            changed=true;
            centers(i)=newCenters(i)
          }
        }
        
        centers.foreach(x=>println(x.mkString(",")))
  }
}

  

转载于:https://www.cnblogs.com/panghaohan/p/6957226.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值