酒店評論情感分析系統——用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()) {
感謝如下博客:
3.使用繼續完善前人寫的文章:使用ICTCLAS JAVA版(ictclas4j)進行中文分詞
