📜  带有Python和NLTK软件包的AI

📅  最后修改于: 2020-12-11 05:40:15             🧑  作者: Mango


在本章中,我们将学习如何开始使用“自然语言工具包”。

先决条件

如果我们要使用自然语言处理来构建应用程序,那么上下文的更改将使其变得最困难。上下文因素影响机器如何理解特定句子。因此,我们需要通过使用机器学习方法来开发自然语言应用程序,以便机器也可以理解人类可以理解上下文的方式。

为了构建这样的应用程序,我们将使用称为NLTK(自然语言工具包)的Python包。

导入NLTK

我们需要在使用前安装NLTK。可以在以下命令的帮助下进行安装-

pip install nltk

要为NLTK构建conda软件包,请使用以下命令-

conda install -c anaconda nltk

现在,在安装NLTK软件包之后,我们需要通过Python命令提示符将其导入。我们可以通过在Python命令提示符下编写以下命令来导入它-

>>> import nltk

下载NLTK的数据

现在,在导入NLTK之后,我们需要下载所需的数据。可以在Python命令提示符下的以下命令的帮助下完成-

>>> nltk.download()

安装其他必需的软件包

为了使用NLTK构建自然语言处理应用程序,我们需要安装必要的软件包。软件包如下-

Gensim

它是一个健壮的语义建模库,对许多应用程序很有用。我们可以通过执行以下命令来安装它-

pip install gensim

模式

它用于使gensim程序包正常工作。我们可以通过执行以下命令来安装它

pip install pattern

标记化,词干和词法化的概念

在本节中,我们将了解什么是标记化,词干和词形化。

代币化

它可以定义为将给定文本(即字符序列)分解为称为令牌的较小单元的过程。令牌可以是单词,数字或标点符号。也称为分词。以下是令牌化的简单示例-

输入-芒果,香蕉,菠萝和苹果都是水果。

输出代币化

可以通过定位单词边界来完成破坏给定文本的过程。单词的结尾和新单词的开头称为单词边界。单词的书写系统和印刷结构会影响边界。

在Python NLTK模块中,我们有与令牌化相关的不同软件包,可根据需要将其用于将文本分为令牌。一些软件包如下-

sent_tokenize包

顾名思义,此程序包会将输入文本分为句子。我们可以在以下Python代码的帮助下导入此软件包-

from nltk.tokenize import sent_tokenize

word_tokenize软件包

该软件包将输入文本分为单词。我们可以在以下Python代码的帮助下导入此软件包-

from nltk.tokenize import word_tokenize

WordPunctTokenizer程序包

该程序包将输入文本分为单词和标点符号。我们可以在以下Python代码的帮助下导入此软件包-

from nltk.tokenize import WordPuncttokenizer

抽干

在处理单词时,由于语法原因,我们会遇到很多变化。这里的变体概念意味着我们必须应对相同形式的不同形式,例如民主,民主民主化。对于机器而言,非常有必要理解这些不同的词具有相同的基本形式。这样,在分析文本时提取单词的基本形式将很有用。

我们可以通过阻止来实现这一目标。这样,我们可以说词干是通过切掉单词的结尾来提取单词的基本形式的启发式过程。

在Python NLTK模块中,我们具有与词干相关的不同软件包。这些软件包可用于获取单词的基本形式。这些软件包使用算法。一些软件包如下-

PorterStemmer包装

该Python软件包使用Porter的算法提取基本表单。我们可以在以下Python代码的帮助下导入此软件包-

from nltk.stem.porter import PorterStemmer

举例来说,如果我们会给A€~writing’作为输入到该词干他们,我们将制止后获得A€~write’。

LancasterStemmer软件包

该Python软件包将使用Lancaster的算法提取基本表单。我们可以在以下Python代码的帮助下导入此软件包-

from nltk.stem.lancaster import LancasterStemmer

举例来说,如果我们会给A€~writing’作为输入到该词干他们,我们将制止后获得A€~write’。

SnowballStemmer包装

该Python软件包将使用snowball的算法来提取基本表单。我们可以在以下Python代码的帮助下导入此软件包-

from nltk.stem.snowball import SnowballStemmer

举例来说,如果我们会给A€~writing’作为输入到该词干他们,我们将制止后获得A€~write’。

所有这些算法都具有不同的严格程度。如果我们比较这三个词干,那么Porter词干是最不严格的,而Lancaster是最严格的。 Snowball stemmer在速度和严格性方面都很好用。

合法化

我们还可以通过词法提取词的基本形式。它基本上是通过词汇的词汇和词法分析来完成此任务的,通常仅旨在消除屈折词尾。任何单词的这种基本形式都称为引理。

词干和词根化之间的主要区别是单词的词汇和词法分析。另一个区别是,词干最通常会使与派生词相关的单词崩溃,而词根化通常只会使词缀的不同变形形式崩溃。例如,如果我们将“ saw”一词作为输入词,则词干提取可能会返回“ s”一词,但是根据词性的使用是动词还是a,词法重制会尝试返回“ see”或“ saw”一词。名词。

