pyhanlp 文本分類與情感分析

這一次我們需要利用HanLP進(jìn)行文本分類與情感分析。同時(shí)這也是pyhanlp用戶指南的倒數(shù)第二篇關(guān)于接口和Python實(shí)現(xiàn)的文章了,再之后就是導(dǎo)論沥潭,使用技巧匯總和幾個(gè)實(shí)例落编丘。真是可喜可賀啊谅畅。

文本分類

在HanLP中,文本分類與情感分析都是使用一個(gè)分類器亥曹,樸素貝葉斯分類器邓了。或許這個(gè)分類器還算是比較一般媳瞪,不過從最終結(jié)果來看效果還是很可以的骗炉。

因?yàn)榈讓硬捎迷~袋模式,所以當(dāng)文本較大時(shí)可能會(huì)是內(nèi)存開效果大蛇受,不過沒關(guān)系句葵,作者預(yù)先寫了一個(gè)特征檢測的方法。使用卡方檢測,利用閾值來過濾特征乍丈,減少內(nèi)存的開銷剂碴。

原作者只給了文本分類的例子,這里我們對原來的例子稍加改造轻专,使其更適用分類任務(wù)忆矛。

語料庫

本文語料庫特指文本分類語料庫,對應(yīng)IDataSet接口请垛。而文本分類語料庫包含兩個(gè)概念:文檔和類目催训。一個(gè)文檔只屬于一個(gè)類目,一個(gè)類目可能含有多個(gè)文檔宗收。比如搜狗文本分類語料庫迷你版.zip漫拭,下載前請先閱讀搜狗實(shí)驗(yàn)室數(shù)據(jù)使用許可協(xié)議。

數(shù)據(jù)格式

分類語料的根目錄.目錄必須滿足如下結(jié)構(gòu):

根目錄

├── 分類A

│? └── 1.txt

│? └── 2.txt

│? └── 3.txt

├── 分類B

│? └── 1.txt

│? └── ...

└── ...


文件不一定需要用數(shù)字命名,也不需要以txt作為后綴名,但一定需要是文本文件.

分詞

目前混稽,本系統(tǒng)中的分詞器接口一共有兩種實(shí)現(xiàn): BigramTokenizer and HanLPTokenizer采驻。

但文本分類是否一定需要分詞?答案是否定的荚坞。 我們可以順序選取文中相鄰的兩個(gè)字挑宠,作為一個(gè)“詞”(術(shù)語叫bigram)。這兩個(gè)字在數(shù)量很多的時(shí)候可以反映文章的主題(參考清華大學(xué)2016年的一篇論文《Zhipeng Guo, Yu Zhao, Yabin Zheng, Xiance Si, Zhiyuan Liu, Maosong Sun. THUCTC: An Efficient Chinese Text Classifier. 2016》)颓影。這在代碼中對應(yīng)BigramTokenizer. 當(dāng)然,也可以采用傳統(tǒng)的分詞器懒鉴,如HanLPTokenizer诡挂。 另外,用戶也可以通過實(shí)現(xiàn)ITokenizer來實(shí)現(xiàn)自己的分詞器临谱,并通過IDataSet#setTokenizer來使其生效

特征提取

特征提取指的是從所有詞中璃俗,選取最有助于分類決策的詞語。理想狀態(tài)下所有詞語都有助于分類決策悉默,但現(xiàn)實(shí)情況是城豁,如果將所有詞語都納入計(jì)算,則訓(xùn)練速度將非常慢抄课,內(nèi)存開銷非常大且最終模型的體積非常大唱星。

本系統(tǒng)采取的是卡方檢測,通過卡方檢測去掉卡方值低于一個(gè)閾值的特征跟磨,并且限定最終特征數(shù)不超過100萬间聊。

預(yù)測

classify方法直接返回最可能的類別的String形式,而predict方法返回所有類別的得分(是一個(gè)Map形式抵拘,鍵是類目哎榴,值是分?jǐn)?shù)或概率),categorize方法返回所有類目的得分(是一個(gè)double數(shù)組,分類得分按照分類名稱的字典序排列)尚蝌,label方法返回最可能類目的字典序迎变。

