(3.1)用ictclas4j进行中文分词,并去除停用词

酒店评论情感分析系统——用ictclas4j进行中文分词,并去除停用词

  ictclas4j是中科院计算所开发的中文分词工具ICTCLAS的Java版本,因其分词准确率较高,而备受青睐。

  注:ictclas4j缺点:

      a.在eclipse里的java文件一定要保存为gbk编码才可以正常运行,utf-8是不能运行的

      b.ictclas4j目前不支持用户自定义字典

1.  下载ictclas4j

  后面的附件中,我有放上ictclas4j的源码包ictclas4j.zip

2.  在Eclipse中新建项目并进行相关配置

  首先把 ictclas4j解压缩,然后把 Data文件夹整个拷贝到 Eclipse项目的文件夹下, 而 bin目录下的 org文件夹整个拷贝到你Eclipse项目的 bin目录下,把src目录下的org文件夹整个拷贝到 Eclipse项目 的src目录下。

3.  导入外部包commons-lang-2.0.jar

4.  测试ictclas4j的分词效果

 

 1 import org.ictclas4j.bean.SegResult;  
 2 import org.ictclas4j.segment.SegTag;  
 3   
 4 public class TextSegmentation {  
 5   
 6     public static void main(String[] args) {  
 7         String fileContent = "中国科学院计算技术研究所在多年研究基础上," +  
 8                 "耗时一年研制出了ICTCLAS汉语词法分析系统";  
 9         SegTag segTag = new SegTag(1);// 分词路径的数目          
10         SegResult segResult = segTag.split(fileContent.trim());  
11         String classifyContent = segResult.getFinalResult();  
12         System.out.println("分词结果\n"+classifyContent);  
13     }  
14 }  

输出带有词性的标注结果:

1 分词结果    
2 中国科学院/n 计算/n 技术/n 研究所/n 在/c 多年/m 研究/n 基础/a 上/f ,/w 耗时/v 一/d 年/a 研制/v 出/q 了/u ICTCLAS/nx 汉语/n 词法/n 分析/v 系统/a 

 

5.  用ictclas4j进行中文分词,并去除停用词

1)   在Eclipse中新建一个java project(如:sentence)

2)   按照上述第1,2,3的步骤配置好ictclas4j

3)   在sentence文件目录中新建destFile目录(用于存放分词和去停用词后的结果)和srcFile目录(用于存放需要分词的文本文件和停用词表)

 

    srcFile目录下:

 

    destFile目录下:

 

4)   新建一个class(如:FileExcludeStopWord.java)

 

 1 import java.io.BufferedReader;
 2 import java.io.BufferedWriter;
 3 import java.io.File;
 4 import java.io.FileInputStream;
 5 import java.io.FileNotFoundException;
 6 import java.io.FileOutputStream;
 7 import java.io.InputStreamReader;
 8 import java.io.OutputStreamWriter;
 9 import java.util.*;
10 
11 import org.ictclas4j.bean.SegResult;  
12 import org.ictclas4j.segment.SegTag;
13 //import ICTCLAS.I3S.AC.ICTCLAS50;
14 
15 public class FileExcludeStopWord {
16     //停用词词表
17     public static final String stopWordTable = "." + File.separator + "srcFile" + File.separator + "StopWordTable.txt";
18 
19     public static void main(String[] args) {
20 
21         //源文件和目的文件
22         String srcFile = "." + File.separator + "srcFile" + File.separator + "酒店评论.txt";
23         String destFile = "." + File.separator + "destFile" + File.separator + "酒店评论.txt";
24         new FileExcludeStopWord().fileExcludeStopWord(srcFile, destFile);
25     }
26     
27     public void fileExcludeStopWord(String srcFile,String destFile){
28         try {
29             //读取原文件和停用词表
30             BufferedReader srcFileBr = new BufferedReader(new InputStreamReader(new FileInputStream(new File(srcFile))));
31             BufferedReader StopWordFileBr = new BufferedReader(new InputStreamReader(new FileInputStream(new File(stopWordTable))));
32             
33             //将去除停用词的文本信息存入输出文件
34             BufferedWriter destFileBw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(destFile))));
35             
36             //用来存放停用词的集合
37             Set<String> stopWordSet = new HashSet<String>();
38             
39             //初始化停用词集
40             String stopWord = null;
41             for(; (stopWord = StopWordFileBr.readLine()) != null;){
42                 stopWordSet.add(stopWord);        
43             }            
44             
45             String paragraph = null;
46             for(; (paragraph = srcFileBr.readLine()) != null;){
47                 //对读入的文本进行分词
48                 SegTag segTag = new SegTag(1);// 分词路径的数目          
49                 SegResult segResult = segTag.split(paragraph);
50                 String spiltResultStr = segResult.getFinalResult();    
51                 //得到分词后的词汇数组,以便后续比较
52                 String[] resultArray = spiltResultStr.split(" ");
53                                 
54                 //过滤停用词            
55                 for(int i = 0; i< resultArray.length; i++){
56                     //System.out.println(resultArray[i]);
57                     if(stopWordSet.contains(resultArray[i])){
58                         resultArray[i] = null;
59                     }
60                     //System.out.println(resultArray[i]);    
61                 }
62                 
63                 //把过滤后的字符串数组存入到一个字符串中
64                 StringBuffer finalStr = new StringBuffer();
65                 for(int i = 0; i< resultArray.length; i++){
66                     if(resultArray[i] != null){
67                         finalStr = finalStr.append(resultArray[i]).append(" ");
68                     }
69                 }
70                 
71                 //将过滤后的文本信息写入到指定文件中
72                 destFileBw.write(finalStr.toString());
73                 destFileBw.newLine();
74                 //输出最后的去停用词之后的结果
75                 System.out.println(finalStr);
76             }
77             
78             //关闭输入流
79             destFileBw.close();
80             StopWordFileBr.close();
81             srcFileBr.close();            
82             
83         } catch (FileNotFoundException e) {
84             // TODO Auto-generated catch block
85             e.printStackTrace();
86         } catch(Exception e){
87             e.printStackTrace();
88         }
89     }
90 }

