文本聚類簡單點的來說就是将文本視作一個樣本,在其上面進行聚類操作。但是與我們機器學習中常用的聚類操作不同之處在于。
我們的聚類對象不是直接的文本本身,而是文本提取出來的特征。是以如何提取特征因而是非常重要的一步。在HanLP中一共有三個文本聚類方法。前兩種都基于詞袋模式,第一個是最常見的聚類算法:k-means,但HanLP不光實作了k-means,還實作了速度更快效果更好的repeated bisection算法(重複二分法,還是翻譯為累次平方法,好像是第一種)。筆者動筆前段時間剛剛添加了一個新的聚類分析器是,基于詞向量的kmens聚類分析器。
基于詞向量的kmeans聚類分析器,輸入的需要時詞向量化後的檔案。雖然HanLP的詞向量在Java實作中,還算可以,但在Python中使用不算太好用,同時Python也不推薦用HanLP做詞向量,我們有更好的工具。是以這裡我們也就不畫蛇添足了。
而對于前兩個聚類分析器而言,其聚類子產品可以接受任意文本作為文檔,而不需要用特殊分隔符隔開單詞。另外,該子產品還接受單詞清單作為輸入,使用者可以将英文、日文等預先切分為單詞清單後輸入本子產品。統計方法适用于所有語種,不必拘泥于中文。
分詞器的性能問題在repeated bisection算法無論性能還是速度都要優于kmens,但是在本人的測試中,前者速度基本原作者一緻約為kmeans的三倍左右,但是性能略低于後者。此處請讀者自行斟酌。
分詞器的參數自動判斷聚類個數k(此處來自于原文:HanLP中的文本聚類
很多時候使用者可能覺得聚類個數k這個超參數很難準确指定。在repeated bisection算法中,有一種變通的方法,那就是通過給準則函數的增幅設定門檻值beta來自動判斷k。此時算法的停機條件為,當一個簇的二分增幅小于beta時不再對該簇進行劃分,即認為這個簇已經達到最終狀态,不可再分;當所有簇都不可再分時,算法終止,此時産生的聚類數量就不再需要人工指定了。
在HanLP中,repeated bisection算法提供了3種接口,分别需要指定k、beta或兩者同時指定。當同時指定k和beta時,滿足兩者的停止條件中任意一個算法都會停止。當隻指定一個時,另一個停止條件不起作用。這三個接口列舉如下:
public List<Set<K>> repeatedBisection(int nclusters)
public List<Set<K>> repeatedBisection(double limit_eval)
public List<Set<K>> repeatedBisection(int nclusters, double limit_eval)
當我們使用analyzer.repeatedBisection(1.0)時,可以進行自動聚類。
from pyhanlp import *
ClusterAnalyzer = SafeJClass('com.hankcs.hanlp.mining.cluster.ClusterAnalyzer')
analyzer = ClusterAnalyzer()
# 我們需要調用并傳回自身
analyzer.addDocument("趙一", "流行, 流行, 流行, 流行, 流行, 流行, 流行, 流行, 流行, 流行, 藍調, 藍調, 藍調, 藍調, 藍調, 藍調, 搖滾, 搖滾, 搖滾, 搖滾");
analyzer.addDocument("錢二", "爵士, 爵士, 爵士, 爵士, 爵士, 爵士, 爵士, 爵士, 舞曲, 舞曲, 舞曲, 舞曲, 舞曲, 舞曲, 舞曲, 舞曲, 舞曲");
analyzer.addDocument("張三", "古典, 古典, 古典, 古典, 民謠, 民謠, 民謠, 民謠");
analyzer.addDocument("李四", "爵士, 爵士, 爵士, 爵士, 爵士, 爵士, 爵士, 爵士, 爵士, 金屬, 金屬, 舞曲, 舞曲, 舞曲, 舞曲, 舞曲, 舞曲");
analyzer.addDocument("王五", "流行, 流行, 流行, 流行, 搖滾, 搖滾, 搖滾, 嘻哈, 嘻哈, 嘻哈");
analyzer.addDocument("馬六", "古典, 古典, 古典, 古典, 古典, 古典, 古典, 古典, 搖滾");
print(analyzer.repeatedBisection(1.0))
[[李四, 錢二], [王五, 趙一], [張三, 馬六]]
評測評測程式仍然使用搜狗文本分類語料庫迷你版。過程為首先周遊子目錄讀取文檔,以子目錄+檔案名作為id将文檔傳入聚類分析器進行聚類,并且計算F1值傳回。該計算過程已被原作者封裝為接口,我們可以直接調用
CORPUS_FOLDER = "/home/fonttian/Data/CNLP/textClassification/sogou-mini/搜狗文本分類語料庫迷你版"
for i in ["kmeans", "repeated bisection"]:
print(i, ClusterAnalyzer.evaluate(CORPUS_FOLDER, i) * 100)
kmeans 83.97065954968313
repeated bisection 82.71523522720585
文章來源FontTian的部落格