pyhanlp文本分類與情感分析


語料庫

本文語料庫特指文本分類語料庫,對應IDataSet接口。而文本分類語料庫包含兩個概念:文檔和類目。一個文檔只屬於一個類目,一個類目可能含有多個文檔。比如搜狗文本分類語料庫迷你版.zip,下載前請先閱讀搜狗實驗室數據使用許可協議。

Map描述

這種關係可以用JavaMap<String, String[]>來描述,其key代表類目,value代表該類目下的所有文檔。用戶可以利用自己的文本讀取模塊構造一個Map<String, String[]>形式的中間語料庫,然後利用IDataSet#add(java.util.Map<java.lang.String,java.lang.String[]>)接口將其加入到訓練語料庫中。

用文件夾描述

 

這種樹形結構也很適合用文件夾描述,即:

 

/**

 * 加載數據集

 *

 * @param folderPath  分類語料的根目錄.目錄必須滿足如下結構:<br>

 *                    根目錄<br>

 *                    ├── 分類A<br>

 *                    │   └── 1.txt<br>

 *                    │   └── 2.txt<br>

 *                    │   └── 3.txt<br>

 *                    ├── 分類B<br>

 *                    │   └── 1.txt<br>

 *                    │   └── ...<br>

 *                    └── ...<br>

 *                    文件不一定需要用數字命名,也不需要以txt作爲後綴名,但一定需要是文本文件.

 * @param charsetName 文件編碼

 * @return

 * @throws IllegalArgumentException

 * @throws IOException

 */

IDataSet load(String folderPath, String charsetName) throws IllegalArgumentException, IOException;

例如:

 

圖1.jpg

 

每個分類裏面都是一些文本文檔。任何滿足此格式的語料庫都可以直接加載。

 

數據集實現

考慮到大規模訓練的時候,文本數量達到千萬級,無法全部加載到內存中,所以本系統實現了基於文件系統的FileDataSet。同時,在服務器資源許可的情況下,可以使用基於內存的MemoryDataSet,提高加載速度。兩者的繼承關係如下:

 

圖2.jpg

 

訓練

訓練指的是,利用給定訓練集尋找一個能描述這種語言現象的模型的過程。開發者只需調用train接口即可,但在實現中,有許多細節。

 

分詞

目前,本系統中的分詞器接口一共有兩種實現:

 

圖3.jpg

但文本分類是否一定需要分詞?答案是否定的。 我們可以順序選取文中相鄰的兩個字,作爲一個“詞”(術語叫bigram)。這兩個字在數量很多的時候可以反映文章的主題(參考清華大學2016年的一篇論文《Zhipeng Guo, Yu Zhao, Yabin Zheng, Xiance Si, Zhiyuan Liu, Maosong Sun. THUCTC: An Efficient Chinese Text Classifier. 2016》)。這在代碼中對應BigramTokenizer. 當然,也可以採用傳統的分詞器,如HanLPTokenizer 另外,用戶也可以通過實現ITokenizer來實現自己的分詞器,並通過IDataSet#setTokenizer來使其生效。

 

特徵提取

特徵提取指的是從所有詞中,選取最有助於分類決策的詞語。理想狀態下所有詞語都有助於分類決策,但現實情況是,如果將所有詞語都納入計算,則訓練速度將非常慢,內存開銷非常大且最終模型的體積非常大。

 

本系統採取的是卡方檢測,通過卡方檢測去掉卡方值低於一個閾值的特徵,並且限定最終特徵數不超過100萬。

 

調參

 

對於貝葉斯模型,沒有超參數需要調節。

 

訓練

 

本系統實現的訓練算法是樸素貝葉斯法,無需用戶關心內部細節。另有一個子項目實現了支持向量機文本分類器,可供參考。由於依賴了第三方庫,所以沒有集成在本項目中。相關性能指標如下表所示:

圖4.JPG 


模型

 

訓練之後,我們就得到了一個模型,可以通過IClassifier#getModel獲取到模型的引用。該接口返回一個AbstractModel對象,該對象實現了Serializable接口,可以序列化到任何地方以供部署。 反序列化後的模型可以通過如下方式加載並構造分類器:

 

NaiveBayesModel model = (NaiveBayesModel) IOUtil.readObjectFrom(MODEL_PATH);

NaiveBayesClassifier naiveBayesClassifier = new NaiveBayesClassifier(model);

分類

 

通過加載模型,我們可以得到一個分類器,利用該分類器,我們就可以進行文本分類了。

 

IClassifier classifier = new NaiveBayesClassifier(model);

目前分類器接口中與文本分類有關的接口有如下三種:

 

/**

 * 預測分類

 *

 * @param text 文本

 * @return 所有分類對應的分值(或概率, 需要enableProbability)

 * @throws IllegalArgumentException 參數錯誤

 * @throws IllegalStateException    未訓練模型

 */

Map<String, Double> predict(String text) throws IllegalArgumentException, IllegalStateException;

 

/**

 * 預測分類

 * @param document

 * @return

 */

Map<String, Double> predict(Document document) throws IllegalArgumentException, IllegalStateException;

 

/**

 * 預測分類

 * @param document

 * @return

 * @throws IllegalArgumentException

 * @throws IllegalStateException

 */

double[] categorize(Document document) throws IllegalArgumentException, IllegalStateException;

 

/**

 * 預測最可能的分類

 * @param document

 * @return

 * @throws IllegalArgumentException

 * @throws IllegalStateException

 */

int label(Document document) throws IllegalArgumentException, IllegalStateException;

 

/**

 * 預測最可能的分類

 * @param text 文本

 * @return 最可能的分類

 * @throws IllegalArgumentException

 * @throws IllegalStateException

 */

String classify(String text) throws IllegalArgumentException, IllegalStateException;

 

/**

 * 預測最可能的分類

 * @param document 一個結構化的文檔(注意!這是一個底層數據結構,請謹慎操作)

 * @return 最可能的分類

 * @throws IllegalArgumentException

 * @throws IllegalStateException

 */

String classify(Document document) throws IllegalArgumentException, IllegalStateException;

classify方法直接返回最可能的類別的String形式,而predict方法返回所有類別的得分(是一個Map形式,鍵是類目,值是分數或概率),categorize方法返回所有類目的得分(是一個double數組,分類得分按照分類名稱的字典序排列),label方法返回最可能類目的字典序。

 

線程安全性

 

類似於HanLP的設計,以效率至上,本系統內部實現沒有使用任何線程鎖,但任何預測接口都是線程安全的(被設計爲不儲存中間結果,將所有中間結果放入參數棧中)。

 

情感分析

 

可以利用文本分類在情感極性語料上訓練的模型做淺層情感分析。目前公開的情感分析語料庫有:中文情感挖掘語料-ChnSentiCorp,語料發佈者爲譚鬆波。

 

接口與文本分類完全一致,請參考com.hankcs.demo.DemoSentimentAnalysis

 

性能指標

 

一般來講,受到語料庫質量的約束(部分語料庫的分類標註模糊或有重疊),我們評測一個分類器時,必須嚴謹地註明在哪個語料庫以何種比例分割數據集下得到這樣的測試結果。

 

版本庫中有一個在搜狗語料庫上的測試com.hankcs.demo.DemoTextClassificationFMeasure,含有完整的參數,請自行運行評估。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章