中文文本挖掘預處理流程總結

from:http://www.cnblogs.com/pinard/p/6744056.html


在對文本做數據分析時,我們一大半的時間都會花在文本預處理上,而中文和英文的預處理流程稍有不同,本文就對中文文本挖掘的預處理流程做一個總結。

1. 中文文本挖掘預處理特點

    首先我們看看中文文本挖掘預處理和英文文本挖掘預處理相比的一些特殊點。

    首先,中文文本是沒有像英文的單詞空格那樣隔開的,因此不能直接像英文一樣可以直接用最簡單的空格和標點符號完成分詞。所以一般我們需要用分詞算法來完成分詞,在文本挖掘的分詞原理中,我們已經講到了中文的分詞原理,這裏就不多說。

    第二,中文的編碼不是utf8,而是unicode。這樣會導致在分詞的時候,和英文相比,我們要處理編碼的問題。

    這兩點構成了中文分詞相比英文分詞的一些不同點,後面我們也會重點講述這部分的處理。當然,英文分詞也有自己的煩惱,這個我們在以後再講。瞭解了中文預處理的一些特點後,我們就言歸正傳,通過實踐總結下中文文本挖掘預處理流程。

2.  中文文本挖掘預處理一:數據收集

    在文本挖掘之前,我們需要得到文本數據,文本數據的獲取方法一般有兩種:使用別人做好的語料庫和自己用爬蟲去在網上去爬自己的語料數據。

    對於第一種方法,常用的文本語料庫在網上有很多,如果大家只是學習,則可以直接下載下來使用,但如果是某些特殊主題的語料庫,比如“機器學習”相關的語料庫,則這種方法行不通,需要我們自己用第二種方法去獲取。

    對於第二種使用爬蟲的方法,開源工具有很多,通用的爬蟲我一般使用beautifulsoup。但是我們我們需要某些特殊的語料數據,比如上面提到的“機器學習”相關的語料庫,則需要用主題爬蟲(也叫聚焦爬蟲)來完成。這個我一般使用ache。 ache允許我們用關鍵字或者一個分類算法來過濾出我們需要的主題語料,比較強大。

3.  中文文本挖掘預處理二:除去數據中非文本部分

    這一步主要是針對我們用爬蟲收集的語料數據,由於爬下來的內容中有很多html的一些標籤,需要去掉。少量的非文本內容的可以直接用Python的正則表達式(re)刪除, 複雜的則可以用beautifulsoup來去除。去除掉這些非文本的內容後,我們就可以進行真正的文本預處理了。

4. 中文文本挖掘預處理三:處理中文編碼問題

    由於Python2不支持unicode的處理,因此我們使用Python2做中文文本預處理時需要遵循的原則是,存儲數據都用utf8,讀出來進行中文相關處理時,使用GBK之類的中文編碼,在下面一節的分詞時,我們再用例子說明這個問題。

5. 中文文本挖掘預處理四:中文分詞

    常用的中文分詞軟件有很多,個人比較推薦結巴分詞。安裝也很簡單,比如基於Python的,用"pip install jieba"就可以完成。下面我們就用例子來看看如何中文分詞。

    首先我們準備了兩段文本,這兩段文本在兩個文件中。兩段文本的內容分別是nlp_test0.txt和nlp_test2.txt:

          沙瑞金讚歎易學習的胸懷,是金山的百姓有福,可是這件事對李達康的觸動很大。易學習又回憶起他們三人分開的前一晚,大家一起喝酒話別,易學習被降職到道口縣當縣長,王大路下海經商,李達康連連賠禮道歉,覺得對不起大家,他最對不起的是王大路,就和易學習一起給王大路湊了5萬塊錢,王大路自己東挪西撮了5萬塊,開始下海經商。沒想到後來王大路竟然做得風生水起。沙瑞金覺得他們三人,在困難時期還能以沫相助,很不容易。

    沙瑞金向毛婭打聽他們家在京州的別墅,毛婭笑着說,王大路事業有成之後,要給歐陽菁和她公司的股權,她們沒有要,王大路就在京州帝豪園買了三套別墅,可是李達康和易學習都不要,這些房子都在王大路的名下,歐陽菁好像去住過,毛婭不想去,她覺得房子太大很浪費,自己家住得就很踏實。

   我們先講文本從第一個文件中讀取,並使用中文GBK編碼,再調用結巴分詞,最後把分詞結果用uft8格式存在另一個文本nlp_test1.txt

中。代碼如下:

複製代碼
# -*- coding: utf-8 -*-

import jieba

with open('./nlp_test0.txt') as f:
    document = f.read()
    
    document_decode = document.decode('GBK')
    document_cut = jieba.cut(document_decode)
    #print  ' '.join(jieba_cut)  //如果打印結果,則分詞效果消失,後面的result無法顯示
    result = ' '.join(document_cut)
    result = result.encode('utf-8')
    with open('./nlp_test1.txt', 'w') as f2:
        f2.write(result)
f.close()
f2.close()
複製代碼

    輸出的文本內容如下:

    沙 瑞金 讚歎 易 學習 的 胸懷 , 是 金山 的 百姓 有福 , 可是 這件 事對 李達康 的 觸動 很大 。 易 學習 又 回憶起 他們 三人 分開 的 前一晚 , 大家 一起 喝酒 話別 , 易 學習 被 降職 到 道口 縣當 縣長 , 王 大路 下海經商 , 李達康 連連 賠禮道歉 , 覺得 對不起 大家 , 他 最 對不起 的 是 王 大路 , 就 和 易 學習 一起 給 王 大路 湊 了 5 萬塊 錢 , 王 大路 自己 東挪西撮 了 5 萬塊 , 開始 下海經商 。 沒想到 後來 王 大路 竟然 做 得 風生水 起 。 沙 瑞金 覺得 他們 三人 , 在 困難 時期 還 能 以沫 相助 , 很 不 容易 。

    可以發現對於一些人名和地名,jieba處理的不好,不過我們可以幫jieba加入詞彙如下:

jieba.suggest_freq('沙瑞金', True)
jieba.suggest_freq('易學習', True)
jieba.suggest_freq('王大路', True)
jieba.suggest_freq('京州', True)

    現在我們再來進行讀文件,編碼,分詞,編碼和寫文件,代碼如下:

複製代碼
with open('./nlp_test0.txt') as f:
    document = f.read()
    
    document_decode = document.decode('GBK')
    document_cut = jieba.cut(document_decode)
    #print  ' '.join(jieba_cut)
    result = ' '.join(document_cut)
    result = result.encode('utf-8')
    with open('./nlp_test1.txt', 'w') as f2:
        f2.write(result)
f.close()
f2.close()   
複製代碼

    輸出的文本內容如下:

    沙瑞金 讚歎 易學習 的 胸懷 , 是 金山 的 百姓 有福 , 可是 這件 事對 李達康 的 觸動 很大 。 易學習 又 回憶起 他們 三人 分開 的 前一晚 , 大家 一起 喝酒 話別 , 易學習 被 降職 到 道口 縣當 縣長 , 王大路 下海經商 , 李達康 連連 賠禮道歉 , 覺得 對不起 大家 , 他 最 對不起 的 是 王大路 , 就 和 易學習 一起 給 王大路 湊 了 5 萬塊 錢 , 王大路 自己 東挪西撮 了 5 萬塊 , 開始 下海經商 。 沒想到 後來 王大路 竟然 做 得 風生水 起 。 沙瑞金 覺得 他們 三人 , 在 困難 時期 還 能 以沫 相助 , 很 不 容易 。

    基本已經可以滿足要求。同樣的方法我們對第二段文本nlp_test2.txt進行分詞和寫入文件nlp_test3.txt。

複製代碼
with open('./nlp_test2.txt') as f:
    document2 = f.read()
    
    document2_decode = document2.decode('GBK')
    document2_cut = jieba.cut(document2_decode)
    #print  ' '.join(jieba_cut)
    result = ' '.join(document2_cut)
    result = result.encode('utf-8')
    with open('./nlp_test3.txt', 'w') as f2:
        f2.write(result)
f.close()
f2.close()  
複製代碼

    輸出的文本內容如下:

    沙瑞金 向 毛婭 打聽 他們 家 在 京州 的 別墅 , 毛婭 笑 着 說 , 王大路 事業有成 之後 , 要 給 歐陽 菁 和 她 公司 的 股權 , 她們 沒有 要 , 王大路 就 在 京州 帝豪園 買 了 三套 別墅 , 可是 李達康 和 易學習 都 不要 , 這些 房子 都 在 王大路 的 名下 , 歐陽 菁 好像 去 住 過 , 毛婭 不想 去 , 她 覺得 房子 太大 很 浪費 , 自己 家住 得 就 很 踏實 。

    可見分詞效果還不錯。

6. 中文文本挖掘預處理五:引入停用詞

    在上面我們解析的文本中有很多無效的詞,比如“着”,“和”,還有一些標點符號,這些我們不想在文本分析的時候引入,因此需要去掉,這些詞就是停用詞。常用的中文停用詞表是1208個,下載地址在這。當然也有其他版本的停用詞表,不過這個1208詞版是我常用的。

    在我們用scikit-learn做特徵處理的時候,可以通過參數stop_words來引入一個數組作爲停用詞表。

    現在我們將停用詞表從文件讀出,並切分成一個數組備用:

複製代碼
#從文件導入停用詞表
stpwrdpath = "stop_words.txt"
stpwrd_dic = open(stpwrdpath, 'rb')
stpwrd_content = stpwrd_dic.read()
#將停用詞表轉換爲list  
stpwrdlst = stpwrd_content.splitlines()
stpwrd_dic.close()
複製代碼

7. 中文文本挖掘預處理六:特徵處理

    現在我們就可以用scikit-learn來對我們的文本特徵進行處理了,在文本挖掘預處理之向量化與Hash Trick中,我們講到了兩種特徵處理的方法,向量化與Hash Trick。而向量化是最常用的方法,因爲它可以接着進行TF-IDF的特徵處理。在文本挖掘預處理之TF-IDF中,我們也講到了TF-IDF特徵處理的方法。這裏我們就用scikit-learn的TfidfVectorizer類來進行TF-IDF特徵處理。

    TfidfVectorizer類可以幫助我們完成向量化,TF-IDF和標準化三步。當然,還可以幫我們處理停用詞。

    現在我們把上面分詞好的文本載入內存:

複製代碼
with open('./nlp_test1.txt') as f3:
    res1 = f3.read()
print res1
with open('./nlp_test3.txt') as f4:
    res2 = f4.read()
print res2
複製代碼

    這裏的輸出還是我們上面分完詞的文本。現在我們可以進行向量化,TF-IDF和標準化三步處理了。注意,這裏我們引入了我們上面的停用詞表。

from sklearn.feature_extraction.text import TfidfVectorizer
corpus = [res1,res2]
vector = TfidfVectorizer(stop_words=stpwrdlst)
tfidf = vector.fit_transform(corpus)
print tfidf

    部分輸出如下:

  (0, 44)	0.154467434933
  (0, 59)	0.108549295069
  (0, 39)	0.308934869866
  (0, 53)	0.108549295069
  ....
  (1, 27)	0.139891059658
  (1, 47)	0.139891059658
  (1, 30)	0.139891059658
  (1, 60)	0.139891059658

    我們再來看看每次詞和TF-IDF的對應關係:

複製代碼
wordlist = vector.get_feature_names()#獲取詞袋模型中的所有詞  
# tf-idf矩陣 元素a[i][j]表示j詞在i類文本中的tf-idf權重
weightlist = tfidf.toarray()  
#打印每類文本的tf-idf詞語權重,第一個for遍歷所有文本,第二個for便利某一類文本下的詞語權重
for i in range(len(weightlist)):  
    print "-------第",i,"段文本的詞語tf-idf權重------"  
    for j in range(len(wordlist)):  
        print wordlist[j],weightlist[i][j]  
複製代碼

    部分輸出如下:

-------第 0 段文本的詞語tf-idf權重------
一起 0.217098590137
萬塊 0.217098590137
三人 0.217098590137
三套 0.0
下海經商 0.217098590137
.....
-------第 1 段文本的詞語tf-idf權重------
.....
李達康 0.0995336411066
歐陽 0.279782119316
毛婭 0.419673178975
沙瑞金 0.0995336411066
沒想到 0.0
沒有 0.139891059658
浪費 0.139891059658
王大路 0.29860092332
.....

 

8. 中文文本挖掘預處理七:建立分析模型

    有了每段文本的TF-IDF的特徵向量,我們就可以利用這些數據建立分類模型,或者聚類模型了,或者進行主題模型的分析。比如我們上面的兩段文本,就可以是兩個訓練樣本了。此時的分類聚類模型和之前講的非自然語言處理的數據分析沒有什麼兩樣。因此對應的算法都可以直接使用。而主題模型是自然語言處理比較特殊的一塊,這個我們後面再單獨講。

9.中文文本挖掘預處理總結

    上面我們對中文文本挖掘預處理的過程做了一個總結,希望可以幫助到大家。需要注意的是這個流程主要針對一些常用的文本挖掘,並使用了詞袋模型,對於某一些自然語言處理的需求則流程需要修改。比如我們涉及到詞上下文關係的一些需求,此時不能使用詞袋模型。而有時候我們對於特徵的處理有自己的特殊需求,因此這個流程僅供自然語言處理入門者參考。

    下一篇我們來總結英文文本挖掘預處理流程,盡情期待。

 

(歡迎轉載,轉載請註明出處。歡迎溝通交流: [email protected]) 

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