Python中的自然语言处理入门

439 阅读5分钟

Getting Started with Natural Language Processing in Python

今天产生的数据中,有很大一部分是非结构化的。非结构化数据包括社交媒体评论、浏览历史和客户反馈。你是否发现自己有一堆文本数据需要分析,却不知道如何进行?Python中的自然语言处理可以帮助你。

本教程的目的是使你能够通过自然语言处理(NLP)的概念在Python中分析文本数据。你将首先学习如何将你的文本标记为较小的块,将单词规范化为它们的词根形式,然后去除你的文档中的任何噪音,为进一步分析做好准备。

让我们开始吧!

前提条件

在本教程中,我们将使用Python的nltk 库来对文本进行所有NLP操作。在编写本教程时,我们使用的是 3.4 版的nltk 。要安装这个库,你可以在终端使用pip 命令。

pip install nltk==3.4

要检查你在系统中拥有哪个版本的nltk ,你可以将该库导入到 Python 解释器中并检查其版本。

import nltk
print(nltk.__version__)

为了在本教程中的nltk 中执行某些操作,你可能需要下载特定的资源。我们会在需要的时候描述每个资源。

然而,如果你想避免在本教程的后面下载个别资源,而现在一次性地抓取它们,请运行以下命令。

python -m nltk.downloader all

第1步:转换为令牌

计算机系统不可能自己找到自然语言的意义。处理自然语言的第一步是将原始文本转换为代币。一个标记是连续字符的组合,具有一定的意义。如何将一个句子分解成令牌,由你来决定。例如,一个简单的方法是用空格来分割一个句子,把它分成各个单词。

在NLTK库中,你可以使用word_tokenize() 函数将一个字符串转换为标记。不过,你首先需要下载punkt 资源。在终端运行以下命令。

nltk.download('punkt')

接下来,你需要从nltk.tokenize 中导入word_tokenize 来使用它。

from nltk.tokenize import word_tokenize
print(word_tokenize("Hi, this is a nice hotel."))

该代码的输出如下。

['Hi', ',', 'this', 'is', 'a', 'nice', 'hotel', '.']

你会注意到,word_tokenize 并不是简单地根据空格来分割字符串,而是将标点符号分割成小数点。如果你想在分析中保留标点符号,这取决于你的意愿。

第2步:将单词转换为其基本形式

当你处理自然语言时,你会经常注意到同一个词有各种语法形式。例如,"go"、"going "和 "gone "是同一个动词 "go "的形式。

虽然你的项目的必要性可能要求你保留各种语法形式的单词,但让我们来讨论一种将同一个单词的各种语法形式转换为其基本形式的方法。有两种技术可以用来将一个词转换为其基础形式。

第一种技术是词干化。词干是一种简单的算法,从一个词中去除词缀。在NLTK中,有多种干化算法可供使用。我们将在本教程中使用Porter算法。

我们首先从nltk.stem.porter 中导入PorterStemmer 。接下来,我们将干系人初始化为stemmer 变量,然后使用.stem() 方法来寻找一个单词的基本形式。

from nltk.stem.porter import PorterStemmer 
stemmer = PorterStemmer()
print(stemmer.stem("going"))

上述代码的输出是go 。如果你对上述 "go "的其他形式运行干化器,你会发现干化器返回相同的基本形式 "go"。然而,由于干化只是一种基于去除词缀的简单算法,当这些词在语言中不太常用时,它就会失败。

例如,当你在 "constitutes "这个词上尝试使用干化器时,它给出了一个不直观的结果。

print(stemmer.stem("constitutes"))

你会发现输出结果是 "constitutes"。

这个问题的解决是通过转到一个更复杂的方法来寻找一个词在特定语境中的基本形式。这个过程被称为词法化。法化是根据文本的上下文和词汇来规范一个词。在NLTK中,你可以使用WordNetLemmatizer 类对句子进行词法处理。

首先,你需要从Python终端的NLTK下载器中下载wordnet 资源。

nltk.download('wordnet')

下载完毕后,你需要导入WordNetLemmatizer 类并对其进行初始化。

from nltk.stem.wordnet import WordNetLemmatizer 
lem = WordNetLemmatizer()

要使用该词法,请使用.lemmatize() 方法。它需要两个参数:单词和上下文。在我们的例子中,我们将使用 "v "作为上下文。在看了.lemmatize() 方法的输出后,让我们进一步探索上下文。

print(lem.lemmatize('constitutes', 'v'))

你会注意到,.lemmatize() 方法正确地将 "constitutes "这个词转换为它的基本形式 "constitutes"。你还会注意到,词根化比词干化花费的时间更长,因为算法更复杂。

让我们来看看如何以编程方式确定.lemmatize() 方法的第二个参数。NLTK有一个pos_tag() 功能,可以帮助确定一个词在句子中的上下文。不过,你首先需要通过NLTK下载器下载averaged_perceptron_tagger 资源。

nltk.download('averaged_perceptron_tagger')

接下来,导入pos_tag() 函数,并在一个句子上运行它。

from nltk.tag import pos_tag
sample = "Hi, this is a nice hotel."
print(pos_tag(word_tokenize(sample)))

你会注意到,输出是一个对的列表。每一对都由一个标记和它的标签组成,它表示一个标记在整个文本中的上下文。请注意,标点符号的标签就是它本身。

[('Hi', 'NNP'),
(',', ','),
('this', 'DT'),
('is', 'VBZ'),
('a', 'DT'),
('nice', 'JJ'),
('hotel', 'NN'),
('.', '.')]

你如何解读每个标记的上下文?这里有一份网络上所有标签及其相应含义的完整列表。请注意,所有名词的标签都以 "N "开头,而所有动词的标签都以 "V "开头。我们可以在我们的.lemmatize() 方法的第二个参数中使用这些信息。

def lemmatize_tokens(stentence):
  lemmatizer = WordNetLemmatizer()
  lemmatized_tokens = []
  for word, tag in pos_tag(stentence):
    if tag.startswith('NN'):
      pos = 'n'
    elif tag.startswith('VB'):
      pos = 'v'
    else:
      pos = 'a'
    lemmatized_tokens.append(lemmatizer.lemmatize(word, pos))
  return lemmatized_tokens

sample = "Legal authority constitutes all magistrates."
print(lemmatize_tokens(word_tokenize(sample)))

上述代码的输出如下。

['Legal', 'authority', 'constitute', 'all', 'magistrate', '.']

这个输出是预期的,其中 "constitutes "和 "mistrates "已经分别转换为 "constitutes "和 "mistrate"。