自然語言處理中的文本處理和特徵工程
機器之心報道
文本處理
現有數據中,文本是最非結構化的形式,裡面有各種各樣的雜訊;如果沒有預處理,文本數據都不能分析。清理和標準化文本的整個過程叫做文本預處理(text preprocessing),其作用是使文本數據沒有雜訊並且可以分析。
主要包括三個步驟:
移除雜訊
辭彙規範化
對象標準化
下圖展示了文本預處理流程的結構。
移除雜訊
任何與數據上下文和最終輸出無關的文本都可被判作雜訊。
例如,語言停止詞(stopword,語言中常用的辭彙:系動詞is,am,定冠詞the,介詞of,in)、URL 或鏈接、社交媒體實體(提及、標籤)、標點符號和特定行業辭彙。這一步移除了文本中所有類型的雜訊。
移除雜訊通用的做法是準備一個雜訊實體的詞典,在文本對象上逐個 token(或逐詞)迭代,消除在雜訊詞典中出現的標籤。
以下是實現這一步的 Python 代碼:
```
# Sample code to remove noisy words from a text
noise_list = ["is", "a", "this", "..."]
def _remove_noise(input_text):
words = input_text.split()
noise_free_words = [word for word in words if word not in noise_list]
noise_free_text = " ".join(noise_free_words)
return noise_free_text
_remove_noise("this is a sample text")
>>> "sample text"
```
另外一種方法是使用正則表達式,儘管其只能解決特定模式的雜訊。我們在之前的文章中詳細介紹了正則表達式:https://www.analyticsvidhya.com/blog/2015/06/regular-expression-python/
以下是從輸入文本中移除正則表達式的 Python 代碼:
```
# Sample code to remove a regex pattern
import re
def _remove_regex(input_text, regex_pattern):
urls = re.finditer(regex_pattern, input_text)
for i in urls:
input_text = re.sub(i.group().strip(), "", input_text)
return input_text
regex_pattern = "#[A-Za-z0-9w]*"
_remove_regex("remove this #hashtag from analytics vidhya", regex_pattern)
>>> "remove this from analytics vidhya"
```
辭彙規範化
另外一種文本形式的雜訊是由一個辭彙所產生的多種表示形式。
例如,「play」,「player」,「played」,「plays」和「playing」,這些辭彙都是由「play」變化而來的。雖然它們意義不一,但根據上下文都是相似的。辭彙規範化這一步把一個詞的不同展現形式轉化為了他們規範化的形式(也叫做引理(lemma))。規範化是文本上的特徵工程起中樞作用的一步,因為它把高維特徵(N個不同的特徵)轉化為了對任何機器學習模型都很理想的低維空間(1個特徵)。
最常見的辭彙規範化是:
詞幹提取:詞幹提取是辭彙後綴(「ing」,「ly」,「es」,「s」等)去除過程的一個基本規則。
詞形還原:詞形還原與詞幹提取相反,是有組織地逐步獲取辭彙根形式的步驟,它使用到了辭彙(辭彙字典序)和形態分析(詞的結構和語法關係)。
下面是實現詞形還原和詞幹提取的代碼,使用了一個流行的 Python 庫 NLTK:
```
from nltk.stem.wordnet import WordNetLemmatizer
lem = WordNetLemmatizer()
from nltk.stem.porter import PorterStemmer
stem = PorterStemmer()
word = "multiplying"
lem.lemmatize(word, "v")
>> "multiply"
stem.stem(word)
>> "multipli"
```
對象標準化
文本數據經常包含不在任何標準詞典里出現的辭彙或短語。搜索引擎和模型都識別不了這些。
比如,首字母縮略詞、辭彙附加標籤和通俗俚語。通過正則表達式和人工準備的數據詞典,這種類型的雜訊可以被修復。以下代碼使用了詞典查找方法來替代文本中的社交俚語。
```
lookup_dict = {"rt":"Retweet", "dm":"direct message", "awsm" : "awesome", "luv" :"love", "..."}
def _lookup_words(input_text):
words = input_text.split()
new_words = []
for word in words:
if word.lower() in lookup_dict:
word = lookup_dict[word.lower()]
new_words.append(word) new_text = " ".join(new_words)
return new_text
_lookup_words("RT this is a retweeted tweet by Shivam Bansal")
>> "Retweet this is a retweeted tweet by Shivam Bansal"
```
除了目前為止討論過的三個步驟,其他類型的文本預處理有編碼-解碼雜訊,語法檢查器和拼寫改正等。我之前的一篇文章給出了預處理及其方法的細節。
文本到特徵(文本數據上的特徵工程)
為了分析已經預處理過的數據,需要將數據轉化成特徵(feature)。取決於用途,文本特徵可通過句法分析、實體/N元模型/基於辭彙的特徵、統計特徵和辭彙嵌入等方法來構建。下面來詳細理解這些技巧。
句法分析
句法分析涉及到對句中詞的語法分析和位置與辭彙的關係的分析。依存語法(Dependency Grammar)和詞性標註(Part of Speech tags)是重要的文本句法屬性。
依賴樹(Dependency Trees)——由一些辭彙共同組成的句子。句中詞與詞之間的聯繫是由基本的依存語法決定的。從屬關係語法是一類解決(已標籤)兩個辭彙項(字詞)間二元不對稱關係的句法文本分析。每一種關係都可用三元組(關係、支配成分、從屬成分)來表示。例如:考慮下面這個句子:「Bills on ports and immigration were submitted by Senator Brownback, Republican of Kansas.」辭彙間的關係可由如下所示的樹的形式觀察得到
觀察樹的形狀可得:「submitted」是該句的根詞(root word),由兩顆子樹所連接(主語和賓語子樹)。每一顆子樹本身又是一顆依存關係樹(dependency tree ),其中的關係比如有 - (「Bills」 <-> 「ports」
這種類型的樹,當從上至下迭代分析時可以得到語法關係三元組。對於很多自然語言處理問題,比如實體性情感分析,執行者(actor)與實體識別和文本分類等,語法關係三元組都可以用作特徵。Python wrapper 的StanfordCoreNLP( http://stanfordnlp.github.io/CoreNLP/ 來自斯坦福自然語言處理組,只允許商業許可證)和NTLK從屬關係語法可以用來生成依賴樹。
詞性標註(PoS/Part of speech tagging)——除了語法關係外,句中每個詞都與詞性(名詞、動詞、形容詞、副詞等等)聯繫起來。詞性標註標籤決定了句中該詞的用法和作用。這裡有賓夕法尼亞大學定義的所有可能的詞性標籤表。以下代碼使用了NTLK包對輸入文本執行詞性標籤注釋。(NTLK提供了不同的實現方式,默認是感知器標籤)
```
from nltk import word_tokenize, pos_tag
text = "I am learning Natural Language Processing on Analytics Vidhya"
tokens = word_tokenize(text)
print pos_tag(tokens)
>>> [("I", "PRP"), ("am", "VBP"), ("learning", "VBG"), ("Natural", "NNP"),("Language", "NNP"),
("Processing", "NNP"), ("on", "IN"), ("Analytics", "NNP"),
詞性標註被用在許多重要的自然語言處理目的上:
A. 詞義消歧:一些辭彙根據用法有很多種意思。例如,下面的兩個句子:
I.「Please book my flight for Delhi」
II. 「I am going to read this book in the flight」
「Book」在不同的上下文中出現,然而這兩種情況的詞性標籤卻不一樣。在第一句中,「book」被用作動詞,而在第二句中,它被用作名詞。(Lesk演算法也可被用於相同的目的)
B. 提高基於辭彙的特徵:當辭彙作為特徵時,一個學習模型可以學習到不同的辭彙上下文,然而特徵與詞性連接起來,上下文就被保留了,因此得到了很強的特徵。例如:
句 - 「book my flight, I will read this book」
標籤 – (「book」, 2), (「my」, 1), (「flight」, 1), (「I」, 1), (「will」, 1), (「read」, 1), (「this」, 1)帶有POS的標籤 – (「book_VB」, 1), (「my_PRP$」, 1), (「flight_NN」, 1), (「I_PRP」, 1), (「will_MD」, 1), (「read_VB」, 1), (「this_DT」, 1), (「book_NN」, 1)
C. 規範化和詞形歸併(Lemmatizatio):詞性標籤是將詞轉化為其基本形式(引理)的基礎
D. 高效移除停止詞:詞性標籤在移除停止詞方面也非常有用。
例如,有一些標籤總是定義低頻/較低重要性的辭彙。
例如:(IN – 「within」, 「upon」, 「except」), (CD – 「one」,」two」, 「hundred」), (MD – 「may」, 「must」 等)
實體提取(實體作為特徵)
實體(entity)被定義為句中最重要的部分——名詞短語、動詞短語或兩者都有。實體檢測演算法通常是由基於規則的解析、詞典查詢、詞性標籤和依存分析組合起來的模型。實體檢測的適用性很廣泛,在自動聊天機器人、內容分析器和消費者見解中都有應用。
主題建模和命名實體識別是自然語言處理領域中兩種關鍵的實體檢測方法。
A. 命名實體識別(NER/Named Entity Recognition)
從文本中檢測命名實體比如人名、位置、公司名稱等的過程叫做命名實體識別(NER)。例如:
句 - Sergey Brin, the manager of Google Inc. is walking in the streets of New York.命名實體 - ( 「人」 : 「Sergey Brin」 ), (「公司名」 : 「Google Inc.」), (「位置」 : 「New York」)典型NER模型包含三個模塊:
名詞短語識別:使用從屬關係分析和詞性分析將所有名詞性短語從文本中提取出來。
短語分類:將提取出的名詞短語分類到各自的目錄(位置,名稱等)中。谷歌地圖API提供了通往消除歧義位置的很好路徑。然後,dbpedia,維基百科的開源資料庫可以用來識別人名或公司名。除了這個,我們能通過結合不同來源的信息精確的查找表和詞典。
實體消歧:有些時候實體可能會誤分類,因此在結果層上建一層交叉驗證層非常有用。知識圖譜就可以用來使用。目前流行的知識圖譜有:谷歌知識圖譜、IBM Watson 和維基百科。
B.主題建模
主題建模是自動識別文本集中主題的過程,它以無監督的方式從語料庫中的辭彙里提取隱藏的模式。主題(topic)被定義為「文本集中共同出現術語的重複模式」。一個好的主題模型能對「健康」、「醫生」、「病人」、「醫院」建模為「健康保健」,「農場」、「作物」、「小麥」建模為「耕作」。
隱含狄利克雷分布(LDA)是最流行的主題建模技術,以下是在Python環境下使用LDA技術實現主題建模的代碼。若想查看更詳細的細節,請參看:https://www.analyticsvidhya.com/blog/2016/08/beginners-guide-to-topic-modeling-in-python/
```
doc1 = "Sugar is bad to consume. My sister likes to have sugar, but not my father."
doc2 = "My father spends a lot of time driving my sister around to dance practice."
doc3 = "Doctors suggest that driving may cause increased stress and blood pressure."
doc_complete = [doc1, doc2, doc3]
doc_clean = [doc.split() for doc in doc_complete]
import gensim from gensim
import corpora
# Creating the term dictionary of our corpus, where every unique term is assigned an index.
dictionary = corpora.Dictionary(doc_clean)
# Converting list of documents (corpus) into Document Term Matrix using dictionary prepared above.
doc_term_matrix = [dictionary.doc2bow(doc) for doc in doc_clean]
# Creating the object for LDA model using gensim library
Lda = gensim.models.ldamodel.LdaModel
# Running and Training LDA model on the document term matrix
ldamodel = Lda(doc_term_matrix, num_topics=3, id2word = dictionary, passes=50)
# Results
print(ldamodel.print_topics())
```
C.N-Grams 特徵
N-Grams是指N個辭彙的結合體。N-Grams(N>1)作為特徵與辭彙(Unigrams)作為特徵相比,通常會更加富含信息。同時,bigrams(N=2)被認為是最重要的特徵。以下代碼生成了文本的 bigrams。
```
def generate_ngrams(text, n):
words = text.split()
output = []
for i in range(len(words)-n+1):
output.append(words[i:i+n])
return output
>>> generate_ngrams("this is a sample text", 2)
# [["this", "is"], ["is", "a"], ["a", "sample"], , ["sample", "text"]]
```
統計特徵
文本數據使用該節所講的幾種技術可直接量化成數字。
A. 術語頻率 - 逆文獻頻率(TF – IDF)
TF-IDF 是經常被使用在信息檢索問題上的權重模型。TF-IDF在不考慮文獻中詞的具體位置情況下,基於文獻中出現的辭彙將文本文獻轉化成向量模型。例如,假設有一個N 個文本文獻的數據集,在任何一個文獻「D」中,TF和IDF會被定義為 - 術語頻率(TF) - 術語「t」的術語頻率被定義為「t」在文獻「D」中的數量。
逆文獻頻率(IDF)- 術語的逆文獻頻率被定義為文本集中可用文獻的數量與包含術語「t」的文獻的數量的比例的對數。
TF-IDF公式給出了文本集中術語的相對重要性,以下為TF-IDF公式和使用Python的scikit學習包將文本轉換為tf-idf向量。
```
from sklearn.feature_extraction.text import TfidfVectorizer
obj = TfidfVectorizer()
corpus = ["This is sample document.", "another random document.", "third sample document text"]
X = obj.fit_transform(corpus)
print X
>>>
(0, 1) 0.345205016865
(0, 4) ... 0.444514311537
(2, 1) 0.345205016865
(2, 4) 0.444514311537
```
模型創建了一個詞典並給每一個辭彙賦了一個索引。輸出的每一行包含了一個元組(i,j)和在第i篇文獻索引j處辭彙的tf-idf值。
B. 數量/密度/可讀性特徵
基於數量或密度的特徵同樣也能被用於模型和分析中。這些特徵可能看起來比較繁瑣但是對學習模型有非常大的影響。一些特徵有:詞數、句數、標點符號數和特定行業辭彙的數量。其他類型的測量還包括可讀性測量(比如音節數量、smog index 和易讀性指數)。參考 Textstat 庫創建這樣的特徵:https://github.com/shivam5992/textstat
詞嵌入(文本向量)
詞嵌入是將詞表示為向量的方法,在盡量保存文本相似性的基礎上將高維的詞特徵向量映射為低維特徵向量。詞嵌入廣泛用於深度學習領域,例如卷積神經網路和循環神經網路。Word2Vec和GloVe是目前非常流行的兩種做詞嵌入的開源工具包,都是將文本轉化為對應的向量。
Word2Vec:https://code.google.com/archive/p/word2vec/
GloVe:http://nlp.stanford.edu/projects/glove/
Word2Vec是由預處理模塊和兩個淺層神經網路(CBOW/Continuous Bag of Words和Skip-gram)組成,這些模型廣泛用於自然語言處理問題。Word2Vec首先從訓練語料庫中組織辭彙,然後將辭彙做詞嵌入,得到對應的文本向量。下面的代碼是利用gensim包實現詞嵌入表示。
```
from gensim.models import Word2Vec
sentences = [["data", "science"], ["vidhya", "science", "data", "analytics"],["machine", "learning"], ["deep", "learning"]]
# train the model on your corpus
model = Word2Vec(sentences, min_count = 1)
print model.similarity("data", "science")
>>> 0.11222489293
print model["learning"]
>>> array([ 0.00459356 0.00303564 -0.00467622 0.00209638, ...])
```
這些向量作為機器學習的特徵向量,然後利用餘弦相似性、單詞聚類、文本分類等方法來衡量文本的相似性。
※入門書籍:《終極演算法》的簡介與深思
※怎樣使用PyTorch實現遞歸神經網路?
※ICLR 2017即將開幕,機器之心帶你概覽論文全貌
※圖像分割的卷積神經網路:從R-CNN到Mark R-CNN
※FB ICLR 2017研究成果概述,對話研究的創新與優勢
TAG:機器之心 |
※工筆畫背景的肌理處理技法
※什麼是自然語言處理
※自然語言處理最新教材開放下載,喬治亞理工大學官方推薦
※自然語言處理應用和前沿技術回顧
※電影影評的自然語言處理方法介紹
※固體廢物處理技術
※清華與中國工程院知識智能聯合實驗室「自然語言處理研究報告」
※談篆刻中篆法的處理
※沙龍·阿里文娛AKOL-自然語言處理技術應用實踐
※特體服裝的結構處理
※文本處理技巧:移除和提取
※頭髮的處理技巧
※5分鐘學習自然語言處理
※高情商的處理辦法
※AWS自然語言處理服務新功能!從複雜文本中提取內容並客制化分類
※自然語言處理全家福:縱覽當前NLP中的任務、數據、模型與論文
※英特爾開源用於自然語言處理的庫,為會話智能體研究提供便利
※大理石拼花的補膠、無縫化處理工藝流程
※自然語言處理,其樂無窮!
※自然語言處理助力解決社會工程攻擊問題