酒店评论.txt中的内容:

总体评价:性价比很高,交通便利,周边吃喝玩乐设施齐全,对面就是家乐福。但是前台男客服服务态度很一般,酒店光线太暗看不清,总感觉脏脏的,并且隔音效果一般,有一点点吵,导致晚上睡觉不踏实。对于价钱,三星级价格有点高,一次性用品要收费。

上述代码输出结果:

总体 评价 性 价 高 交通 便利 周边 吃喝玩乐 设施 齐全 对面 家乐福 前台 男客 服 服务 态度 酒店 光线 太 暗 清 总 感觉 脏脏 隔音 效果 一点点 吵 导致 晚上 睡觉 踏实 价钱 三星级 价格 点 高 一次性 用品 收费

注:

  ictclas4j的分词结果中本来是带有词性标注的,但是停用词表中是没有词性标注,故要从分词结果中除去停用词,则原本的分词词性结果不应该出现,所以为了让分词的结果中不进行词性的标注,进行了如下更改:

打开.../src/org/ictclas4j/segment中的SegTag.java文件,修改outputResult()函数,将:

result += sn.getSrcWord() + "/" + temp + " ";

改为:

result += sn.getSrcWord() + "  "; 

 

【补充】

6.  ictclas4j分词过程中可能遇到的问题和解决方案

①   分词的结果中不需要进行词性的标注
打开.../src/org/ictclas4j/segment中的SegTag.java文件,修改outputResult()函数,将:

result += sn.getSrcWord() + "/" + temp + " ";

改为:

result += sn.getSrcWord() + "  "; 

②   “org.apache”

  这个新建的测试类可能会提示错误:"The import org.apache cannot be resolved",这是由于系统需要一个Apache的commons的jar包(如:commons-lang-2.0.jar)。

③ 在读取外部文件的内容进行分词时出现错误,如下所示:
 Exception in thread "main" java.lang.NullPointerException at org.ictclas4j.bean.Dictionary.getMaxMatch
 打开../src/org/ictclas4j/bean中的Dictionary.java文件,修改getMaxMatch()函数,在:

for (int j = 0; j < wis.size(); j++) {

之前加上如下语句,判断为空条件:

if (wis == null) { return null; }

④ 读取外部文件时由于编码问题引起的错误

  注意文件的读取方式,在打开文件的同时注意指定文件的编码:

InputStreamReader read = new InputStreamReader (new FileInputStream(f),"UTF-8");  

  举例如下:

 1 import java.io.BufferedReader;
 2 import java.io.File;
 3 import java.io.FileInputStream;
 4 import java.io.FileReader;
 5 import java.io.InputStreamReader;
 6 
 7 import org.ictclas4j.bean.SegResult;
 8 import org.ictclas4j.segment.SegTag;
 9 
10 public class Test {
11     public static void main(String[] args) throws Exception{
12         SegTag st = new SegTag(1);
13         String str = "";
14         int n = 0;
15         File f = new File("E:/corpus/traindatas/train_uy2ch.ch.txt");
16         InputStreamReader read = new InputStreamReader (new FileInputStream(f),"UTF-8");
17         BufferedReader reader=new BufferedReader(read);
18         String line;
19         while ((line = reader.readLine()) != null&&n<20) {
20             SegResult sr = st.split(line);
21             System.out.println(sr.getFinalResult());
22             n ++;
23             }
24         }
25     }

⑤ 在对大文件进行中文分词时,出现了以下的错误信息:

java.lang.ArrayIndexOutOfBoundsException: -39
       at java.util.ArrayList.get(ArrayList.java:324)
       at org.ictclas4j.bean.Dictionary.findInOriginalTable(Dictionary.java:
422)
       at org.ictclas4j.bean.Dictionary.getFreq(Dictionary.java:632)
       at org.ictclas4j.segment.GraphGenerate.biGenerate(GraphGenerate.java:
170)
       at org.ictclas4j.segment.Segment.split(Segment.java:81)
       at com.ictclas4j.test.MyTest.main(MyTest.java:19)

可能的出错原因:

分词过程中出现了未能识别的字,如繁体字等

改错方法:在Dictionary.java文件中找到findInOriginalTable()方法,将其中的:

if (res != null && wts != null) { 

改为:

if (res != null && wts != null &&index>=0 &&index<wts.size()) {

 

感谢如下博客:

1.使用ictclas4j进行中文分词

2.使用ictclas4j进行中文分词(续)

3.使用继续完善前人写的文章:使用ICTCLAS JAVA版(ictclas4j)进行中文分词

4.Java过滤停用词源码

 

附件:ictclas4j+commons-lang-2.4.jar+stopword

posted @ 2014-10-03 21:10  CherishFu  阅读(3791)  评论(15编辑  收藏  举报