1. 程式人生 > >NLP自然語言處理入門-- 文本預處理Pre-processing

NLP自然語言處理入門-- 文本預處理Pre-processing

檢查 bag 領域 影響 rds except clean numpy 我只

引言

自然語言處理NLP(nature language processing),顧名思義,就是使用計算機對語言文字進行處理的相關技術以及應用。在對文本做數據分析時,我們一大半的時間都會花在文本預處理上,而中文和英文的預處理流程稍有不同,本文就對中、英文文本挖掘的常用的NLP的文本預處技術做一個總結。

文章內容主要按下圖流程講解:

技術分享圖片

1.中英文文本預處理的特點

中英文的文本預處理大體流程如上圖,但是還是有部分區別。首先,中文文本是沒有像英文的單詞空格那樣隔開的,因此不能直接像英文一樣可以直接用最簡單的空格和標點符號完成分詞。所以一般我們需要用分詞算法來完成分詞,具體操作後面會講到。

當然,英文文本的預處理也有自己特殊的地方——拼寫問題,很多時候,對英文預處理要包括拼寫檢查,比如“Helo World”這樣的錯誤,我們不能在分析的時候再去糾錯。還有就是詞幹提取(stemming)和詞形還原(lemmatization),主要是因為英文中一個詞會會不同的形式,這個步驟有點像孫悟空的火眼金睛,直接得到單詞的原始形態。比如,"faster"、"fastest", 都變為"fast";“leafs”、“leaves”,都變為"leaf"。

2. 收集數據

文本數據的獲取一般有兩個方法:

  • 別人已經做好的數據集,或則第三方語料庫,比如wiki。這樣可以省去很多麻煩。自己從網上爬取數據。但很多情況所研究的是面向某種特定的領域,這些開放語料庫經常無法滿足我們的需求。我們就需要用爬蟲去爬取想要的信息了。可以使用如beautifulsoup、scrapy等框架編寫出自己需要的爬蟲。

3.文本預處理

3.1 去除數據中的非文本部分

由於爬下來的內容中有很多html的一些標簽,需要去掉。還有少量的非文本內容的可以直接用Python 的正則表達式(re)刪除, 另外還有一些特殊的非英文字符和標點符號,也可以用Python的正則表達式(re)刪除。

