用Python進行自然語言處理(第一章)
搜尋文本
text1.concordance("monstrous")#搜尋文章中的詞語
text3.concordance("lived")
text1.similar("monstrous")#近義詞
text2.common_contexts(["monstrous","very"])#兩個詞共同的上下文
text4.dispersion_plot(['citizens','democracy','freedom','duties','America'])#該函數需要依賴numpy和matplotlib庫
計數詞彙
set(text3)#text3中所有标點,單詞的集合,去重
sorted(set(text3))#text3中的所有标點、單詞排序之後,去重
len(set(text3))#text3的獨一無二的标點、單詞類型個數,稱為唯一項目類型
print(len(text3) / len(set(text3)))#每個字平均被使用的次數
print(text3.count("smote"))#統計一個詞語在一個文本中出現的次數
print(100 * text4.count('a') / len(text4))#'統計一個詞語占全部詞語的百分比是多少
函數
def關鍵字定義,lexical_diversity為函數名,text為參數
def lexical_diversity(text):
return len(text) / len(set(text))
print(lexical_diversity(text3));
def percentage(count, total):
return 100 * count / total
将文本當作詞連結清單
a = ['Call','me','Ishmael','.']
print(a[1])#索引是從0開始的
print(text4[173]);#找到索引處的元素
print(text4.index('awaken'));#找到元素第一次出現的索引
print(text5[16715:16735])#擷取連結清單中任意片段中的元素
sent = ['word1','word2','word3','word4','word5','word6','word7','word8','word9','word10'];
print(sent[5:8])#sent[m:n] m:n-1 m represents index
print(sent[:3])#from the first to index 3(exclude index3)
print(sent[3:])#from index3 to the end
sent[0] = 'First'#replace 'word1' to 'First'
sent[1:9] = ['First','Last']#replace index 1~index 9 to the designated two words
變量
#assignment(指派):variation = expression ,words ahead ,numbers and '_' is permitted
my_sent = ['a','wwe','eee']
noun = my_sent[0:3]
print(sorted(noun))#capital is ahead of lowercase
字元串
#operation on character string
a = 'Monty'
print(a[0])#'M'
print(a[:4])#'Mont'
#connect character string
print(''.join(['Monty','Python','asd']))
#split two character string
print('Monty Pytho n'.split())
統計分布
找出文本中最常見的50個詞
fdist = FreqDist(text1)
vocabulary = fdist.keys()
voc = list(vocabulary)#必須得轉換成list才能用
print(fdist)#print the number of words
print(voc[:50])#分片前50個
print(fdist['whale'])#the number of 'whale'
fdist.plot(50,cumulative = True)#畫出圖案,需要安裝pyqt
找出text1中長度超過15個字元的詞并排序
V = set(text1)
long_words = [w for w in V if len(w) > 15]
print(sorted(long_words))
找出長度超過7個字元并且出現次數超過7次的詞
fdist5 = FreqDist(text5)
print(sorted([w for w in set(text5) if len(w) > 7 and fdist5[w] > 7]))
搭配:經常出現的詞的序列,詞對、雙連詞:找到在一起出現的兩個詞
print(bigrams(['more','is','said','than','done']))#找詞對,有問題
text4.collocations()#找到出現頻繁的雙連詞
輸出text1中每個詞的長度
print([len(w) for w in text1])
文本中的詞的長度的性質統計
fdist = FreqDist(len(w) for w in text1)#FreqDist計數連結清單中每個長度出現的次數
print(fdist.keys())#輸出的是包含的元素的不同詞長
print(fdist.items())#以(a,b)輸出a長度的詞出現了b次
print(fdist.max())#輸出出現次數最多的長度
print(fdist[3])#輸出長度為3的詞出現的次數
print(fdist.freq(3))#輸出長度為3的詞出現的次數占總詞數的比例
print(fdist.N())#輸出樣本總數
fdist.plot()#繪制頻率分布圖
fdist.plot(cumulative=True)#繪制累積頻率分布圖
決策
[w for w in sent7 if len(w) < 4]#輸出sent7中長度小于4的元素
sorted([w for w in set(text1) if w.endswith('ableness')])#輸出以ableness結尾的單詞并排序
s.startswith(t) #測試s是否以t開頭
s.endswith(t) #測試s是否以t結尾
t in s #測試s是否包含t
s.islower() #測試s中所有字元是否都是小寫字母
s.isupper() #測試 s 中所有字元是否都是大寫字母
s.isalpha() #測試 s 中所有字元是否都是字母
s.isalnum() #測試 s 中所有字元是否都是字母或數字
s.isdigit() #測試 s 中所有字元是否都是數字
s.istitle() #測試 s 是否首字母大寫(s 中所有的詞都首字母大寫)
控制
對每個元素進行操作
[len(w)for w in text1]
[w.upper()for w in text1]
#這些表達式形式為[f(w) for ...]或[w.f() for ...],其中 f是一個函數,用來計算詞長或把字母轉換為大寫
len(set(word.lower()for word in text1))#由于我們不重複計算像This和this這樣僅僅大小寫不同的詞,就已經從詞彙表計數中抹去了2,000個!
len(set(word.lower()for word in text1 if word.isalpha()))#通過過濾掉所有非字母元素,從詞彙表中消除數字和标點符号
嵌套代碼塊
控制結構:
if len(word) < 5:#(注意冒号)
print('word length is less than 5')#注意段首空tab
...#該行空出來,再下一行輸出
#如果不滿足if成立條件,沒有輸出
for word in ['Call','me','Ishmael','.']:
print(word)
...#空一行,下一行輸出
sent1 = ['Call','me','Ishmael','.']
for word in sent1:
if word.endswith('l'):
print(word)
...
Call
Ishmael
#在 if 和for語句所在行末尾——縮進開始之前——有一個冒号
#所有的Python控制結構都以冒号結尾。冒号表示目前語句與後面的縮進塊有關聯。
for token in sent1:
... if token.islower():
... print(token,'is a lowercase word')
... elif token.istitle():
... print(token,'is a titlecase word')
... else :
... print (token,'is punctuation')
...
Call is a titlecase word
me is a lowercase word
Ishmael is a titlecase word
. is punctuation
tricky = sorted([w for w in set(text2) if 'cei' in w or 'cie' in w])
for word in tricky:
... print(word)
...
關于NLP-自動了解自然語言
詞意消歧
我們要算出特定上下文中的詞被賦予的是哪個意思
自動消除歧義需要使用上下文,利用相鄰詞彙有相近含義這樣一個簡單的事實
指代消解
一種更深刻的語言了解是解決“誰對誰做了什麼”,即檢測主語和動詞的賓語
a. The thieves stole the paintings. They were subsequently sold .b. The thieves stole the paintings. They were subsequently caught .c. The thieves stole the paintings. They were subsequently found .要回答這個問題涉及到尋找代詞they的先行詞thieves或者paintings。處理這個問題的計算技術包括指代消解(anaphora resolution)——确定代詞或名詞短語指的是什麼——和語義角色标注(semantic role labeling)——确定名詞短語如何與動詞相關聯(如施事,受事,工具等)。
自動生成語言
如果我們能夠解決自動語言了解等問題,我們将能夠繼續那些包含自動生成語言的任務,如自動問答和機器翻譯。在自動問答中,一台機器要能夠回答使用者關于特定文本集的問題:
a.Text : ... The thieves stole the paintings. They were subsequently sold. ...b.Human : Who or what was sold?c.Machine : The paintings. 機器的回答表明,它已經正确的計算出they是指paintings,而不是thieves。在機器翻譯中,機器要能夠把文本翻譯成另一種語言文字,并準确傳達原文的意思。正确的翻譯實際上取決于對代詞的正确了解。所有這些例子中,弄清楚詞的含義、動作的主語以及代詞的先行詞是了解句子含義的步驟,也是我們希望語言了解系統能夠做到的事情。
機器翻譯
長久以來,機器翻譯(MT)都是語言了解的聖杯,人們希望能找到從根本上提供高品質的符合語言習慣的任意兩種語言之間的翻譯。其曆史可以追溯到冷戰初期,當時自動翻譯的許諾帶來大量的政府贊助,它也是NLP本身的起源。
今天,特定語言之間實用的翻譯系統已經存在,有些已經內建到搜尋引擎中了。但是,這些系統有一些嚴重的缺點,例如babelize_shell() 該函數在nltk3.0中已經不再可用機器翻譯是困難的,因為一個給定的詞可能有幾種不同的解釋(取決于它的意思),也因為必須改變詞序才能與目智語言的文法結構保持一緻。今天,這些困難遇到新情況,從 聞和政府網站釋出的兩種或兩種以上的語言文檔中可以收集到大量的相似文本。給出一個德文和英文雙語的文檔或者一個雙語詞典,我們就可以自動配對組成句子,這個過程叫做文本對齊。一旦我們有一百萬或更多的句子對,就可以檢測出相應的詞和短語,并建立一個能用來翻譯新文本的模型。
人機對話系統
在人工智能的曆史,主要的智能測試是一個語言學測試,叫做圖靈測試:一個響應使用者文本輸入的對話系統能否表現的自然到我們無法區分它是人工生成的響應?相比之下,今天的商業對話系統能力是非常有限的,但在較小的給定領域仍然有些作用
S: How may I help you?U: When is Saving Private Ryan playing? S: For what theater? U: The Paramount theater. S: Saving Private Ryan is not playing at the Paramount theater, but it’s playing at the Madison theater at 3:00, 5:30, 8:00, and 10:30.你不能要求這個系統提供駕駛訓示或附近餐館的細節,除非所需的資訊已經被儲存并且合适的問題答案對已經被納入語言處理系統。 請看,這個系統似乎了解使用者的目标:使用者詢問電影上映的時間,系統正确的判斷出使用者是想要看電影。這一推斷看起來如此明顯,你可能都沒有注意到它,一個自然語言系統需要被賦予這種自然的互動能力。沒有它,當問到:“ 你知道拯救大兵瑞恩什麼時候上映? ”時,系統可能隻會回答一個冷冷的毫無用處的“ 是的 ”。然而,商業對話系統的開發者使用上下文語境假設和業務邏輯確定在使用者以不同方式表達需求或提供資訊時對特定應用都能有效處理。是以,如果你輸入 When is ...或者 I want to know when ...或者Can you tell me whe n ...時,這些簡單的規則總是對應着放映時間,這就足夠系統提供有益的服務了。舉例:原始的對話系統import nltknltk.chat.chatbots()Which chatbot would you like to talk to? 1: Eliza (psycho-babble) 2: Iesha (teen anime junky) 3: Rude (abusive bot) 4: Suntsu (Chinese sayings) 5: Zen (gems of wisdom)
Enter a number in the range 1-5: Error: bad chatbot number
Enter a number in the range 1-5: 1
文本的含義
近年來,一個叫做文本含義識别(Recognizing Textual Entailment 簡稱 RTE)的公開的“共享任務”使語言了解所面臨的挑戰成為關注焦點。基本情形很簡單:假設你想找到證據來支援一個假設:Sandra Goudie 被Max Purnell擊敗了。而你有一段簡短的文字似乎是有關的, 例如:Sandra Goudie 在2002 年國會選舉首次當選,通過擊敗工黨候選人 Max Purnell 将現 任綠黨下院議員 Jeanette Fitzsimons 推到第三位,以微弱優勢赢得了 Coromandel 席位。文本 是否為你接受假說提供了足夠的證據呢?在這種特殊情況下,答案是“否”。你可以很容易得 出這樣的結論,但使用自動方法做出正确決策是困難的。RTE 挑戰為競賽者開發他們的系統提供資料,但這些資料對“蠻力”機器學習技術(我們将在第 6章講述這一主題)來說是不 夠的。是以,一些語言學分析是至關重要的。在前面的例子中,很重要的一點是讓系統知道 Sandra Goudie 是假設中被擊敗的人,而不是文本中擊敗别人的人。思考下面的文本-假設對, 這是任務困難性的另一個例證:a. Text: David Golinkin is the editor or author of 18 books, and over 150 responsa, articles, sermons and books b. Hypothesis: Golinkin has written 18 books
為了确定假說是否得到文本的支援,該系統需要以下背景知識: (一)如果有人是一本書的作者,那麼他/她寫了這本書; (二)如果有人是一本書的編輯,那麼他/她(完全)沒有寫這本書; (三)如果有人是18 本書的編輯或作者,則無法斷定他/她是18 本書的作者
NLP的局限性
盡管在很多如 RTE這樣的任務中研究取得了進展,但在現實世界的應用中已經部署的語言了解系統仍不能進行常識推理或以一種一般的可靠的方式描繪這個世界的知識。我們在等待這些困難的人工智能問題得到解決的同時,接受一些在推理和知識能力上存在嚴重限制的自然語言系統是有必要的。是以,從一開始,自然語言處理研究的一個重要目标一直是使用淺顯但強大的技術代替無邊無際的知識和推理能力,促進建構“語言了解”技術的艱巨任務的不斷取得進展。事實上,這是本書的目标之一,我們希望你能掌握這些知識和技能,建構有效的自然語言處理系統,并為建構智能機器這一長期的理想做出貢獻。