转载请注明:http://blog.youkuaiyun.com/HEL_WOR/article/details/50583923
一直想找个方法把分类的数据直观的展示出来,最近在Java上发现了类似Pyhton的MatPlotLib库的jar包,上周末在屋里把代码折腾出来了。
Kmeans算属于非监督的聚类算法。
监督学习的定义是通过对算法进行有正面影响和负面影响的训练,算法能够学习出一种模型,这个时候我们将测试数据输入这个模型后,模型能得出我们想要的结果,例如分类。举个例子,我们怎样训练自己家的狗狗要听话,我们通过狗狗做对的事情奖励它,做错了事情教育它,那么足够多的时间后我们就会觉得狗狗越来越听话了。这就属于监督学习。
非监督学习是我们无法确切的去训练算法认识到什么是positive的,什么是negative的,具体的学习过程只能由算法自己去描述。
Kmeans属于非监督学习,与SVM,Logistic,决策树等监督学习算法不同,我们不能如果训练SVM那样给出一系列的正反数据点去训练算法成为一种能分辨正负类点的模型。Kmeans需要自己去学习如果分类。所以分类的本身就只能来源于算法的自身描述。
Kmeans算法能实现分类核心是因为其距离函数:
这个算法是一个坐标上升的优化算法,有兴趣的话可以自己推导,公式会不停交替地对u和c做求导操作,当导数趋于0时结果趋于不变,最终算法收敛。
根据这个距离公式,我们可以根据距离来描述类别。设定k个中心点,根据所有数据点与k个中心点的距离,把与中心点距离最近的点划分为一类。这是对公式中u的优化,同时对每一个类型重新计算中心点,这是对公式中c的优化,到最后,算法收敛,分类完成。
由此,对算法的描述为:
算法在实现后,要注意:
1.类别的个数会对分类结果有很大影响。
2.初始中心点的选择不当会造成数据点分类错误。
关于初始中心点,在SVM看到过有自启发式的方式。不知道能不能用到Kmeans上。
测试数据集: testData
测试结果(JFreeChart实现图像展示):
Kmeans类(算法主逻辑):
package helWor.Share.KMeans;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
public class KMeans {
private static int ClusterNum;
private static ArrayList<ArrayList<double[]>> cluster;
private static double[][] center = new double[ClusterNum][2];
private static double[][] lastCenter = new double[ClusterNum][2];
private ArrayList<double[]> dataSet = new ArrayList<double[]>();
/*
* 构造函数
*/
public KMeans(int clusterNum)
{
ClusterNum = clusterNum;
}
/*
* 主执行方法
*/
public void ExecuteMethod() throws IOException
{
LoadDataSet();
initCenters();
do
{
initCluster();
AllocateCluster();
lastCenter = center;
setNewCenter();
}
while(this.IsCenterChanged(center));
}
/*
* 获取簇
*/
public ArrayList<ArrayList<double[]>> getCluster()
{
return cluster;
}
/*
* 装载数据
*/