import re
# 過濾不了\ 中文()還有————
r1 = u‘[a-zA-Z0-9’!"#$%&‘()*+,-./:;<=>[email protected],。?★、…【】《》?“”‘’![\]^_`{|}~]+‘#用戶也可以在此進行自定義過濾字符
# 者中規則也過濾不完全
r2 = "[s+.!/_,$%^*(+"‘]+|[+——!,。?、[email protected]#¥%……&*()]+"
# \可以過濾掉反向單杠和雙杠,/可以過濾掉正向單杠和雙杠,第一個中括號裏放的是英文符號,第二個中括號裏放的是中文符號,第二個中括號前不能少|,否則過濾不完全
r3 = "[.!//_,$&%^*()<>+"‘[email protected]#-|:~{}]+|[——!\\,。=?、:“”‘’《》【】¥……()]+"
# 去掉括號和括號內的所有內容
r4 = "\【.*?】+|\《.*?》+|\#.*?#+|[.!/_,$&%^*()<>+""‘[email protected]|:~{}#]+|[——!\,。=?、:“”‘’¥……()《》【】]"
sentence = "hello! wo?rd!."
cleanr = re.compile(‘<.*?>‘)
sentence = re.sub(cleanr, ‘ ‘, sentence) #去除html標簽
sentence = re.sub(r4,‘‘,sentence)
print(sentence)

3.2 分詞

  • 由於英文單詞間由空格分隔,所以分詞分簡單,只需要調用split()函數即可。對於中文來說常用的中文分詞軟件有很多,例如,結巴分詞。安裝也很簡單,比如基於Python的,用"pip install jieba"就可以完成。
import jieba
sentence = "我們學習人工智能"
sentence_seg = jieba.cut(sentence)
result = ‘ ‘.join(sentence_seg)
print(result)

3.3 去掉停用詞

停用詞就是句子沒什麽必要的單詞,去掉他們以後對理解整個句子的語義沒有影響。文本中,會存在大量的虛詞、代詞或者沒有特定含義的動詞、名詞,這些詞語對文本分析起不到任何的幫助,我們往往希望能去掉這些“停用詞”。

  • 在英文中,例如,"a","the",“to",“their”等冠詞,借此,代詞..... 我們可以直接用nltk中提供的英文停用詞表。首先,"pip install nltk"安裝nltk。當你完成這一步時,其實是還不夠的。因為NLTK是由許多許多的包來構成的,此時運行Python,並輸入下面的指令。
import nltk
from nltk.tokenize import word_tokenize
nltk.download()

然後,Python Launcher會彈出下面這個界面,你可以選擇安裝所有的Packages,以免去日後一而再、再而三的進行安裝,也為你的後續開發提供一個穩定的環境。

技術分享圖片

我們可以運行下面的代碼,看看英文的停用詞庫。

from nltk.corpus import stopwords 
stop = set(stopwords.words(‘english‘))
print(stop)

去除停用詞

sentence = "this is a apple"
filter_sentence= [w for w in sentence.split(‘ ‘) if w not in stopwords.words(‘english‘)]
print(filter_sentence)

對於中文停用詞,由於nlkt不支持中文,所以需要自己構造中文停用詞。常用的中文停用詞表是1208個,下載地址在這 。有了中文停用詞表,去除停用詞的代碼和英文類似,這裏就不贅述了。

3.4 英文單詞--stemming和lemmatization

詞幹提取(stemming)和詞型還原(lemmatization)是英文文本預處理的特色。兩者其實有共同點,即都是要找到詞的原始形式。只不過詞幹提取(stemming)會更加激進一點,它在尋找詞幹的時候可以會得到不是詞的詞幹。比如"leaves"的詞幹可能得到的是"leav", 並不是一個詞。而詞形還原則保守一些,它一般只對能夠還原成一個正確的詞的詞進行處理。nltk中提供了很多方法,wordnet的方式比較好用,不會把單詞過分精簡。

from nltk.stem import SnowballStemmer
stemmer = SnowballStemmer("english") # 選擇語言
stemmer.stem("leaves") # 詞幹化單詞
from nltk.stem import WordNetLemmatizer
wnl = WordNetLemmatizer()
print(wnl.lemmatize(‘leaves‘))

3.5 英文單詞--轉換為小寫

英文單詞有大小寫之分,Python和python是同一個單詞,所以轉換為小寫可以減少單詞數量。

word = "Python"
word = word.lower() #轉換成lower_case
print(word)

3.6 特征處理

數據處理到這裏,基本上是幹凈的文本了,現在可以調用sklearn來對我們的文本特征進行處理了。常用的方法如下:

  • Bag of Words詞袋模型BowTf-idfN-gram語言模型BigramTrigramWord2vec分布式模型Word2vec

接下來我將結合代碼簡單講解一下Tf-idf,Bigram,word2vec的用法。語言模型這一塊內容,可以在之後的文章深入了解。

Tf-idf(Term Frequency-Inverse Document Frequency)

該模型基於詞頻,將文本轉換成向量,而不考慮詞序。假設現在有N篇文檔,在其中一篇文檔D中,詞匯x的TF、IDF、TF-IDF定義如下:

1.Term Frequency(TF(x)):指詞x在當前文本D中的詞頻

2.Inverse Document Frequency(IDF): N代表語料庫中文本的總數,而N(x)代表語料庫中包含詞x的文本總數,平滑後的IDF如下:

技術分享圖片

3.TF-IDF :

技術分享圖片

使用sklearn庫裏的TfidfVectorizer類可以幫助我們完成向量化,TF-IDF和標準化三步。

from sklearn.feature_extraction.text import TfidfVectorizer
corpus = ["This is sample document.", "another random document.", "third sample document text"]
vector = TfidfVectorizer()
tf_data = vector.fit_transform(corpus)
print(tf_data) #(句子下標, 單詞特征下標) 權重
print(vector.vocabulary_) #單詞特征
df1 = pd.DataFrame(tf_data.toarray(), columns=vector.get_feature_names()) # to DataFrame
df1
技術分享圖片

N-gram語言模型

詞袋模型不考慮每個單詞的順序。有時候把一句話順序搗亂,我們可能就看不懂這句話在說什麽了,例如:

我玩電腦 = 電腦玩我 ?

N-gram模型是一種語言模型(Language Model),語言模型是一個基於概率的判別模型,它的輸入是一句話(單詞的順序序列),輸出是這句話的概率,即這些單詞的聯合概率(joint probability)。N-gram本身也指一個由N個單詞組成的集合,各單詞具有先後順序,且不要求單詞之間互不相同。常用的有 Bi-gram (N=2N=2) 和 Tri-gram (N=3N=3),一般已經夠用了。例如,"I love deep learning",可以分解的 Bi-gram 和 Tri-gram :

Bi-gram : {I, love}, {love, deep}, {love, deep}, {deep, learning}

Tri-gram : {I, love, deep}, {love, deep, learning}

sklearn庫中的CountVectorizer 有一個參數ngram_range,如果賦值為(2,2)則為Bigram,當然使用語言模型會大大增加我們字典的大小。

ram_range=(1,1) 表示 unigram, ngram_range=(2,2) 表示 bigram, ngram_range=(3,3) 表示 thirgram
from sklearn.feature_extraction.text import CountVectorizer
import pandas as pd
import jieba
data = ["為了祖國,為了勝利,向我開炮!向我開炮!",
"記者:你怎麽會說出那番話",
"我只是覺得,對準我自己打"]
data = [" ".join(jieba.lcut(e)) for e in data] # 分詞,並用" "連接
vector = CountVectorizer(min_df=1, ngram_range=(2,2)) # bigram
X = vector.fit_transform(data) # 將分詞好的文本轉換為矩陣
print(vector.vocabulary_ ) # 得到特征
print(X) #(句子下標, 單詞特征下標) 頻數
df1 = pd.DataFrame(X.toarray(), columns=vector.get_feature_names()) # to DataFrame
df1.head()
技術分享圖片

Word2vec詞向量

Word2Vec使用一系列的文檔的詞語去訓練模型,把文章的詞映射到一個固定長度的連續向量

。一般維數較小,通常為100 ~ 500。意義相近的詞之間的向量距離較小。它以稠密的向量形式表示單詞。有兩種模式:

CBOW(Continuous Bag-Of-Words):利用詞的上下文預測當前的詞。

Skip-Gram:利用當前的詞來預測上下文。

因為word2vector模型的得到的是詞向量,如何表示句子呢?最簡單的方法就是,將每個句子中的詞向量相加取平均值,即每個句子的平均詞向量來表示句子的向量。

from gensim.models import Word2Vec 
import numpy as np
data = ["I love deep learning","I love studying","I want to travel"]
#詞頻少於min_count次數的單詞會被丟棄掉
#size指特征向量的維度為50
#workers參數控制訓練的並行數
train_w2v = Word2Vec(data,min_count=5,size=50, workers=4)
for row in data: #計算平均詞向量,表示句子向量
vec = np.zeros(50)
count = 0
for word in row:
try:
vec += train_w2v[word]
count += 1
except:
pass
avg_data.append(vec/count)
print(avg_data[1])
技術分享圖片

4. 建立分析模型

有了每段文本的特征向量後,我們就可以利用這些數據建立分類模型,或者聚類模型了,或者進行相似度的分析。

5.總結

3.6小節中的特征提取一塊,為了demo演示的方便,沒有和前面的分詞,清洗,標準化結合在一起。如果是從分詞步驟開始做的文本預處理,需要註意:在特征提取時,要將每個句子的單詞以空格連接起來。

NLP自然語言處理入門-- 文本預處理Pre-processing