在Python NLTK模块中,我们有以下与词形化过程相关的软件包,可用于获取单词的基本形式-

WordNetLemmatizer程序包

这个Python软件包将提取单词的基本形式,具体取决于它是用作名词还是用作动词。我们可以在以下Python代码的帮助下导入此软件包-

from nltk.stem import WordNetLemmatizer

块:将数据分为块

它是自然语言处理中的重要过程之一。分块的主要工作是识别语音和名词短语之类的简短词组。我们已经研究了令牌化的过程,即令牌的创建。块基本上是这些令牌的标签。换句话说,分块将向我们展示句子的结构。

在以下部分中,我们将学习不同类型的Chunking。

分块的类型

有两种类型的分块。类型如下-

分块

在分块的过程中,对象,事物等朝着更加通用的方向发展,语言变得更加抽象。达成协议的机会更多。在此过程中,我们将缩小。例如,如果我们将“汽车的用途是什么?我们可能会得到答案“运输”。

分块

在分块的过程中,对象,事物等朝着更加具体的方向发展,并且语言也得到了更深入的渗透。更深层次的结构将在细分中进行检查。在此过程中,我们将进行放大。例如,如果我们将“专门讲一辆汽车”这一问题简化了?我们将获得有关汽车的较小信息。

在此示例中,我们将使用Python的NLTK模块进行名词短语分块,这是一个分块的类别,可以在句子中找到名词短语的分块-

在Python按照以下步骤实施名词短语分块-

步骤1-在此步骤中,我们需要定义用于分块的语法。它由我们需要遵循的规则组成。

步骤2-在这一步中,我们需要创建一个块解析器。它将解析语法并给出输出。

步骤3-在最后一步中,输出以树格式生成。

让我们导入必要的NLTK包,如下所示:

import nltk

现在,我们需要定义句子。在这里,DT是行列式,VBP是动词,JJ是形容词,IN是介词,NN是名词。

sentence=[("a","DT"),("clever","JJ"),("fox","NN"),("was","VBP"),
          ("jumping","VBP"),("over","IN"),("the","DT"),("wall","NN")]

现在,我们需要给出语法。在这里,我们将以正则表达式的形式给出语法。

grammar = "NP:{
?*}"

我们需要定义一个解析器来解析语法。

parser_chunking = nltk.RegexpParser(grammar)

解析器解析句子如下-

parser_chunking.parse(sentence)

接下来,我们需要获取输出。输出在名为output_chunk的简单变量中生成。

Output_chunk = parser_chunking.parse(sentence)

执行以下代码后,我们可以以树的形式绘制输出。

output.draw()

Nltk

单词袋(BoW)模型

单词袋(BoW)是自然语言处理中的模型,基本上用于从文本中提取特征,以便可以在建模中(例如在机器学习算法中)使用文本。

现在出现的问题是,为什么我们需要从文本中提取特征。这是因为机器学习算法无法处理原始数据,并且它们需要数字数据,以便可以从中提取有意义的信息。文本数据到数字数据的转换称为特征提取或特征编码。

怎么运行的

这是从文本中提取特征的非常简单的方法。假设我们有一个文本文档,我们想将其转换为数字数据,或者想从中提取特征,然后首先,该模型从文档中的所有单词中提取词汇。然后,通过使用文档术语矩阵,它将建立一个模型。这样,BoW仅将文档表示为单词包。有关文档中单词顺序或结构的任何信息都将被丢弃。

文档术语矩阵的概念

BoW算法通过使用文档术语矩阵来构建模型。顾名思义,文档术语矩阵是文档中出现的各种单词计数的矩阵。借助此矩阵,可以将文本文档表示为各个单词的加权组合。通过设置阈值并选择更有意义的词,我们可以构建文档中所有可用作特征向量的词的直方图。以下是了解文档术语矩阵概念的示例-

假设我们有以下两个句子-

  • 句子1-我们使用的是单词袋模型。

  • 句子2-单词袋模型用于提取特征。

现在,通过考虑这两个句子,我们得到以下13个不同的词-

  • 我们
  • 使用
  • 模型
  • 用过的
  • 对于
  • 提取
  • 特征

现在,我们需要通过使用每个句子中的字数为每个句子建立直方图-

  • 句子1- [1,1,1,1,1,1,1,1,0,0,0,0,0]

  • 句子2- [0,0,0,1,1,1,1,1,1,1,1,1,1,1]

这样,我们就可以提取特征向量。每个特征向量都是13维的,因为我们有13个不同的词。

统计概念

统计的概念称为TermFrequency-逆文档频率(tf-idf)。每个单词在文档中都很重要。统计数据有助于我们理解每个单词的重要性。

词频(tf)

它衡量每个单词在文档中出现的频率。可以通过将每个单词的计数除以给定文档中单词的总数来获得。

反文档频率(idf)

它是衡量单词在给定文档集中对该文档的唯一性的量度。为了计算idf并制定独特的特征向量,我们需要减少常见单词(如the)的权重并权衡稀有单词。

