机器学习——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