在本章中,我們將學(xué)習(xí)如何開(kāi)始使用自然語(yǔ)言工具包(軟件包)。
前提條件
如果想用自然語(yǔ)言處理來(lái)構(gòu)建應(yīng)用程序,那么上下文中的變化就會(huì)使其變得非常困難。 語(yǔ)境因素影響機(jī)器如何理解特定句子。 因此,我們需要通過(guò)使用機(jī)器學(xué)習(xí)方法來(lái)開(kāi)發(fā)自然語(yǔ)言應(yīng)用程序,以便機(jī)器也能夠理解人類可以理解上下文的方式。
要構(gòu)建這樣的應(yīng)用程序,我們將使用名為NLTK(自然語(yǔ)言工具包包)的Python包。
在使用之前需要安裝NLTK,它可以在以下命令來(lái)安裝 -
pip install nltk
要為NLTK構(gòu)建conda包,請(qǐng)使用以下命令 -
conda install -c anaconda nltk
現(xiàn)在安裝NLTK包后,需要通過(guò)python命令提示符導(dǎo)入。通過(guò)在Python命令提示符下編寫以下命令來(lái)導(dǎo)入它 -
>>> import nltk
下載NLTK的數(shù)據(jù)
現(xiàn)在導(dǎo)入NLTK后,我們還需要下載所需的數(shù)據(jù)。 它可以在Python命令提示符下通過(guò)以下命令完成 -
>>> nltk.download()
安裝其他必需的軟件包
為了使用NLTK構(gòu)建自然語(yǔ)言處理應(yīng)用程序,需要安裝必要的軟件包。如下 -
gensim
它是一個(gè)強(qiáng)大的語(yǔ)義建模庫(kù),對(duì)許多應(yīng)用程序很有用??梢酝ㄟ^(guò)執(zhí)行以下命令來(lái)安裝它 -
pip install gensim
pattern
它用于使gensim包正常工作??梢酝ㄟ^(guò)執(zhí)行以下命令來(lái)安裝它 -
pip install pattern
在本節(jié)中,我們將了解什么是標(biāo)記化,詞干化和詞形化。
它可以被定義為將給定文本即字符序列分成稱為令牌的較小單元的過(guò)程。令牌可以是單詞,數(shù)字或標(biāo)點(diǎn)符號(hào)。 它也被稱為分詞。 以下是標(biāo)記化的一個(gè)簡(jiǎn)單示例 -
輸入 - 芒果,香蕉,菠蘿和蘋果都是水果。
輸出 -