線程安全性

類似于HanLP的設(shè)計(jì),以效率至上飘言,本系統(tǒng)內(nèi)部實(shí)現(xiàn)沒有使用任何線程鎖,但任何預(yù)測接口都是線程安全的(被設(shè)計(jì)為不儲(chǔ)存中間結(jié)果衣形,將所有中間結(jié)果放入?yún)?shù)棧中)。

from pyhanlp import SafeJClass

import zipfile

import os

from pyhanlp.static import download, remove_file, HANLP_DATA_PATH

# 設(shè)置路徑热凹,否則會(huì)從配置文件中尋找

HANLP_DATA_PATH = "/home/fonttian/Data/CNLP"

"""

獲取測試數(shù)據(jù)路徑泵喘,位于$root/data/textClassification/sogou-mini,

根目錄由配置文件指定,或者等于我們前面手動(dòng)設(shè)置的HANLP_DATA_PATH般妙。

"""

DATA_FILES_PATH = "textClassification/sogou-mini"

def test_data_path():

? ? data_path = os.path.join(HANLP_DATA_PATH, DATA_FILES_PATH)

? ? if not os.path.isdir(data_path):

? ? ? ? os.mkdir(data_path)

? ? return data_path

def ensure_data(data_name, data_url):

? ? root_path = test_data_path()

? ? dest_path = os.path.join(root_path, data_name)

? ? if os.path.exists(dest_path):

? ? ? ? return dest_path

? ? if data_url.endswith('.zip'):

? ? ? ? dest_path += '.zip'

? ? download(data_url, dest_path)

? ? if data_url.endswith('.zip'):

? ? ? ? with zipfile.ZipFile(dest_path, "r") as archive:

? ? ? ? ? ? archive.extractall(root_path)

? ? ? ? remove_file(dest_path)

? ? ? ? dest_path = dest_path[:-len('.zip')]

? ? return dest_path

NaiveBayesClassifier = SafeJClass('com.hankcs.hanlp.classification.classifiers.NaiveBayesClassifier')

IOUtil = SafeJClass('com.hankcs.hanlp.corpus.io.IOUtil')

sogou_corpus_path = ensure_data('搜狗文本分類語料庫迷你版',

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 'http://hanlp.linrunsoft.com/release/corpus/sogou-text-classification-corpus-mini.zip')

def train_or_load_classifier(path):

? ? model_path = path + '.ser'

? ? if os.path.isfile(model_path):

? ? ? ? return NaiveBayesClassifier(IOUtil.readObjectFrom(model_path))

? ? classifier = NaiveBayesClassifier()

? ? classifier.train(sogou_corpus_path)

? ? model = classifier.getModel()

? ? IOUtil.saveObjectTo(model, model_path)

? ? return NaiveBayesClassifier(model)

def predict(classifier, text):

? ? print("《%16s》\t屬于分類\t【%s】" % (text, classifier.classify(text)))

? ? # 如需獲取離散型隨機(jī)變量的分布纪铺,請使用predict接口

? ? # print("《%16s》\t屬于分類\t【%s】" % (text, classifier.predict(text)))

if __name__ == '__main__':

? ? classifier = train_or_load_classifier(sogou_corpus_path)

? ? predict(classifier, "C羅壓梅西內(nèi)馬爾蟬聯(lián)金球獎(jiǎng) 2017=C羅年")

? ? predict(classifier, "英國造航母耗時(shí)8年仍未服役 被中國速度遠(yuǎn)遠(yuǎn)甩在身后")

? ? predict(classifier, "研究生考錄模式亟待進(jìn)一步專業(yè)化")

? ? predict(classifier, "如果真想用食物解壓,建議可以食用燕麥")

? ? predict(classifier, "通用及其部分競爭對手目前正在考慮解決庫存問題")



