HFUTUtils的使用
1、HFUTUtils简介
这是合肥工业大学管理学院学生创建一个工具程序集合,方便我们平时处理数据。针对文本处理的内容较多。主要是方便大家对数据进行预处理工作。具体的项目地址请见 https://github.com/df19900725/HFUTUtils 。本项目使用jdk8+,使用maven的方式管理引入的jar包。在Github下面直接下载了jar包,引入到你的项目中,然后在pom.xml中添加本项目的依赖就可以了。
2、文件操作类HFUTFileUtils
这是一个增强的文件操作,提供了集中方便读取文件的方法。Apache Commons IO已经提供了很多很好文件操作了。这里补充了一些没有但很实用的。
//从输入文件目录中读取文件,并去除输出目录中存在的文件。通常我们需要读取一些某个目录下所有的文件,但是又想去掉一些在目标目录中存在的文件,可以使用如下方法。
String source_directory = "d:/source";
String target_directory = "d:/target";
Collection<File> files = HFUTFileUtils.readFileList(source_directory, target_directory);
//读取某个文件夹下所有文件的名字到List中
String inputDirectory = "D:/test";
Collection<String> fileNames = HFUTFileUtils.readFileNameByDirectory(inputDirectory);
//获取某个文件的总行数
int lineNumber = HFUTFileUtils.getLineNumber(inputDirectory);
//将一个Map键值对写入到一个文件中
HashMap<String,Integer> map = new HashMap<String,Integer>();
map.put("test",1);
HFUTFileUtils.save2DMap(inputDirectory, map);
3、文本预处理
3.1、分词的使用
张华平分词/中科院分词/ICTCLAS/NLPIR
这四个都是同一个分词系统,是张华平先生开发的(原程序使用方式可参考:http://www.datalearner.com/blog/1051461066435555 )。
首先,我们需要从在NLPIR官网上下载分词系统(http://ictclas.nlpir.org/downloads )。解压之后找出两个文件夹,Data文件夹和lib文件夹,前者是一些数据文件,包括授权文件,后一个文件是C语言的库文件。本工具的使用非常简单,只需要初始化的时候加入这两个文件夹的地址即可。第一个参数是所在系统的lib文件夹下对应系统位置,注意:要加上NLPIR,但不需要后缀名,第二个参数是Data文件夹位置。(Linux系统下的调用完全一样,只是前者参数要加上.so的后缀)
String input_text1 = "合肥工业大学(Hefei University of Technology)简称“合工大(HFUT)”,创建于1945 年,坐落于全国四大科教城市之一,素有大湖名城、创新高地之称的江淮枢纽名城安徽省合肥市";
String input_text2 = "学校创建于1945年,1960年被中共中央批准为全国重点大学";
HashMap<String,String> input_text_map = Maps.newHashMap();
input_text_map.put("1",input_text1);
input_text_map.put("2",input_text2);
//初始化,写出两个文件夹位置,基本上只要改"d:/nlpir"就可以了
NLPIR nlpir = new NLPIR("d:/nlpir/lib/win64/NLPIR","d:/nlpir/");
//对单个字符进行分词,第二个参数:0-不带标签输出,1-带词性标签输出。
String output_text1 = nlpir.seg(input_text1, 0);
System.out.println("-------------对单个字符进行分词------------");
System.out.println(output_text1);
//对一组字符进行分词,第二个参数:0-不带标签输出,1-带词性标签输出。
NLPIR nlpir2 = new NLPIR("d:/nlpir/lib/win64/NLPIR","d:/nlpir/");
List<String> input_text_list = new ArrayList<>();
input_text_list.add(input_text1);
input_text_list.add(input_text2);
List<String> output_text2 = nlpir2.segList(input_text_list, 1);
System.out.println("-------------对一组字符进行分词------------");
for( String line : output_text2 ){
System.out.println(line);
}
//对带有key值的HashMap分词,key是id之类的,value是待分词结果
NLPIR nlpir3 = new NLPIR("d:/nlpir/lib/win64/NLPIR","d:/nlpir/");
HashMap<String,String> output_text_map = nlpir3.segMapValue(input_text_map, 1);
System.out.println("-------------对带有key值的HashMap分词------------");
for( Map.Entry<String, String> entry : output_text_map.entrySet() ){
System.out.println(entry.getKey()+"\t"+entry.getValue());
}
//自定义词典的使用,第一种方法无效,应该是张华平分词自己的bug,推荐使用第二种
NLPIR nlpir4 = new NLPIR("d:/nlpir/lib/win64/NLPIR","d:/nlpir/");
String dictPath = "F:\\dict.txt";
try {
System.out.println("-------------第一种自定义词典的使用------------");
List<String> output_text_with_dict = nlpir4.segWithUserDict(input_text_list,dictPath,1);
for( String line : output_text_with_dict ){
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
//第二种自定义词典
NLPIR nlpir5 = new NLPIR("d:/nlpir/lib/win64/NLPIR","d:/nlpir/");
List<String> list = Lists.newArrayList("合肥工业大学 n","合工大 n");
System.out.println("-------------第二种自定义词典的使用------------");
List<String> output_text_with_dict = nlpir5.segWithUserDict(input_text_list,list,1);
for( String line : output_text_with_dict ){
System.out.println(line);
}
结巴分词
结巴分词的功能相对较少,它原本是Python版本的,有人将其转换成Java版本,也非常好用,为了避免还要去下载,本程序这里就集成了一下结巴分词。在返回结果上去掉了原来java版本的词语位置信息。默认使用的是原来的SEARCH模式分词,原来的Java版本依然可用。
结巴分词:https://github.com/fxsjy/jieba 结巴分词(Java):https://github.com/huaban/jieba-analysis
Jieba jieba = new Jieba();
List<String> outList = jieba.seg(input_text_list);
for (String sentence : outList) {
System.out.println(sentence);
}
3.2、过滤分词后的文本
分词之后需要过滤一些无用词,这里我们既可以按照词性标注的结果去除某些词语,比如把量词“个”“捆”“一束”这种去掉,也可以按照停用词表的结果过滤。一般这两个都用。效果不错。比如:
String original_text = "合肥工业大学简称合工大,位于安徽省省会合肥市,创建于1945年秋,1960年10月22日被中共中央批准为全国重点大学,是教育部直属高校,“211工程”和“985工程”优势学科创新平台项目建设高校,是一所以工科为主要特色,工、理、文、经、管、法、教育多学科的综合性高等院校。";
//分词
NLPIR nlpir = new NLPIR("d:/nlpir/lib/win64/NLPIR","d:/nlpir/");
String sentence = nlpir.seg(original_text, 1); //分词后带标签
System.out.println("original text:\t" + original_text);
System.out.println("seg by NLPIR:\t" + sentence); //分词结果
System.out.println("filtered by POS:\t" + WordFiltering.filterWordsByPOS(sentence," ", "")); //按照词性标注结果过滤
System.out.println("remove POSTag:\t" + WordFiltering.removePOSTag(sentence, " ")); //去除词性标注的标签
System.out.println("filtered by stop words:\t" + WordFiltering.removeSentenceStopWords(WordFiltering.filterWordsByPOS(sentence," ", ""), " ","F:/experiment_data/stop_words_hit")); //按照词性标注结果过滤后,再去除停用词,去除停用词方法的第二个参数是空格,表示单词由空格切分
下面我们详细介绍一下这两种过滤方法。
按照词性标注的结果过滤
有些单词,根据词性我们就可以去除掉。在这里,我们主要根据NLPIR分词结果的词性标注,去除某些词语。你可以直接基于我们内置的规则过滤。内置规则过滤的标签为:/w|/x|/r|/c|/u|/y|/m|/q|/p|/vshi|/vyou分别对应过滤:标点符号|字符串(Email/微博会话分隔符/表情符号/网址)|代词|连词|助词|语气词|数词|量词|介词|动词“是”|动词“有”。你可以根据自己的情况自己写过滤规则,用竖线隔开就行了。注意NLPIR分词和其他分词标注结果的写法差异(加不加“/”,词性标注的代码含义可以看张华平分词文件夹下doc文件夹下的POS的文档)。例子如下:
String original_text = "合肥工业大学简称合工大,位于安徽省省会合肥市,创建于1945年秋,1960年10月22日被中共中央批准为全国重点大学,是教育部直属高校,“211工程”和“985工程”优势学科创新平台项目建设高校,是一所以工科为主要特色,工、理、文、经、管、法、教育多学科的综合性高等院校。";
String sentence = nlpir.seg(original_text, 1); //分词后带标签
//第三个参数是自定义的规则,如果为空,则使用我们内置的过滤规则,第二个参数是单词的分隔符,一般都是空格。这里提供一个接口大家可以改
String filtered_text = WordFiltering.filterWordsByPOS(sentence," ", "");
System.out.println(filtered_text);
//输出结果为:合肥 工业 大学 简称 合 工大 位于 安徽省 省会 合肥市 创建 1945年 秋 1960年 10月 22日 中共中央 批准 全国 重点 大学 教育部 直属 高校 工程 工程 优势 学科 创新 平台 项目 建设 高校 工科 主要 特色 工 理 文 经 管 法 教育 多 学科 综合性 高等院校
按照停用词表过滤停用词
过滤提用词是指根据停用词表过滤分词后的文本。一般可以是在按照词性过滤完之后去除停用词。你可以按照停用词文件结果去除停用词,也可以自己将停用词读成List之后再去除。例如:
String original_text = "合肥工业大学简称合工大,位于安徽省省会合肥市,创建于1945年秋,1960年10月22日被中共中央批准为全国重点大学,是教育部直属高校,“211工程”和“985工程”优势学科创新平台项目建设高校,是一所以工科为主要特色,工、理、文、经、管、法、教育多学科的综合性高等院校。";
NLPIR nlpir = new NLPIR("d:/nlpir/lib/win64/NLPIR","d:/nlpir/");
String sentence = nlpir.seg(original_text, 1); //分词后带标签
//removePOSTag是将分词后的词性标签去掉,如果是经过词性过滤的结果,不带标签就可以不用这个方法了。
System.out.println(WordFiltering.removeSentenceStopWords(WordFiltering.removePOSTag(sentence, " "), " ", "F:/experiment_data/stop_words_hit"));
//输出结果为:合肥 工业 大学 合 工大 位于 安徽省 省会 合肥市 创建 1945年 秋 1960年 10月 22日 中共中央 批准 全国 重点 大学 教育部 直属 高校 211 工程 985 工程 优势 学科 创新 平台 项目 建设 高校 工科 主要 特色 工 理 文 法 教育 学科 综合性 高等院校。
//与上面比较,我们少了“简称”这个单词,这是在停用词表里面的词。这里面没按照词性过滤。因此还有比如“位于”这样的词语存在。
4.文档语料处理
本程序提供文档模型,可以读取文件夹或者是文件模型(根据不同构造参数初始化不同的语料类型)。类为Corpus,可以自动将文档转换成Sparse Vector Space Model,也就是稀疏向量空间模型,即每一行是一个文档,将该文档包含的单词和频率用冒号连接起来,不出现的单词索引表明改文档中没有。并且所有的单词和文档都用整数型的索引表示,可以保存这个结果到一个文件夹中并可以后续直接载入。
Corpus还提供了如文档数量、单词数量、词汇数量、每个单词的计数等结果。使用loadCorpus方法可以直接载入之前导入的Corpus语料。
import org.hfutec.nlp.model.Corpus;
/**
* 读取语料
* Created by DuFei on 2017/5/26.
*/
public class CorpusTest {
public static void main(String[] args) {
String inputFile = "d:/test.txt";
//读取文件并保存语料
Corpus corpus = new Corpus(inputFile, false);
corpus.saveCorpus(inputFile);
//载入之前保存的语料
Corpus corpusLoading = new Corpus();
corpusLoading.loadCorpus(inputFile);
//输入是文件夹的测试,去掉false参数即可
String inputDir = "D:/test";
String outputDir = "d:/test_out";
Corpus corpusDir = new Corpus(inputDir);
corpusDir.saveCorpus(outputDir);
}
}
Corpus提供的属性,可以直接使用:
public int docSize = 0; //文档数量
public int wordSize = 0; //单词总数(包含重复)
public int vocabularySize = 0; //词汇数量(不重复)
public HashSet<Integer> wordSet = Sets.newHashSet(); //单词集合
public HashBiMap<String,Integer> docIndex = HashBiMap.create(); //文档索引
public HashBiMap<String,Integer> wordIndex = HashBiMap.create(); //单词索引
public HashMap<Integer,HashMap<Integer,Integer>> sparseVSMOfDocs = Maps.newHashMap(); //文档的稀疏空间表示
public HashMap<Integer,HashSet<Integer>> wordDocs = Maps.newHashMap(); //单词对应的文档编号
public HashMap<Integer,Integer> wordCount = Maps.newHashMap(); //单词计数,即每个单词对应的数量,单词用索引表示
public HashMap<Integer,HashSet<Integer>> docWords = Maps.newHashMap(); //文档中包含的单词
例子:有一个文件,一行是一个文档(分过词,分隔符为空格): 安徽省 合肥 工业 大学 HeFei University of Technology 教育部 直属 的 全国 重点 大学 国家 211工程 重点 建设 高校 合肥 工业 大学 管理 学院 始 建 于 1979年 成立 的 管理 工程 系 1998年 改名 为 管理 学院
本程序可以自动将这些单词变成索引形式,并将文档用SparseVSM表示。保存后生成三个文件:docIndex、wordIndex、sparseVSM。分别表示文档-索引、单词-索引和稀疏向量空间模型。(注意,输入语料是文档的时候,VSM一行对应之前的一行,因此docIndex为空。输入语料是文件夹时候,docIndex是文件名字-索引,VSM是按索引0-ndocs来的)。上述文件的单词索引和sparseVSM结果如下:


