什么是詞干提取?
在語言形態學和信息檢索里,詞干提取是去除詞綴得到詞根的過程─―得到單詞最一般的寫法。對于一個詞的形態詞根,詞干并不需要完全相同;相關的詞映射到同一個詞干一般能得到滿意的結果,即使該詞干不是詞的有效根。從1968年開始在計算機科學領域出現了詞干提取的相應算法。很多搜索引擎在處理詞匯時,對同義詞采用相同的詞干作為查詢拓展,該過程叫做歸并。
一個面向英語的詞干提取器,例如,要識別字符串“cats”、“catlike”和“catty”是基于詞根“cat”;“stemmer”、“stemming”和“stemmed”是基于詞根“stem”。一根詞干提取算法可以簡化詞 “fishing”、“fished”、“fish”和“fisher” 為同一個詞根“fish”。
技術方案的選擇
Python和R是數據分析的兩種主要語言;相對于R,Python更適合有大量編程背景的數據分析初學者,尤其是已經掌握Python語言的程序員。所以我們選擇了Python和NLTK庫(Natual Language Tookit)作為文本處理的基礎框架。此外,我們還需要一個數據展示工具;對于一個數據分析師來說,數據庫的冗繁安裝、連接、建表等操作實在是不適合進行快速的數據分析,所以我們使用Pandas作為結構化數據和分析工具。
環境搭建
我們使用的是Mac OS X,已預裝Python 2.7.
安裝NLTK
sudo pip install nltk
安裝Pandas
sudo pip install pandas
對于數據分析來說,最重要的是分析結果,iPython notebook是必備的一款利器,它的作用在于可以保存代碼的執行結果,例如數據表格,下一次打開時無需重新運行即可查看。
安裝iPython notebook
sudo pip install ipython
創建一個工作目錄,在工作目錄下啟動iPython notebook,服務器會開啟http://127.0.0.1:8080頁面,并將創建的代碼文檔保存在工作目錄之下。
mkdir Codescd Codesipython notebook
文本處理
數據表創建
使用Pandas創建數據表 我們使用得到的樣本數據,建立DataFrame――Pandas中一個支持行、列的2D數據結構。
from pandas import DataFrameimport pandas as pdd = ['pets insurance','pets insure','pet insurance','pet insur','pet insurance"','pet insu']df = DataFrame(d)df.columns = ['Words']df
顯示結果

NLTK分詞器介紹
RegexpTokenizer:正則表達式分詞器,使用正則表達式對文本進行處理,就不多作介紹。
PorterStemmer:波特詞干算法分詞器,原理可看這里:http://snowball.tartarus.org/algorithms/english/stemmer.html
第一步,我們創建一個去除標點符號等特殊字符的正則表達式分詞器:
import nltktokenizer = nltk.RegexpTokenizer(r'w+')
接下來,對準備好的數據表進行處理,添加詞干將要寫入的列,以及統計列,預設默認值為1:
df["Stemming Words"] = ""df["Count"] = 1
讀取數據表中的Words列,使用波特詞干提取器取得詞干:
j = 0while (j <= 5): for word in tokenizer.tokenize(df["Words"][j]): df["Stemming Words"][j] = df["Stemming Words"][j] + " " + nltk.PorterStemmer().stem_word(word) j += 1df
Good!到這一步,我們已經基本上實現了文本處理,結果顯示如下:

分組統計
在Pandas中進行分組統計,將統計表格保存到一個新的DataFrame結構uniqueWords中:
uniqueWords = df.groupby(['Stemming Words'], as_index = False).sum().sort(['Count'])uniqueWords

注意到了嗎?依然還有一個pet insu未能成功處理。
拼寫檢查
對于用戶拼寫錯誤的詞語,我們首先想到的是拼寫檢查,針對Python我們可以使用enchant:
sudo pip install enchant
使用enchant進行拼寫錯誤檢查,得到推薦詞:
import enchantfrom nltk.metrics import edit_distanceclass SpellingReplacer(object): def __init__(self, dict_name='en', max_dist=2): self.spell_dict = enchant.Dict(dict_name) self.max_dist = 2 def replace(self, word): if self.spell_dict.check(word): return word suggestions = self.spell_dict.suggest(word) if suggestions and edit_distance(word, suggestions[0]) <= self.max_dist: return suggestions[0] else: return wordfrom replacers import SpellingReplacerreplacer = SpellingReplacer()replacer.replace('insu')'insu'但是,結果依然不是我們預期的“insur”。能不能換種思路呢?
算法特殊性
用戶輸入非常重要的特殊性來自于行業和使用場景。采取通用的英語大詞典來進行拼寫檢查,無疑是行不通的,并且某些詞語恰恰是拼寫正確,但本來卻應該是另一個詞。但是,我們如何把這些背景信息和數據分析關聯起來呢?
經過一番思考,我認為最重要的參考庫恰恰就在已有的數據分析結果中,我們回來看看:

已有的5個“pet insur”,其實就已經給我們提供了一份數據參考,我們已經可以對這份數據進行聚類,進一步除噪。
相似度計算
對已有的結果進行相似度計算,將滿足最小偏差的數據歸類到相似集中:
import LevenshteinminDistance = 0.8distance = -1lastWord = ""j = 0while (j < 1): lastWord = uniqueWords["Stemming Words"][j] distance = Levenshtein.ratio(uniqueWords["Stemming Words"][j], uniqueWords["Stemming Words"][j + 1]) if (distance > minDistance): uniqueWords["Stemming Words"][j] = uniqueWords["Stemming Words"][j + 1] j += 1uniqueWords
查看結果,已經匹配成功!

最后一步,重新對數據結果進行分組統計:
uniqueWords = uniqueWords.groupby(['Stemming Words'], as_index = False).sum()uniqueWords
到此,我們已經完成了初步的文本處理。

新聞熱點
疑難解答
圖片精選