NLTK包

NLTK包

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

前提条件

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

要构建这样的应用程序,我们将使用名为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

pattern

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

pip install pattern

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

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

标记化" class="reference-link">1. 标记化

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

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

输出 -

打断给定文本的过程可以通过查找单词边界来完成。 单词的结尾和新单词的开头称为单词边界。 文字的书写体系和印刷结构会影响边界。

在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

2. 词干

在处理文字时,由于语法原因,我们遇到了很多变化。 这里的变化的概念意味着必须处理像:democracy, democraticdemocratization 等不同形式的相同词汇。机器非常需要理解这些不同的单词具有相同的基本形式。 通过这种方式,在分析文本的同时提取单词的基本形式将会很有用。

我们可以通过阻止来实现这一点。 通过这种方式,可以说干扰是通过切断单词的结尾来提取单词基本形式的启发式过程。

在Python NLTK模块中,有一些与stemming相关的其它包。 这些包可以用来获取单词的基本形式。 这些软件包使用算法。 一些软件包如下所示 -

PorterStemmer包

这个Python包使用Porter算法来提取基础表单。可以使用下面的Python代码来这个包 -

from nltk.stem.porter import PorterStemmer

例如,如果将writing这个词作为这个词干的输入,它们就会在词干之后得到write这个词。

LancasterStemmer包

这个Python包将使用Lancaster的算法来提取基本形式。 可以使用下面的Python代码来导入这个包 -

from nltk.stem.lancaster import LancasterStemmer

例如,如果将writing这个词作为这个词干的输入,它们就会在词干之后得到write这个词。

SnowballStemmer包

这个Python包将使用雪球算法来提取基本形式。 可以使用下面的Python代码来导入这个包 -

from nltk.stem.snowball import SnowballStemmer

例如,如果将writing这个词作为这个词干的输入,它们就会在词干之后得到write这个词。

所有这些算法都有不同程度的严格性。 如果比较这三个词干的话,那么波特词干是最不严格的,兰卡斯特词干是最严格的。 雪球词干在速度和严格性方面都很好用。

词形还原

也可以通过词形化来提取单词的基本形式。 它基本上通过使用词汇的词汇和形态分析来完成这项任务,通常旨在仅删除变元结尾。 任何单词的这种基本形式都称为引理。

词干化和词性化的主要区别在于词汇的使用和形态分析。 另一个区别是,词干最常见的是崩溃派生相关的词汇,而词素化通常只会折拢引理的不同的折点形式。 例如,如果提供单词saw作为输入词,那么词干可能会返回单词's',但词形化会尝试返回单词,看看或看到取决于使用该单词是动词还是名词。

在Python NLTK模块中,有以下与词形化过程有关的包,可以使用它来获取词的基本形式 -

WordNetLemmatizer包

这个Python包将提取单词的基本形式,取决于它是用作名词还是动词。 可以使用下面的Python代码的来导入这个包 -

from nltk.stem import WordNetLemmatizer

块化:将数据分割成块

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

在下面的章节中,我们将学习不同类型的分块。

组块的类型

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

  • 上分块
    在这个组块过程中,对象,事物等向更普遍的方向发展,语言变得更加抽象。 有更多的协议机会。 在这个过程中缩小。 例如,如果将“汽车是为了什么目的”这个问题大肆渲染?我们可能会得到答案是:“运输”。

  • 下分块
    在这个组块过程中,对象,事物等朝着更具体的方向发展,语言更加渗透。 更深层次的结构将进行仔细检查。 在这个过程中会放大。例如,如果将“专门讲述一辆汽车”这个问题归纳起来? 会得到关于汽车的更小的信息。

示例

在这个例子中,我们将通过使用Python中的NLTK模块来进行Noun-Phrase chunking,这是一种chunking类别,它可以在句子中找到名词短语块,

在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:{<DT>?<JJ>*<NN>}"

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

parser_chunking = nltk.RegexpParser(grammar)

解析器解析该句子如下 -

parser_chunking.parse(sentence)

接下来,需要获得输出。 输出在名为output_chunk的变量中生成。

Output_chunk = parser_chunking.parse(sentence)

执行以下代码后,以树的形式绘制输出结果。

output.draw()

执行上面代码,得到以下结果 -

词袋(BOW)模型

词袋 - 英文为:Bag of Word(BoW) ,它是自然语言处理中的一个模型,基本上用于从文本中提取特征,以便文本可用于建模,以便在机器学习算法中使用。

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

它是怎么运行的
这是从文本中提取特征的非常简单的方法。 假设我们有一个文本文档,并且希望将其转换为数字数据或者说想从中提取特征,那么首先这个模型从文档中的所有单词中提取词汇。 然后通过使用文档术语矩阵,它将建立一个模型。通过这种方式,BoW仅将文件表示为一袋文字。 丢弃关于文档中单词的顺序或结构的任何信息。

文档术语矩阵的概念

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

示例

假设有以下两个句子 -

  • 句子1 - 正在使用词袋模型。
  • 句子2 - Bag of Words模型用于提取特征。

现在,通过考虑这两句子,有以下13个不同的单词 -

  • we
  • are
  • using
  • the
  • bag
  • of
  • words
  • model
  • is
  • used
  • for
  • extracting
  • features

现在,我们需要使用每个句子中的单词计数为每个句子建立一个直方图 -

  • 子句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]

这样,就得到了已经提取的特征向量。每个特征向量都是13维的,因为这里有13个不同的单词。

统计概念

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

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

逆文档频率(idf)
这是衡量在给定的文档集中这个文档有多独特的一个单词。要计算idf和制定一个特征向量,我们需要减少像这样的常见词的权重,并权衡稀有词。

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

以上数据将用于训练一个Multinomial朴素贝叶斯分类器 -

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

在上面的输出中可以看到,结束字母的最大数量的准确性是两个,并且随着结束字母数量的增加而减少。

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

我们知道,一般而言,文档被分组为主题。 有时需要确定文本中与特定主题相对应的模式。 这样做的技术称为主题建模。 换句话说,可以说主题建模是一种揭示给定文档集合中抽象主题或隐藏结构的技术。

可以在以下场景中使用主题建模技术 -

文本分类
在主题建模的帮助下,分类可以得到改进,因为它将相似的单词分组在一起,而不是分别将每个单词用作特征。

推荐系统
在主题建模的帮助下,可以使用相似性度量来构建推荐系统。

主题建模算法

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

潜在狄利克雷分配(LDA)
该算法是主题建模中最流行的算法。 它使用概率图形模型来实现主题建模。 我们需要在Python中导入gensim包以使用LDA slgorithm。

潜在语义分析(LDA)或潜在语义索引(LSI)
该算法基于线性代数。 基本上它在文档术语矩阵上使用SVD(奇异值分解)的概念。

非负矩阵分解(NMF)
它也基于线性代数。

上述所有用于话题建模的算法都将主题数量作为参数,将文档 - 词汇矩阵作为输入,将WTM(词主题矩阵)和TDM(主题文档矩阵)作为输出。