软件:IDEA2014、Maven、HanLP、JDK;
用到的知识:HanLP、Spark TF-IDF、Spark kmeans、Spark mapPartition;
用到的数据集:www.threedweb.cn/thread-1288…
工程下载:github.com/fansy1990/h… 。
- 问题描述 现在有一个中文文本数据集,这个数据集已经对其中的文本做了分类,如下:

其中每个文件夹中含有个数不等的文件,比如环境有200个,艺术有248个;同时,每个文件的内容基本上就是一些新闻报道或者中文描述,如下:

- 解决思路: 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,但是这个木有用户自定义词典,所以前期考虑先用两种),具体参考:github.com/hankcs/HanL… ;
2.3 词转换为词向量 在Kmeans算法中,一个样本需要使用数值类型,所以需要把文本转为数值向量形式,这里在Spark中有两种方式。其一,是使用TF-IDF;其二,使用Word2Vec。这里暂时使用了TF-IDF算法来进行,这个算法需要提供一个numFeatures,这个值越大其效果也越好,但是相应的计算时间也越长,后面也可以通过实验验证。 2.4 使用每个文档的词向量进行聚类建模 在进行聚类建模的时候,需要提供一个初始的聚类个数,这里面设置为10,因为我们的数据是有10个分组的。但是在实际的情况下,一般这个值是需要通过实验来验证得到的。 2.5 对聚类后的结果进行评估 这里面采用的思路是:
- 得到聚类模型后,对原始数据进行分类,得到原始文件名和预测的分类id的二元组(fileName,predictId);
- 针对(fileName,predictId),得到(fileNameFirstChar ,fileNameFirstChar.toInt - predictId)的值,这里需要注意的是fileNameFirstChar其实就是代表这个文件的原始所属类别了。
- 这里有一个一般假设,就是使用kmeans模型预测得到的结果大多数是正确的,所以fileNameFirstChar.toInt-predictId得到的众数其实就是分类的正确的个数了(这里可能比较难以理解,后面会有个小李子来说明这个问题);
- 得到每个实际类别的预测的正确率后就可以去平均预测率了。
- 改变numFeatuers的值,看下是否numFeatures设置的比较大,其正确率也会比较大?
- 具体步骤: 3.1 开发环境--Maven 首先第一步,当然是开发环境了,因为用到了Spark和HanLP,所以需要在pom.xml中加入这两个依赖:

3.3 Scala调用HanLP进行中文分词 Scala调用HanLP进行分词和Java的是一样的,同时,因为这里有些词语格式不正常,所以把这些特殊的词语添加到自定义词典中,其示例如下:


考虑到使用方便,这里把分词封装成一个函数:

输入即是一个中文的文本,输出就是分词的结果,同时去掉了一些常用的停用词。
3.4 求TF-IDF 在Spark里面求TF-IDF,可以直接调用Spark内置的算法模块即可,同时在Spark的该算法模块中还对求得的结果进行了维度变换(可以理解为特征选择或“降维”,当然这里的降维可能是提升维度)。代码如下:


3.5 建立KMeans模型 直接参考官网给定例子即可:

这里有计算cost值的,但是这个值评估不是很准确,比如我numFeature设置为2000的话,那么这个值就很大,但是其实其正确率会比较大的。 3.6 模型评估 这里的模型评估直接使用一个小李子来说明:比如,现在有这样的数据:

- 把同一类文档分到同一个partition中;







- 实验 设置不同的numFeature,比如使用200和2000,其对比结果为:

所以设置numFeatures值越大,其准确率也越高,不过计算也比较复杂。
- 总结
- HanLP的使用相对比较简单,这里只使用了分词及停用词,感谢开源;
- Spark里面的TF-IDF以及Word2Vector使用比较简单,不过使用这个需要先分词;
- 这里是在IDEA里面运行的,如果使用Spark-submit的提交方式,那么需要把hanpl的jar包加入,这个有待验证;
文章来源于fansy1990的博客