打斷給定文本的過(guò)程可以通過(guò)查找單詞邊界來(lái)完成。 單詞的結(jié)尾和新單詞的開(kāi)頭稱為單詞邊界。 文字的書(shū)寫體系和印刷結(jié)構(gòu)會(huì)影響邊界。
在Python NLTK模塊中,有與標(biāo)記化有關(guān)的不同包,可以根據(jù)需要將文本劃分為標(biāo)記。 一些軟件包如下所示 -
sent_tokenize包
顧名思義,這個(gè)軟件包會(huì)將輸入文本分成幾個(gè)句子。 可以使用下面的Python代碼導(dǎo)入這個(gè)包 -
from nltk.tokenize import sent_tokenize
word_tokenize包
這個(gè)包將輸入文本分成單詞??梢允褂孟旅娴腜ython代碼來(lái)導(dǎo)入這個(gè)包 -
from nltk.tokenize import word_tokenize
WordPuncttokenizer包
這個(gè)包將輸入文本分成單詞和標(biāo)點(diǎn)符號(hào)??梢允褂孟旅娴腜ython代碼來(lái)導(dǎo)入這個(gè)包 -
from nltk.tokenize import WordPuncttokenizer
在處理文字時(shí),由于語(yǔ)法原因,我們遇到了很多變化。 這里的變化的概念意味著必須處理像:democracy, democratic 和 democratization 等不同形式的相同詞匯。機(jī)器非常需要理解這些不同的單詞具有相同的基本形式。 通過(guò)這種方式,在分析文本的同時(shí)提取單詞的基本形式將會(huì)很有用。
我們可以通過(guò)阻止來(lái)實(shí)現(xiàn)這一點(diǎn)。 通過(guò)這種方式,可以說(shuō)干擾是通過(guò)切斷單詞的結(jié)尾來(lái)提取單詞基本形式的啟發(fā)式過(guò)程。
在Python NLTK模塊中,有一些與stemming相關(guān)的其它包。 這些包可以用來(lái)獲取單詞的基本形式。 這些軟件包使用算法。 一些軟件包如下所示 -
PorterStemmer包
這個(gè)Python包使用Porter算法來(lái)提取基礎(chǔ)表單。可以使用下面的Python代碼來(lái)這個(gè)包 -
from nltk.stem.porter import PorterStemmer
例如,如果將writing這個(gè)詞作為這個(gè)詞干的輸入,它們就會(huì)在詞干之后得到write這個(gè)詞。
LancasterStemmer包
這個(gè)Python包將使用Lancaster的算法來(lái)提取基本形式。 可以使用下面的Python代碼來(lái)導(dǎo)入這個(gè)包 -
from nltk.stem.lancaster import LancasterStemmer
例如,如果將writing這個(gè)詞作為這個(gè)詞干的輸入,它們就會(huì)在詞干之后得到write這個(gè)詞。
SnowballStemmer包
這個(gè)Python包將使用雪球算法來(lái)提取基本形式。 可以使用下面的Python代碼來(lái)導(dǎo)入這個(gè)包 -
from nltk.stem.snowball import SnowballStemmer
例如,如果將writing這個(gè)詞作為這個(gè)詞干的輸入,它們就會(huì)在詞干之后得到write這個(gè)詞。
所有這些算法都有不同程度的嚴(yán)格性。 如果比較這三個(gè)詞干的話,那么波特詞干是最不嚴(yán)格的,蘭卡斯特詞干是最嚴(yán)格的。 雪球詞干在速度和嚴(yán)格性方面都很好用。
詞形還原
也可以通過(guò)詞形化來(lái)提取單詞的基本形式。 它基本上通過(guò)使用詞匯的詞匯和形態(tài)分析來(lái)完成這項(xiàng)任務(wù),通常旨在僅刪除變?cè)Y(jié)尾。 任何單詞的這種基本形式都稱為引理。
詞干化和詞性化的主要區(qū)別在于詞匯的使用和形態(tài)分析。 另一個(gè)區(qū)別是,詞干最常見(jiàn)的是崩潰派生相關(guān)的詞匯,而詞素化通常只會(huì)折攏引理的不同的折點(diǎn)形式。 例如,如果提供單詞saw作為輸入詞,那么詞干可能會(huì)返回單詞's',但詞形化會(huì)嘗試返回單詞,看看或看到取決于使用該單詞是動(dòng)詞還是名詞。
在Python NLTK模塊中,有以下與詞形化過(guò)程有關(guān)的包,可以使用它來(lái)獲取詞的基本形式 -
WordNetLemmatizer包
這個(gè)Python包將提取單詞的基本形式,取決于它是用作名詞還是動(dòng)詞。 可以使用下面的Python代碼的來(lái)導(dǎo)入這個(gè)包 -
from nltk.stem import WordNetLemmatizer
它是自然語(yǔ)言處理中的重要過(guò)程之一。 分塊的主要工作是識(shí)別詞類和短語(yǔ),如名詞短語(yǔ)。 我們已經(jīng)研究了令牌化的過(guò)程,即令牌的創(chuàng)建。 分塊基本上就是這些令牌的標(biāo)簽。 換句話說(shuō),組塊會(huì)告訴我們句子的結(jié)構(gòu)。
在下面的章節(jié)中,我們將學(xué)習(xí)不同類型的分塊。
有兩種類型的組塊。 類型如下 -
上分塊
在這個(gè)組塊過(guò)程中,對(duì)象,事物等向更普遍的方向發(fā)展,語(yǔ)言變得更加抽象。 有更多的協(xié)議機(jī)會(huì)。 在這個(gè)過(guò)程中縮小。 例如,如果將“汽車是為了什么目的”這個(gè)問(wèn)題大肆渲染?我們可能會(huì)得到答案是:“運(yùn)輸”。
下分塊
在這個(gè)組塊過(guò)程中,對(duì)象,事物等朝著更具體的方向發(fā)展,語(yǔ)言更加滲透。 更深層次的結(jié)構(gòu)將進(jìn)行仔細(xì)檢查。 在這個(gè)過(guò)程中會(huì)放大。例如,如果將“專門講述一輛汽車”這個(gè)問(wèn)題歸納起來(lái)? 會(huì)得到關(guān)于汽車的更小的信息。
示例
在這個(gè)例子中,我們將通過(guò)使用Python中的NLTK模塊來(lái)進(jìn)行Noun-Phrase chunking,這是一種chunking類別,它可以在句子中找到名詞短語(yǔ)塊,
在python中執(zhí)行這些步驟來(lái)實(shí)現(xiàn)名詞短語(yǔ)分塊 -
第1步 - 在這一步中,需要定義分塊的語(yǔ)法。 它將包含需要遵循的規(guī)則。
第2步 - 在這一步中,需要?jiǎng)?chuàng)建一個(gè)塊解析器。 它會(huì)解析語(yǔ)法并給出結(jié)果。
第3步 - 在最后一步中,輸出以樹(shù)格式生成。
按照以下步驟導(dǎo)入必要的NLTK包 -
import nltk
現(xiàn)在,我們需要定義這個(gè)句子。 這里,DT表示行列式,VBP表示動(dòng)詞,JJ表示形容詞,IN表示介詞,NN表示名詞。
sentence=[("a","DT"),("clever","JJ"),("fox","NN"),("was","VBP"),
("jumping","VBP"),("over","IN"),("the","DT"),("wall","NN")]
現(xiàn)在,我們需要給出語(yǔ)法。 在這里以正則表達(dá)式的形式給出語(yǔ)法。
grammar = "NP:{<DT>?<JJ>*<NN>}"
我們需要定義一個(gè)解析器來(lái)解析語(yǔ)法。
parser_chunking = nltk.RegexpParser(grammar)
解析器解析該句子如下 -
parser_chunking.parse(sentence)
接下來(lái),需要獲得輸出。 輸出在名為output_chunk的變量中生成。
Output_chunk = parser_chunking.parse(sentence)
執(zhí)行以下代碼后,以樹(shù)的形式繪制輸出結(jié)果。
output.draw()
執(zhí)行上面代碼,得到以下結(jié)果 -

