pyhanlp文字分類與情感分析

adnb34g發表於2019-02-20


語料庫

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

Map 描述

這種關係可以用 Java Map<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;

例如:


 

每個分類裡面都是一些文字文件。任何滿足此格式的語料庫都可以直接載入。

 

資料集實現

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


 

訓練

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

 

分詞

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


但文字分類是否一定需要分詞?答案是否定的。 我們可以順序選取文中相鄰的兩個字,作為一個 “詞”(術語叫 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 萬。

 

調參

 

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

 

訓練

 

本系統實現的訓練演算法是樸素貝葉斯法,無需使用者關心內部細節。另有一個子專案實現了支援向量機文字分類器,可供參考。由於依賴了第三方庫,所以沒有整合在本專案中。相關效能指標如下表所示:

 


模型

 

訓練之後,我們就得到了一個模型,可以透過 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 ,含有完整的引數,請自行執行評估。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31524777/viewspace-2636455/,如需轉載,請註明出處,否則將追究法律責任。

相關文章