? ? print("\n 我們這里再用訓(xùn)練好的模型連測試一下新的隨便從網(wǎng)上找來的幾個(gè)新聞標(biāo)題 \n")

? ? predict(classifier, "今年考研壓力進(jìn)一步增大,或許考研正在變成第二次高考")

? ? predict(classifier, "張繼科被劉國梁連珠炮喊醒:醒醒碟渺!奧運(yùn)會(huì)開始了鲜锚。")

? ? predict(classifier, "福特終于開竅了!新車1.5T懟出184馬力苫拍,不足11萬芜繁,思域自愧不如")


《C羅壓梅西內(nèi)馬爾蟬聯(lián)金球獎(jiǎng) 2017=C羅年》 屬于分類 【體育】

《英國造航母耗時(shí)8年仍未服役 被中國速度遠(yuǎn)遠(yuǎn)甩在身后》 屬于分類 【軍事】

《 研究生考錄模式亟待進(jìn)一步專業(yè)化》 屬于分類 【教育】

《如果真想用食物解壓,建議可以食用燕麥》 屬于分類 【健康】

《通用及其部分競爭對手目前正在考慮解決庫存問題》 屬于分類 【汽車】

我們這里再用訓(xùn)練好的模型連測試一下新的隨便從網(wǎng)上找來的幾個(gè)新聞標(biāo)題

《今年考研壓力進(jìn)一步增大,或許考研正在變成第二次高考》 屬于分類 【教育】

《張繼科被劉國梁連珠炮喊醒:醒醒绒极!奧運(yùn)會(huì)開始了骏令。》 屬于分類 【體育】

《福特終于開竅了垄提!新車1.5T懟出184馬力榔袋,不足11萬,思域自愧不如》 屬于分類 【汽車】


從我們最后自己增加的幾個(gè)新聞標(biāo)題來看铡俐,分類器的效果相當(dāng)?shù)暮没硕摇_@多虧了word2vec。

情感分析

我們對于情感分析的實(shí)現(xiàn)與之前的文本分類具有高度的相似性审丘,同時(shí)剛剛也提到了吏够,實(shí)際上他們就是用的一個(gè)分類器。而在python的實(shí)現(xiàn)中滩报,他們則幾乎一模一樣锅知。

也正是因?yàn)槿绱耍灾灰覀儞碛型瑯痈袷降恼Z料露泊,那么我們可以使用這個(gè)分類器做任何我們需要的文本分類

語料來源

可以利用文本分類在情感極性語料上訓(xùn)練的模型做淺層情感分析喉镰。目前公開的情感分析語料庫有:中文情感挖掘語料-ChnSentiCorp,語料發(fā)布者為譚松波惭笑。

"""

獲取測試數(shù)據(jù)路徑侣姆,位于$root/data/textClassification/sogou-mini生真,

根目錄由配置文件指定,或者等于我們前面手動(dòng)設(shè)置的HANLP_DATA_PATH。

ChnSentiCorp評論酒店情感分析

"""

DATA_FILES_PATH = "sentimentAnalysis/ChnSentiCorp"

if __name__ == '__main__':


? ? ChnSentiCorp_path = ensure_data('酒店評論情感分析', \

? ? ? ? 'http://hanlp.linrunsoft.com/release/corpus/ChnSentiCorp.zip')

? ? # 此處感謝網(wǎng)友給出的下載鏈接

? ? # 本文示例中捺宗,如果需要使用本地資料柱蟀,請通過上面的DATA_FILES_PATH變量控制

? ? classifier = train_or_load_classifier(ChnSentiCorp_path)

? ? predict(classifier, '距離川沙公路較近,但是公交指示不對,如果是"蔡陸線"的話,會(huì)非常麻煩.建議用別的路線.房間較為簡單.')

? ? predict(classifier, "商務(wù)大床房,房間很大蚜厉,床有2M寬长已,整體感覺經(jīng)濟(jì)實(shí)惠不錯(cuò)!")