詞袋 - 英文為:Bag of Word(BoW) ,它是自然語(yǔ)言處理中的一個(gè)模型,基本上用于從文本中提取特征,以便文本可用于建模,以便在機(jī)器學(xué)習(xí)算法中使用。
現(xiàn)在問(wèn)題出現(xiàn)了,為什么我們需要從文本中提取特征。 這是因?yàn)闄C(jī)器學(xué)習(xí)算法不能處理原始數(shù)據(jù),他們需要數(shù)字?jǐn)?shù)據(jù),以便可以從中提取有意義的信息。 將文本數(shù)據(jù)轉(zhuǎn)換為數(shù)字?jǐn)?shù)據(jù)稱為特征提取或特征編碼。
它是怎么運(yùn)行的
這是從文本中提取特征的非常簡(jiǎn)單的方法。 假設(shè)我們有一個(gè)文本文檔,并且希望將其轉(zhuǎn)換為數(shù)字?jǐn)?shù)據(jù)或者說(shuō)想從中提取特征,那么首先這個(gè)模型從文檔中的所有單詞中提取詞匯。 然后通過(guò)使用文檔術(shù)語(yǔ)矩陣,它將建立一個(gè)模型。通過(guò)這種方式,BoW僅將文件表示為一袋文字。 丟棄關(guān)于文檔中單詞的順序或結(jié)構(gòu)的任何信息。
文檔術(shù)語(yǔ)矩陣的概念
BoW算法通過(guò)使用文檔術(shù)語(yǔ)矩陣來(lái)建立模型。 顧名思義,文檔術(shù)語(yǔ)矩陣就是文檔中出現(xiàn)的各種字?jǐn)?shù)的矩陣。 在這個(gè)矩陣的幫助下,文本文檔可以表示為各種單詞的加權(quán)組合。 通過(guò)設(shè)置閾值并選擇更有意義的單詞,我們可以構(gòu)建文檔中可用作特征向量的所有單詞的直方圖。 以下是了解文檔術(shù)語(yǔ)矩陣概念的示例 -
示例
假設(shè)有以下兩個(gè)句子 -
現(xiàn)在,通過(guò)考慮這兩句子,有以下13個(gè)不同的單詞 -
現(xiàn)在,我們需要使用每個(gè)句子中的單詞計(jì)數(shù)為每個(gè)句子建立一個(gè)直方圖 -
這樣,就得到了已經(jīng)提取的特征向量。每個(gè)特征向量都是13維的,因?yàn)檫@里有13個(gè)不同的單詞。
統(tǒng)計(jì)學(xué)的概念稱為TermFrequency-Inverse Document Frequency(tf-idf)。 每個(gè)單詞在文檔中都很重要。 統(tǒng)計(jì)數(shù)據(jù)有助于我們理解每個(gè)詞的重要性。
術(shù)語(yǔ)頻率(tf)
這是衡量每個(gè)單詞出現(xiàn)在文檔中的頻率。 它可以通過(guò)將每個(gè)詞的計(jì)數(shù)除以給定文檔中的詞的總數(shù)來(lái)獲得。
逆文檔頻率(idf)
這是衡量在給定的文檔集中這個(gè)文檔有多獨(dú)特的一個(gè)單詞。要計(jì)算idf和制定一個(gè)特征向量,我們需要減少像這樣的常見(jiàn)詞的權(quán)重,并權(quán)衡稀有詞。
在本節(jié)中,我們將使用CountVectorizer從這些句子中創(chuàng)建矢量來(lái)定義字符串集合。
導(dǎo)入必要的軟件包 -
from sklearn.feature_extraction.text import CountVectorizer
現(xiàn)在定義一組句子。
Sentences = ['We are using the Bag of Word model', 'Bag of Word model is
used for extracting the features.']
vectorizer_count = CountVectorizer()
features_text = vectorizer.fit_transform(Sentences).todense()
print(vectorizer.vocabulary_)
上述程序生成如下所示的輸出。它表明在上述兩句話中有13個(gè)不同的單詞 -
{'we': 11, 'are': 0, 'using': 10, 'the': 8, 'bag': 1, 'of': 7,
'word': 12, 'model': 6, 'is': 5, 'used': 9, 'for': 4, 'extracting': 2, 'features': 3}
這些是可以用于機(jī)器學(xué)習(xí)的特征向量(文本到數(shù)字形式)。
在本節(jié)中,我們將解決一些相關(guān)問(wèn)題。
類別預(yù)測(cè)
在一組文件中,不僅單詞而且單詞的類別也很重要; 在哪個(gè)類別的文本中特定的詞落入。 例如,想要預(yù)測(cè)給定的句子是否屬于電子郵件,新聞,體育,計(jì)算機(jī)等類別。在下面的示例中,我們將使用tf-idf來(lái)制定特征向量來(lái)查找文檔的類別。使用sklearn的20個(gè)新聞組數(shù)據(jù)集中的數(shù)據(jù)。
導(dǎo)入必要的軟件包 -
from sklearn.datasets import fetch_20newsgroups
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
定義分類圖。使用五個(gè)不同的類別,分別是宗教,汽車,體育,電子和空間。
category_map = {'talk.religion.misc':'Religion','rec.autos''Autos',
'rec.sport.hockey':'Hockey','sci.electronics':'Electronics', 'sci.space': 'Space'}
創(chuàng)建訓(xùn)練集 -
training_data = fetch_20newsgroups(subset = 'train',
categories = category_map.keys(), shuffle = True, random_state = 5)
構(gòu)建一個(gè)向量計(jì)數(shù)器并提取術(shù)語(yǔ)計(jì)數(shù) -
vectorizer_count = CountVectorizer()
train_tc = vectorizer_count.fit_transform(training_data.data)
print("\nDimensions of training data:", train_tc.shape)
tf-idf轉(zhuǎn)換器的創(chuàng)建過(guò)程如下 -
tfidf = TfidfTransformer()
train_tfidf = tfidf.fit_transform(train_tc)
現(xiàn)在,定義測(cè)試數(shù)據(jù) -
input_data = [
'Discovery was a space shuttle',
'Hindu, Christian, Sikh all are religions',
'We must have to drive safely',
'Puck is a disk made of rubber',
'Television, Microwave, Refrigrated all uses electricity'
]
以上數(shù)據(jù)將用于訓(xùn)練一個(gè)Multinomial樸素貝葉斯分類器 -
classifier = MultinomialNB().fit(train_tfidf, training_data.target)
使用計(jì)數(shù)向量化器轉(zhuǎn)換輸入數(shù)據(jù) -
input_tc = vectorizer_count.transform(input_data)
現(xiàn)在,將使用tfidf轉(zhuǎn)換器來(lái)轉(zhuǎn)換矢量化數(shù)據(jù) -
input_tfidf = tfidf.transform(input_tc)
執(zhí)行上面代碼,將預(yù)測(cè)輸出類別 -
predictions = classifier.predict(input_tfidf)
輸出結(jié)果如下 -
for sent, category in zip(input_data, predictions):
print('\nInput Data:', sent, '\n Category:', \
category_map[training_data.target_names[category]])
類別預(yù)測(cè)器生成以下輸出 -
Dimensions of training data: (2755, 39297)
Input Data: Discovery was a space shuttle
Category: Space
Input Data: Hindu, Christian, Sikh all are religions
Category: Religion
Input Data: We must have to drive safely
Category: Autos
Input Data: Puck is a disk made of rubber
Category: Hockey
Input Data: Television, Microwave, Refrigrated all uses electricity
Category: Electronics
性別發(fā)現(xiàn)器
在這個(gè)問(wèn)題陳述中,將通過(guò)提供名字來(lái)訓(xùn)練分類器以找到性別(男性或女性)。 我們需要使用啟發(fā)式構(gòu)造特征向量并訓(xùn)練分類器。這里使用scikit-learn軟件包中的標(biāo)簽數(shù)據(jù)。 以下是構(gòu)建性別查找器的Python代碼 -
導(dǎo)入必要的軟件包 -
import random
from nltk import NaiveBayesClassifier
from nltk.classify import accuracy as nltk_accuracy
from nltk.corpus import names
現(xiàn)在需要從輸入字中提取最后的N個(gè)字母。 這些字母將作為功能 -
def extract_features(word, N = 2):
last_n_letters = word[-N:]
return {'feature': last_n_letters.lower()}
if __name__=='__main__':
使用NLTK中提供的標(biāo)簽名稱(男性和女性)創(chuàng)建培訓(xùn)數(shù)據(jù) -
male_list = [(name, 'male') for name in names.words('male.txt')]
female_list = [(name, 'female') for name in names.words('female.txt')]
data = (male_list + female_list)
random.seed(5)
random.shuffle(data)
現(xiàn)在,測(cè)試數(shù)據(jù)將被創(chuàng)建如下 -
namesInput = ['Rajesh', 'Gaurav', 'Swati', 'Shubha']
使用以下代碼定義用于列車和測(cè)試的樣本數(shù) -
train_sample = int(0.8 * len(data))
現(xiàn)在,需要迭代不同的長(zhǎng)度,以便可以比較精度 -
for i in range(1, 6):
print('\nNumber of end letters:', i)
features = [(extract_features(n, i), gender) for (n, gender) in data]
train_data, test_data = features[:train_sample],
features[train_sample:]
classifier = NaiveBayesClassifier.train(train_data)
分類器的準(zhǔn)確度可以計(jì)算如下 -
accuracy_classifier = round(100 * nltk_accuracy(classifier, test_data), 2)
print('Accuracy = ' + str(accuracy_classifier) + '%')
現(xiàn)在,可以預(yù)測(cè)輸出結(jié)果 -
for name in namesInput:
print(name, '==>', classifier.classify(extract_features(name, i))
上述程序?qū)⑸梢韵螺敵?-
Number of end letters: 1
Accuracy = 74.7%
Rajesh -> female
Gaurav -> male
Swati -> female
Shubha -> female
Number of end letters: 2
Accuracy = 78.79%
Rajesh -> male
Gaurav -> male
Swati -> female
Shubha -> female
Number of end letters: 3
Accuracy = 77.22%
Rajesh -> male
Gaurav -> female
Swati -> female
Shubha -> female
Number of end letters: 4
Accuracy = 69.98%
Rajesh -> female
Gaurav -> female
Swati -> female
Shubha -> female
Number of end letters: 5
Accuracy = 64.63%
Rajesh -> female
Gaurav -> female
Swati -> female
Shubha -> female
在上面的輸出中可以看到,結(jié)束字母的最大數(shù)量的準(zhǔn)確性是兩個(gè),并且隨著結(jié)束字母數(shù)量的增加而減少。
我們知道,一般而言,文檔被分組為主題。 有時(shí)需要確定文本中與特定主題相對(duì)應(yīng)的模式。 這樣做的技術(shù)稱為主題建模。 換句話說(shuō),可以說(shuō)主題建模是一種揭示給定文檔集合中抽象主題或隱藏結(jié)構(gòu)的技術(shù)。
可以在以下場(chǎng)景中使用主題建模技術(shù) -
文本分類
在主題建模的幫助下,分類可以得到改進(jìn),因?yàn)樗鼘⑾嗨频膯卧~分組在一起,而不是分別將每個(gè)單詞用作特征。
推薦系統(tǒng)
在主題建模的幫助下,可以使用相似性度量來(lái)構(gòu)建推薦系統(tǒng)。
主題建??梢酝ㄟ^(guò)使用算法來(lái)實(shí)現(xiàn)。 算法如下 -
潛在狄利克雷分配(LDA)
該算法是主題建模中最流行的算法。 它使用概率圖形模型來(lái)實(shí)現(xiàn)主題建模。 我們需要在Python中導(dǎo)入gensim包以使用LDA slgorithm。
潛在語(yǔ)義分析(LDA)或潛在語(yǔ)義索引(LSI)
該算法基于線性代數(shù)。 基本上它在文檔術(shù)語(yǔ)矩陣上使用SVD(奇異值分解)的概念。
非負(fù)矩陣分解(NMF)
它也基于線性代數(shù)。
上述所有用于話題建模的算法都將主題數(shù)量作為參數(shù),將文檔 - 詞匯矩陣作為輸入,將WTM(詞主題矩陣)和TDM(主題文檔矩陣)作為輸出。