Project2实验报告 - GongRuqin/bigdata GitHub Wiki

151220032 龚茹沁

程序设计说明

step1:数据集和训练集预处理:文本向量化

TrainingData: 将每个情感偏好的文件夹里面的新闻进行分词,计算每个单词tf-idf值,并且降序输出。在排名前30的词中选取15个单词作为此文本属性的特征词。
共45个词语与其tf-idf值构成特征向量。
对训练集所有文件进行文本向量化:求出所有特征词在每个文件中的出现次数作为tf值,再与其idf相乘,得到新的tf-idf值,构成每个文本属性向量。

step2:进行模型训练:分别用到了knn算法和朴素贝叶斯算法。

knn算法思想:对于每个测试集的文本向量,求出k个离此向量最近的训练集向量。并判断此k个向量从属哪个分类,多数所属的类别即作为测试集文本所属类别。
朴素贝叶斯算法:对于未分类的测试文本,针对其包含的每个具体属性值,与其相似的训练样本频度求积,再乘以类别频度。得到每个测试文本在各个分类下的频度,最大频度的分类作为测试样本的分类。

具体代码:

选取特征词:TFDIF1

代码说明:

分为三个mapreduce过程。
第一个map过程public static class Mapper_Part1 进行分词和词频写入,并且统计出现的所有单词数目。
第一个reduce过程public static class Combiner_Part1进行词频统计,并算出每个单词的tf值(=某单词在某文本出现的次数/所有单词量) 还执行了一次自己的partition过程,利用hash函数,将不同文件的输出结果放在不同的结果文件中,方便查看。此路径为输入的临时路径,之后执行过程会有说明。
第二个map过程public static class Mapper_Part2统计单词在所有文章出现的次数。
第二个reduce过程public static class Reduce_Part2算出单词idf值:某单词在所有文本中出现次数/所有文本。并将tf与idf相乘,得到每个单词的tf-idf值。
第三个mapreduce过程则为将所有单词与其tf-idf值降序输出。用到了之前写过的排序函数public static class DescComparator extends WritableComparator,大致思路与project1.wordcount类似。

文本向量化:TFIDF

代码说明:

进行了两次mapreduce过程,大致思路与之前选特征值求tf-idf的思路相同。只是在第一次map做分词写入的时候,只写入了特征词的词频。
第一次mapreduce过程统计特征词在特定文本中出现的次数。
第二次mapreduce过程则为求单词的idf值。并将其与tf值相乘。得到特征词在每个文本中的tf-idf值作为文本向量。由于之前每个情感下挑选了15个特征词,共45个特征词。文本向量化的结果为45维向量+所属类别。另测试集的outout key中还包含每个文本的名字,便于查看分类结果。
类别设置:positive:1,negative:2,neutral:3 未知:-1(此为训练集ouput类别结果)

knn算法:KNN

代码说明:

map过程public static class MyMapper extends Mapper读取训练集和测试集数据,根据每个文本的向量化结果,算出离每个测试文本最近的k个训练文本。
reduce过程public static class MyReducer extends Reducer根据记下的k个训练文本分类,找到出现次数最多的类名,将此类名作为value,测试集文本名作为key输出。

朴素贝叶斯算法:Bayes

代码说明:

进行了两次mapreduce。分别进行训练集预处理和分类预测。
第一次mapreduce统计每个类别出现的次数,和每个类别下每个单词,属性值,属性名一致的频度。
第二次进行一次map操作public static class TestMapper extends Mapper<Object, Text, Text, Text>计算测试集向量和训练集向量相似程度。如果每个类别下,单词和属性名相同,属性值相差较小(设置为0.00001),则将其出现的频度相乘。最后与类别出现频度相乘,算出最大值,则此类别为与测试集文本最相似的类别。

程序执行说明及执行结果:

测试集为实验一的download_data部分文件。共有350个txt文件。
训练集为此次给出的TrainingData所有文件。

程序运行jar包:

选取特征词
文本向量化
Knn算法
朴素贝叶斯

选取特征词执行命令:
project2.1.jar TFIDF [in] [tmp] [out] -skip [patterns]
其中in为原始数据集,tmp为存放第一次mapreduce即每个文本单词tf值的临时目录,每个文本一个输出文件。out为最终所有单词tf-idf值输出,放在一个文件中,降序排列。
特征词:

文本向量化执行命令:
projrct2.2.jar TFIDF [in] [tmp] [out]
执行结果:
TrainingData:positive
negative
neutral
TestData:test

KNN执行命令:
knn1.jar KNN0 [in] [out]
训练集的hdfs目录提前在代码中给出,直接读取。
执行结果: (因为文件较大,加上hdfs无法全部加载到本地,放出部分输出)

朴素贝叶斯执行命令:
bigdata5.jar bayes [train] [tmp] [test] [out]
其中train为训练集输入目录。tmp为训练集预处理结果输出的临时目录,记下并在第二次mapreduce的时候读取。test为测试集数据,out为最终分类的输出目录。
执行结果:

实验结果分析

用两种方法进行的情感分析结果显示,大多数文本是属于中性的。这跟一开始选词的时候我的操作也有关系。考虑到采用ik分词器,可能会有一些没用的词语,我是自己选词的。在tf-idf值高的词中选出一些代表词。相对而言,中性词中较多“股,股票,市场,投资”等内容。而positive和negative中出现次数最多的其实也是这些,但我选择了一些更为代表性的词,类似于“涨停,制胜,下降,违规”等词语。可能对最后的分类结果会有一定的影响。
另外朴素贝叶斯的代码完全是自己实现的,我在考虑代码实现的时候,对于相似度的判断其实比较粗糙。另外,由于int溢出的问题,我在计算乘数的时候也进行了一定的精读调整,可能对最后结果也有一定影响。