1. 程式人生 > >Python NLTK 自然語言處理入門與例程

Python NLTK 自然語言處理入門與例程

  • 在這篇文章中,我們將基於 Python 討論自然語言處理(NLP)。本教程將會使用 Python NLTK 庫。NLTK 是一個當下流行的,用於自然語言處理的 Python 庫。

那麼 NLP 到底是什麼?學習 NLP 能帶來什麼好處?

簡單的說,自然語言處理( NLP )就是開發能夠理解人類語言的應用程式和服務。

我們生活中經常會接觸的自然語言處理的應用,包括語音識別,語音翻譯,理解句意,理解特定詞語的同義詞,以及寫出語法正確,句意通暢的句子和段落。

NLP的作用

正如大家所知,每天部落格,社交網站和網頁會產生數億位元組的海量資料。

有很多公司熱衷收集所有這些資料,以便更好地瞭解他們的使用者和使用者對產品的熱情,並對他們的產品或者服務進行合適的調整。

這些海量資料可以揭示很多現象,打個比方說,巴西人對產品 A 感到滿意,而美國人卻對產品 B 更感興趣。通過NLP,這類的資訊可以即時獲得(即實時結果)。例如,搜尋引擎正是一種 NLP,可以在正確的時間給合適的人提供適當的結果。

但是搜尋引擎並不是自然語言處理(NLP)的唯一應用。還有更好更加精彩的應用。

NLP的應用

以下都是自然語言處理(NLP)的一些成功應用:

  • 搜尋引擎,比如谷歌,雅虎等等。谷歌等搜尋引擎會通過NLP瞭解到你是一個科技發燒友,所以它會返回科技相關的結果。
  • 社交網站資訊流,比如 Facebook 的資訊流。新聞饋送演算法通過自然語言處理了解到你的興趣,並向你展示相關的廣告以及訊息,而不是一些無關的資訊。
  • 語音助手,諸如蘋果 Siri。
  • 垃圾郵件程式,比如 Google 的垃圾郵件過濾程式 ,這不僅僅是通常會用到的普通的垃圾郵件過濾,現在,垃圾郵件過濾器會對電子郵件的內容進行分析,看看該郵件是否是垃圾郵件。

NLP庫

現在有許多開源的自然語言處理(NLP)庫。比如:

  • Natural language toolkit (NLTK)
  • Apache OpenNLP
  • Stanford NLP suite
  • Gate NLP library

自然語言工具包(NLTK)是最受歡迎的自然語言處理(NLP)庫。它是用 Python 語言編寫的,背後有強大的社群支援。

NLTK 也很容易入門,實際上,它將是你用到的最簡單的自然語言處理(NLP)庫。

在這個 NLP 教程中,我們將使用 Python NLTK 庫。在開始安裝 NLTK 之前,我假設你知道一些 Python入門知識

安裝 NLTK

如果你使用的是 Windows , Linux 或 Mac,你可以 使用PIP 安裝NLTK: # pip install nltk。

在本文撰寫之時,你可以在 Python 2.7 , 3.4 和 3.5 上都可以使用NLTK。或者可以通過獲取tar 進行原始碼安裝

要檢查 NLTK 是否正確地安裝完成,可以開啟你的Python終端並輸入以下內容:Import nltk。如果一切順利,這意味著你已經成功安裝了 NLTK 庫。

一旦你安裝了 NLTK,你可以執行下面的程式碼來安裝 NLTK 包:

import nltk
nltk.download()

這將開啟 NLTK 下載器來選擇需要安裝的軟體包。

你可以選擇安裝所有的軟體包,因為它們的容量不大,所以沒有什麼問題。現在,我們開始學習吧!

使用原生 Python 來對文字進行分詞

首先,我們將抓取一些網頁內容。然後來分析網頁文字,看看爬下來的網頁的主題是關於什麼。我們將使用 urllib模組來抓取網頁:

import urllib.request
response = urllib.request.urlopen('http://php.net/')
html = response.read()
print (html)

從列印輸出中可以看到,結果中包含許多需要清理的HTML標記。我們可以用這個 BeautifulSoup 庫來對抓取的文字進行處理:

from bs4 import BeautifulSoup
import urllib.request 
response = urllib.request.urlopen('http://php.net/') 
html = response.read()
soup = BeautifulSoup(html,"html5lib")
text = soup.get_text(strip=True)
print (text)

現在,我們能將抓取的網頁轉換為乾淨的文字。這很棒,不是麼?

最後,讓我們通過以下方法將文字分詞:

from bs4 import BeautifulSoup 
import urllib.request 
response = urllib.request.urlopen('http://php.net/') 
html = response.read() 
soup = BeautifulSoup(html,"html5lib") 
text = soup.get_text(strip=True) 
tokens = [t for t in text.split()] 
print (tokens)

詞頻統計

現在的文字相比之前的 html 文字好多了。我們再使用 Python NLTK 來計算每個詞的出現頻率。NLTK 中的FreqDist( ) 函式可以實現詞頻統計的功能 :

from bs4 import BeautifulSoup
import urllib.request
import nltk 
response = urllib.request.urlopen('http://php.net/') 
html = response.read() 
soup = BeautifulSoup(html,"html5lib") 
text = soup.get_text(strip=True) 
tokens = [t for t in text.split()] 
freq = nltk.FreqDist(tokens) 
for key,val in freq.items(): 
    print (str(key) + ':' + str(val))

如果你檢視輸出結果,會發現最常用的詞語是PHP。

你可以用繪圖函式為這些詞頻繪製一個圖形: freq.plot(20, cumulative=False)。