在NLTK中构建单词袋模型

在本节中,我们将使用CountVectorizer从这些句子创建向量来定义字符串集合。

让我们导入必要的包-

from sklearn.feature_extraction.text import CountVectorizer

现在定义句子集。

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个不同的词-

{'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}

这些是可以用于机器学习的特征向量(文本到数字形式)。

解决问题

在本节中,我们将解决一些相关问题。

类别预测

在一组文档中,不仅单词,而且单词的类别也很重要。特定单词属于哪种文本类别。例如,我们要预测给定的句子是否属于电子邮件,新闻,体育,计算机等类别。在以下示例中,我们将使用tf-idf公式化特征向量以查找文档的类别。我们将使用来自sklearn的20个新闻组数据集的数据。

我们需要导入必要的软件包-

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

定义类别图。我们使用五个不同的类别,分别是宗教,汽车,体育,电子和太空。

category_map = {'talk.religion.misc':'Religion','rec.autos''Autos',
   'rec.sport.hockey':'Hockey','sci.electronics':'Electronics', 'sci.space': 'Space'}

创建训练集-

training_data = fetch_20newsgroups(subset = 'train',
   categories = category_map.keys(), shuffle = True, random_state = 5)

构建一个计数向量器并提取计数项-

vectorizer_count = CountVectorizer()
train_tc = vectorizer_count.fit_transform(training_data.data)
print("\nDimensions of training data:", train_tc.shape)

TF-IDF变压器创建如下-

tfidf = TfidfTransformer()
train_tfidf = tfidf.fit_transform(train_tc)

现在,定义测试数据-

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'
]

以上数据将帮助我们训练多项式朴素贝叶斯分类器-

classifier = MultinomialNB().fit(train_tfidf, training_data.target)

使用计数矢量化器转换输入数据-

input_tc = vectorizer_count.transform(input_data)

现在,我们将使用tfidf转换器转换矢量化数据-

input_tfidf = tfidf.transform(input_tc)

我们将预测输出类别-

predictions = classifier.predict(input_tfidf)

输出生成如下-

for sent, category in zip(input_data, predictions):
   print('\nInput Data:', sent, '\n Category:', \
      category_map[training_data.target_names[category]])

类别预测变量生成以下输出-

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

性别搜寻器

在此问题陈述中,将训练分类器通过提供姓名来查找性别(男性或女性)。我们需要使用启发式方法来构建特征向量并训练分类器。我们将使用scikit-learn包中的标签数据。以下是构建性别查找器的Python代码-

让我们导入必要的包-

import random

from nltk import NaiveBayesClassifier
from nltk.classify import accuracy as nltk_accuracy
from nltk.corpus import names

现在我们需要从输入单词中提取最后N个字母。这些字母将充当特征-

def extract_features(word, N = 2):
   last_n_letters = word[-N:]
   return {'feature': last_n_letters.lower()}
    
if __name__=='__main__':

使用NLTK中可用的带标签的名称(男性和女性)创建训练数据-

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)

现在,测试数据将如下创建:

namesInput = ['Rajesh', 'Gaurav', 'Swati', 'Shubha']

使用以下代码定义用于训练和测试的样本数量

train_sample = int(0.8 * len(data))

现在,我们需要迭代不同的长度,以便可以比较精度-

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)

分类器的准确性可以计算如下-

accuracy_classifier = round(100 * nltk_accuracy(classifier, test_data), 2)
   print('Accuracy = ' + str(accuracy_classifier) + '%')

现在,我们可以预测输出-

for name in namesInput:
   print(name, '==>', classifier.classify(extract_features(name, i)))

上面的程序将生成以下输出-

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

在上面的输出中,我们可以看到最大结尾字母数的精度为2,并且随着结尾字母数的增加而降低。

主题建模:识别文本数据中的模式

我们知道,一般来说文件都是按主题分组的。有时我们需要识别文本中与特定主题相对应的模式。执行此操作的技术称为主题建模。换句话说,可以说主题建模是一种在给定的文档集中发现抽象主题或隐藏结构的技术。

我们可以在以下情况下使用主题建模技术-

文字分类

借助主题建模,可以改进分类,因为分类将相似的单词组合在一起,而不是将每个单词分别用作功能。

推荐系统

借助主题建模,我们可以使用相似性度量来构建推荐系统。

主题建模算法

主题建模可以通过使用算法来实现。算法如下-

潜在狄利克雷分配(LDA)

该算法在主题建模中最受欢迎。它使用概率图形模型来实现主题建模。我们需要在Python导入gensim包以使用LDA slgorithm。

潜在语义分析(LDA)或潜在语义索引(LSI)

该算法基于线性代数。基本上,它在文档术语矩阵上使用SVD(奇异值分解)的概念。

非负矩阵分解(NMF)

它也基于线性代数。

上面提到的所有用于主题建模的算法都将主题数作为参数,将文档-单词矩阵作为输入,并将WTM(单词主题矩阵)TDM(主题文档矩阵)作为输出。