阿飞飞飞

学而时习之

导航

机器学习——Kmeans算法

机器学习分为:监督学习,无监督学习,半监督学习

按算法分类:分类算法,聚类算法,对于无监督学习,应用最广的是“聚类”

Kmeans算法属于无监督学习(聚类),对于训练样本的标记信息是未知的

 

1、Kmeans算法思想

Kmeans算法又称为K均值算法,其原理为:先从样本集中随机选取K个样本作为簇中心(质心),并计算所有的样本与K个质心的距离,将所有的样本划分到与其距离最近的质心

算法实现:

  簇中心个数K的选择;

  样本点到簇中心的距离;

  更新簇中心.

 

2、Kmeans算法

对于两个n维变量a(x11,x12,x13...x1n)与b(x21,x22,x23...x2n)间的闵氏距离的定义:

其中,p为一个变参数

当p=1时,则为曼哈顿距离

当p=2时,则为欧式距离

当p->∞时,则为切比雪夫距离

注:对于Kmeans算法,一般时基于欧式距离来进行距离的度量计算

 

3、Kmeans算法过程

 

 

对于最佳的质心数量K,选取是由实际的需求或者算法实现的时候给定的,而如何得到一个最为适合的K值,方法如下:

利用jFreeChart产生图形,得到曲线

依赖:

<!-- https://mvnrepository.com/artifact/org.jfree/jfreechart -->
    <dependency>
      <groupId>org.jfree</groupId>
      <artifactId>jfreechart</artifactId>
      <version>1.0.19</version>
    </dependency>

 

对于图形化界面的设置:

class LineGraph(appName:String) extends ApplicationFrame(appName) {

  def this(appName:String,title: String,list:ListBuffer[Double]) {
    this(appName);

    val lineChart = ChartFactory.createLineChart(title,
      "质点", "距离", createDataset(list),
      PlotOrientation.VERTICAL, true, true, false)
    //设置窗口字体
    val font = new Font("黑体",Font.BOLD,20)
    lineChart.getTitle.setFont(font) //设置标题
    lineChart.getLegend.setItemFont(font) //设置标签字体
    lineChart.getCategoryPlot.getDomainAxis.setLabelFont(font)//设置x轴标签字体
    lineChart.getCategoryPlot.getRangeAxis.setLabelFont(font) //设置y轴标签字体

    val chartPanel = new ChartPanel(lineChart)
    chartPanel.setPreferredSize(new java.awt.Dimension(1200, 800))
    setContentPane(chartPanel)
  }

  def createDataset(list:ListBuffer[Double]): DefaultCategoryDataset = {
    val dataset = new DefaultCategoryDataset();
    var point=2
    for(dst<-list){
      dataset.addValue(dst,"dist",point+"")
      point+=1
    }
    dataset
  }
}

 

定义resdf为每一个用户的DataFrame("id","feature"),给定质心范围2-20:

val distLst:ListBuffer[Double]=ListBuffer[Double]()
    for(i<- 2 to 20){
      val kms = new KMeans().setFeaturesCol("feature").setK(i)
      val model = kms.fit(resdf)
      distLst.append(model.computeCost(resdf))
    }


    //调用绘图工具
    val chart = new LineGraph("app","KMeans质心和距离",distLst)
    chart.pack()
    RefineryUtilities.centerFrameOnScreen(chart)
    chart.setVisible(true)

从图形分析,找出斜率较小位置所对应的点,得到最佳质心数量K

 

posted on 2020-10-21 09:45  阿飞飞飞  阅读(1112)  评论(0编辑  收藏  举报