? ? predict(classifier, "標(biāo)準(zhǔn)間太差 房間還不如3星的 而且設(shè)施非常陳舊.建議酒店把老的標(biāo)準(zhǔn)間從新改善.")

? ? predict(classifier, "服務(wù)態(tài)度極其差,前臺接待好象沒有受過培訓(xùn)昼牛,連基本的禮貌都不懂术瓮,竟然同時(shí)接待幾個(gè)客人")



? ? print("\n 我們這里再用訓(xùn)練好的模型連測試一下我自己編的‘新的’的文本 \n")

? ? predict(classifier, "服務(wù)態(tài)度很好,認(rèn)真的接待了我們贰健,態(tài)度可以的胞四!")

? ? predict(classifier, "有點(diǎn)不太衛(wèi)生,感覺不怎么樣伶椿。")


《距離川沙公路較近,但是公交指示不對,如果是"蔡陸線"的話,會(huì)非常麻煩.建議用別的路線.房間較為簡單.》 屬于分類 【正面】

《商務(wù)大床房辜伟,房間很大,床有2M寬脊另,整體感覺經(jīng)濟(jì)實(shí)惠不錯(cuò)!》 屬于分類 【正面】

《標(biāo)準(zhǔn)間太差 房間還不如3星的 而且設(shè)施非常陳舊.建議酒店把老的標(biāo)準(zhǔn)間從新改善.》 屬于分類 【負(fù)面】

《服務(wù)態(tài)度極其差导狡,前臺接待好象沒有受過培訓(xùn),連基本的禮貌都不懂偎痛,竟然同時(shí)接待幾個(gè)客人》 屬于分類 【負(fù)面】

我們這里再用訓(xùn)練好的模型連測試一下我自己編的‘新的’的文本

《服務(wù)態(tài)度很好旱捧,認(rèn)真的接待了我們,態(tài)度可以的踩麦!》 屬于分類 【正面】

《? 有點(diǎn)不太衛(wèi)生廊佩,感覺不怎么樣【搁牛》 屬于分類 【負(fù)面】




文章來源于Font Tian的博客

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市顽铸,隨后出現(xiàn)的幾起案子茁计,更是在濱河造成了極大的恐慌,老刑警劉巖谓松,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件星压,死亡現(xiàn)場離奇詭異,居然都是意外死亡鬼譬,警方通過查閱死者的電腦和手機(jī)娜膘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來优质,“玉大人竣贪,你說我怎么就攤上這事军洼。” “怎么了演怎?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵匕争,是天一觀的道長。 經(jīng)常有香客問我爷耀,道長甘桑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任歹叮,我火速辦了婚禮跑杭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘咆耿。我一直安慰自己德谅,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布票灰。 她就那樣靜靜地躺著女阀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪屑迂。 梳的紋絲不亂的頭發(fā)上浸策,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天,我揣著相機(jī)與錄音惹盼,去河邊找鬼庸汗。 笑死,一個(gè)胖子當(dāng)著我的面吹牛手报,可吹牛的內(nèi)容都是我干的蚯舱。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼掩蛤,長吁一口氣:“原來是場噩夢啊……” “哼枉昏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起揍鸟,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤兄裂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后阳藻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體晰奖,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年腥泥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了匾南。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蛔外,死狀恐怖蛆楞,靈堂內(nèi)的尸體忽然破棺而出溯乒,到底是詐尸還是另有隱情,我是刑警寧澤臊岸,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布橙数,位于F島的核電站,受9級特大地震影響帅戒,放射性物質(zhì)發(fā)生泄漏灯帮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一逻住、第九天 我趴在偏房一處隱蔽的房頂上張望钟哥。 院中可真熱鬧,春花似錦瞎访、人聲如沸腻贰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽播演。三九已至,卻和暖如春伴奥,著一層夾襖步出監(jiān)牢的瞬間写烤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工拾徙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留洲炊,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓尼啡,卻偏偏與公主長得像暂衡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子崖瞭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容