软件:IDEA2014、Maven、HanLP、JDK;
用到的知识:HanLP、Spark TF-IDF、Spark kmeans、Spark mapPartition;
用到的数据集:http://www.threedweb.cn/thread-1288-1-1.html(不需要下载,已经包含在工程里面);
工程下载:https://github.com/fansy1990/hanlp-test 。
1. 问题描述
现在有一个中文文本数据集,这个数据集已经对其中的文本做了分类,如下:
其中每个文件夹中含有个数不等的文件,比如环境有200个,艺术有248个;同时,每个文件的内容基本上就是一些新闻报道或者中文描述,如下:
现在需要做的就是,把这些文档进行聚类,看其和原始给定的类别的重合度有多少,这样也可以反过来验证我们聚类算法的正确度。
2. 解决思路:
2.1 文本预处理:
1. 由于文件的编码是GBK的,读取到Spark中全部是乱码,所以先使用Java把代码转为UTF8编码;
2. 由于文本存在多个文件中(大概2k多),使用Spark的wholeTextFile读取速度太慢,所以考虑把这些文件全部合并为一个文件,这时又结合1.的转变编码,所以在转变编码的时候就直接把所有的数据存入同一个文件中;
其存储的格式为: 每行: 文件名.txt\t文件内容
如: 41.txt
【 日 期 】199601....
这样子的话,就可以通过.txt\t 来对每行文本进行分割,得到其文件名以及文件内容,这里每行其实就是一个文件了。
2.2 分词
分词直接采用HanLP的分词来做,HanLP这里选择两种:Standard和NLP(还有一种就是HighSpeed,但是这个木有用户自定义词典,所以前期考虑先用两种),具体参考:https://github.com/hankcs/HanLP ;
2.3 词转换为词向量
在Kmeans算法中,一个样本需要使用数值类型,所以需要把文本转为数值向量形式,这里在Spark中有两种方式。其一,是使用TF-IDF;其二,使用Word2Vec。这里暂时使用了TF-IDF算法来进行,这个算法需要提供一个numFeatures,这个值越大其效果也越好,但是相应的计算时间也越长,后面也可以通过实验验证。
2.4 使用每个文档的词向量进行聚类建模
在进行聚类建模的时候,需要提供一个初始的聚类个数,这里面设置为10,因为我们的数据是有10个分组的。但是在实际的情况下,一般这个值是需要通过实验来验证得到的。
2.5 对聚类后的结果进行评估
这里面采用的思路是:
1. 得到聚类模型后,对原始数据进行分类,得到原始文件名和预测的分类id的二元组(fileName,predictId);
2. 针对(fileName,predictId),得到(fileNameFirstChar ,fileNameFirstChar.toInt - predictId)的值,这里需要注意的是fileNameFirstChar其实就是代表这个文件的原始所属类别了。
3. 这里有一个一般假设,就是使用kmeans模型预测