Kmeans是十分常见的数据挖掘算法,其逻辑较为简单,应用范围广。通过百度搜索java实现的Kmeans算法,可参考的版本很多,比如:
http://blog.csdn.net/jdplus/article/details/23960127
还有:
http://www.cnblogs.com/chaoku/p/3748456.html
虽然作者都表示亲测有效,不会有任何问题,然而在实际应用中每个人的环境不同,尤其是hadoop版本的不同,总会出现这样或者那样的问题。不过他们的算法给了很好的参考,按照他们的逻辑照虎画猫,也是可行的。
我的hadoop版本较为老旧,其中最为突出的问题就是在老版本的hadoop中并没有
org.apache.hadoop.mapreduce.Job;
这个包,这个版本上的差别照成了并不能直接拿大牛们的代码复制过来就用。随后在参考了hadoop官网中的案例重新对Kmeans算法进行了实现,代码参考“潇洒子弦”较多,也容纳我的思考,主要有耽三个大方面的不同:
实现的版本不同,基于低级版本的hadoop予以实现。
在计算距离上有了变化,采用了欧式距离,按照原来的实现方案并不能有效聚类成需要的组别数呢。
- 将中心点写入新文件中语句也有变动,按照原始的写法,似乎会覆盖掉。
以下是主要代码:
package mykmeans;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.util.LineReader;
public class CopyOfUtils {
//读取中心文件的数据
public static ArrayList<ArrayList<Double>> getCentersFromHDFS(String centersPath,boolean isDirectory) throws IOException{
ArrayList<ArrayList<Double>> result = new ArrayList<ArrayList<Double>>();
Path path = new Path(centersPath);
Configuration conf = new Configuration();
FileSystem fileSystem = path.getFileSystem(conf);
if(isDirectory){
FileStatus[] listFile = fileSystem.listStatus(path);
for (int i = 0; i < listFile.length; i++) {
result.addAll(getCentersFromHDFS(listFile[i].getPath().toString(),false));
}
return result;
}
FSDataInputStream fsis = fileSystem.open(path);
LineReader lineReader = new LineReader(fsis, conf);
Text line = new Text();
while(lineReader.readLine(line) > 0){
//ArrayList<Double> tempList = textToArray(line);
ArrayList<Double> tempList = new ArrayList<Double>();
String[] fields = line.toString().replaceAll("\t", "").split(",");
for(int i=0;i<fields.length;i++){
tempList.add(Double.parseDouble(fields[i]));
}
result.add(tempList);
}
lineReader.close();
return result;
}
//删掉文件
pub