從圖中,你可以肯定這篇文章正在談論 PHP。這很棒!有一些詞,如"the," "of," "a," "an," 等等。這些詞是停止詞。一般來說,停止詞語應該被刪除,以防止它們影響我們的結果。

使用 NLTK 刪除停止詞

NLTK 具有大多數語言的停止詞表。要獲得英文停止詞,你可以使用以下程式碼:

from nltk.corpus import stopwords
stopwords.words('english')

現在,讓我們修改我們的程式碼,並在繪製圖形之前清理標記。首先,我們複製一個列表。然後,我們通過對列表中的標記進行遍歷並刪除其中的停止詞:

clean_tokens = tokens[:] 
sr = stopwords.words('english')
for token in tokens:
    if token in stopwords.words('english'):
        clean_tokens.remove(token)

最終的程式碼應該是這樣的:

from bs4 import BeautifulSoup 
import urllib.request 
import nltk 
from nltk.corpus import stopwords 
response = urllib.request.urlopen('http://php.net/') 
html = response.read() 
soup = BeautifulSoup(html,"html5lib") 
text = soup.get_text(strip=True) 
tokens = [t for t in text.split()] 
clean_tokens = tokens[:] 
sr = stopwords.words('english') 
for token in tokens: 
    if token in stopwords.words('english'): 
        clean_tokens.remove(token) 
freq = nltk.FreqDist(clean_tokens) 
for key,val in freq.items(): 
    print (str(key) + ':' + str(val))

如果你現在檢查圖表,會感覺比之前那張圖示更加清晰,因為沒有了停止詞的干擾。

freq.plot(20,cumulative=False)

使用 NLTK 對文字分詞

我們剛剛瞭解瞭如何使用 split( ) 函式將文字分割為標記 。現在,我們將看到如何使用 NLTK 對文字進行標記化。對文字進行標記化是很重要的,因為文字無法在沒有進行標記化的情況下被處理。標記化意味著將較大的部分分隔成更小的單元。

你可以將段落分割為句子,並根據你的需要將句子分割為單詞。NLTK 具有內建的句子標記器和詞語標記器。

假設我們有如下的示例文字:

Hello Adam, how are you? I hope everything is going well.  Today is a good day, see you dude.

為了將這個文字標記化為句子,我們可以使用句子標記器:

from nltk.tokenize import sent_tokenize 
mytext = "Hello Adam, how are you? I hope everything is going well. Today is a good day, see you dude." 
print(sent_tokenize(mytext))

輸出如下:

['Hello Adam, how are you?', 'I hope everything is going well.', 'Today is a good day, see you dude.']

你可能會說,這是一件容易的事情。我不需要使用 NLTK 標記器,並且我可以使用正則表示式來分割句子,因為每個句子前後都有標點符號或者空格。

那麼,看看下面的文字:

Hello Mr. Adam, how are you? I hope everything is going well. Today is a good day, see you dude.

呃!Mr. 是一個詞,雖然帶有一個符號。讓我們來試試使用 NLTK 進行分詞:

from nltk.tokenize import sent_tokenize 
mytext = "Hello Mr. Adam, how are you? I hope everything is going well. Today is a good day, see you dude." 
print(sent_tokenize(mytext))

輸出如下所示:

['Hello Mr. Adam, how are you?', 'I hope everything is going well.', 'Today is a good day, see you dude.']

Great!結果棒極了。然後我們嘗試使用詞語標記器來看看它是如何工作的:

from nltk.tokenize import word_tokenize
mytext = "Hello Mr. Adam, how are you? I hope everything is going well. Today is a good day, see you dude."
print(word_tokenize(mytext))

輸出如下:

['Hello', 'Mr.', 'Adam', ',', 'how', 'are', 'you', '?', 'I', 'hope', 'everything', 'is', 'going', 'well', '.', 'Today', 'is', 'a', 'good', 'day', ',', 'see', 'you', 'dude', '.']

正如所料,Mr. 是一個詞,也確實被 NLTK 當做一個詞。NLTK使用 nltk.tokenize.punkt module 中的 PunktSentenceTokenizer 進行文字分詞。這個標記器經過了良好的訓練,可以對多種語言進行分詞 。

標記非英語語言文字

為了標記其他語言,可以像這樣指定語言:

from nltk.tokenize import sent_tokenize
mytext = "Bonjour M. Adam, comment allez-vous? J'espère que tout va bien. Aujourd'hui est un bon jour."
print(sent_tokenize(mytext,"french"))

結果將是這樣的:

['Bonjour M. Adam, comment allez-vous?', "J'espère que tout va bien.", "Aujourd'hui est un bon jour."]

NLTk 對其他非英語語言的支援也非常好!

從 WordNet 獲取同義詞

如果你還記得我們使用 nltk.download( ) 安裝 NLTK 的擴充套件包時。其中一個擴充套件包名為 WordNet。WordNet 是為自然語言處理構建的資料庫。它包括部分詞語的一個同義詞組和一個簡短的定義。

通過 NLTK 你可以得到給定詞的定義和例句:

from nltk.corpus import wordnet
syn = wordnet.synsets("pain")
print(syn[0].definition())
print(syn[0].examples())

結果是:

a symptom of some physical hurt or disorder
['the patient developed severe pain and distension']

WordNet 包含了很多詞的定義:

from nltk.corpus import wordnet
syn = wordnet.synsets("NLP")
print(syn[0].definition())
syn = wordnet.synsets("Python")
print(syn[0].definition())

結果是:

the branch of information science that deals with natural language information
large Old World boas

您可以使用 WordNet 來獲得同義詞:

from nltk.corpus import wordnet 
synonyms = []
for syn in wordnet