本教程的目标是让您能够通过自然语言处理 (NLP) 的概念在 Python 中分析文本数据。您将首先学习如何将文本标记为更小的块,将单词规范化为其根形式,然后去除文档中的任何噪音,为进一步分析做好准备。
[[434759]]
让我们开始吧!
先决条件
在本教程中,我们将使用 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')
接下来,您需要导入word_tokenizefromnltk.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”的形式。
虽然您的项目的必要性可能要求您保留各种语法形式的单词,但让我们讨论一种将同一单词的各种语法形式转换为其基本形式的方法。有两种技术可用于将单词转换为其基词。
第一种技术是词干。Stemming是一种简单的算法,可以从单词中删除词缀。有多种词干提取算法可用于 NLTK。我们将在本教程中使用 Porter 算法。
我们首先PorterStemmer从nltk.stem.porter. 接下来,我们将词干分析器初始化为stemmer变量,然后使用该.stem()方法查找单词的基本形式:
- from nltk.stem.porter import PorterStemmer
- stemmer = PorterStemmer()
- print(stemmer.stem("going"))
上面代码的输出是go. 如果您针对上述其他形式的“go”运行词干分析器,您会注意到词干分析器返回相同的基本形式“go”。然而,由于词干提取只是一种基于去除词缀的简单算法,当词在语言中不太常用时,它会失败。
例如,当您在单词“constitutes”上尝试词干分析时,它给出了一个不直观的结果:
- print(stemmer.stem("constitutes"))
你会注意到输出是“constitut”。
这个问题可以通过使用更复杂的方法来解决,以在给定的上下文中找到单词的基本形式。该过程称为词形还原。词形还原根据文本的上下文和词汇对单词进行规范化。在 NLTK 中,您可以使用WordNetLemmatizer类对句子进行词形还原。
首先,您需要wordnet从 Python 终端中的 NLTK 下载器下载资源:
- nltk.download('wordnet')
下载后,您需要导入WordNetLemmatizer该类并对其进行初始化:
- from nltk.stem.wordnet import WordNetLemmatizer
- lem = WordNetLemmatizer()
要使用 lemmatizer,请使用.lemmatize()方法。它需要两个参数:单词和上下文。在我们的示例中,我们将使用“v”作为上下文。在查看该.lemmatize()方法的输出后,让我们进一步探索上下文:
- print(lem.lemmatize('constitutes', 'v'))
您会注意到该.lemmatize()方法正确地将单词“constitutes”转换为其基本形式“constitute”。您还会注意到词形还原比词干提取花费的时间更长,因为算法更复杂。
让我们检查如何以.lemmatize()编程方式确定方法的第二个参数。NLTK 具有pos_tag()帮助确定句子中单词上下文的功能。但是,您首先需要
averaged_perceptron_tagger通过 NLTK 下载器下载资源:
- 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'),
- ('.', '.')]
你如何解码每个令牌的上下文?这是Web 上所有标签及其相应含义的完整列表。请注意,所有名词的标签都以“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”和“magistrates”已分别转换为“constitute”和“magistrate”。
第 3 步:数据清理
准备数据的下一步是清理数据并删除任何对您的分析没有意义的内容。从广义上讲,我们将考虑从您的分析中删除标点符号和停用词。
删除标点符号是一项相当容易的任务。该库的punctuation对象string包含所有英文标点符号:
- import string
- print(string.punctuation)
此代码片段的输出如下:
- '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
为了从标记中删除标点符号,您可以简单地运行:
- for token in tokens:
- if token in string.punctuation:
- # Do something
接下来,我们将专注于删除停用词。停用词是语言中常用的词,如“I”、“a”和“the”,在分析文本时对文本几乎没有意义。因此,我们将从分析中删除停用词。首先,stopwords从 NLTK 下载器下载资源:
- nltk.download('stopwords')
一旦下载完成后,进口stopwords从nltk.corpus和使用.words()方法与“英语”作为参数。这是一个包含 179 个英语停用词的列表:
- from nltk.corpus import stopwords
- stop_words = stopwords.words('english')
我们可以将词形还原示例与本节中讨论的概念结合起来创建以下函数,clean_data()。此外,在比较一个词是否是停用词列表的一部分之前,我们将其转换为小写。这样,如果停止词出现在句子的开头并且大写,我们仍然会捕获它:
- def clean_data(tokens, stop_words = ()):
- cleaned_tokens = []
- for token, tag in pos_tag(tokens):
- if tag.startswith("NN"):
- pos = 'n'
- elif tag.startswith('VB'):
- pos = 'v'
- else:
- pos = 'a'
- lemmatizer = WordNetLemmatizer()
- token = lemmatizer.lemmatize(token, pos)
- if token not in string.punctuation and token.lower() not in stop_words:
- cleaned_tokens.append(token)
- return cleaned_tokens
- sample = "The quick brown fox jumps over the lazy dog."
- stop_words = stopwords.words('english')
- clean_data(word_tokenize(sample), stop_words)
该示例的输出如下:
- ['quick', 'brown', 'fox', 'jump', 'lazy', 'dog']
如您所见,标点符号和停用词已被删除。
词频分布
现在您已经熟悉了 NLP 中的基本清理技术,让我们尝试找出文本中单词的频率。在本练习中,我们将使用古腾堡免费提供的童话故事《老鼠、鸟和香肠》的文本。我们将这个童话的文本存储在一个字符串中,text。
首先,我们text对它进行标记,然后使用clean_data我们上面定义的函数对其进行清理:
- tokens = word_tokenize(text)
- cleaned_tokens = clean_data(tokens, stop_words = stop_words)
要查找文本中单词的频率分布,您可以使用FreqDistNLTK 类。使用令牌作为参数初始化类。然后使用该.most_common()方法查找常见的术语。在这种情况下,让我们尝试找出前十项:
- from nltk import FreqDist
- freq_dist = FreqDist(cleaned_tokens)
- freq_dist.most_common(10)
以下是这个童话故事中最常见的十个术语:
- [('bird', 15),
- ('sausage', 11),
- ('mouse', 8),
- ('wood', 7),
- ('time', 6),
- ('long', 5),
- ('make', 5),
- ('fly', 4),
- ('fetch', 4),
- ('water', 4)]
不出所料,三个最常见的词是童话故事中的三个主要人物。
在分析文本时,单词的频率可能不是很重要。通常,NLP 的下一步是生成一个统计数据——TF-IDF(词频——逆文档频率)——它表示一个单词在文档列表中的重要性。
结论
在本教程中,我们首先了解了 Python 中的自然语言处理。我们将文本转换为标记,将单词转换为它们的基本形式,最后,清理文本以删除任何对分析没有意义的部分。
尽管我们在本教程中研究了简单的 NLP 任务,但还有更多技术需要探索。例如,我们可能想要对文本数据执行主题建模,其目标是找到文本可能正在谈论的共同主题。NLP 中更复杂的任务是实现情感分析模型,以确定任何文本背后的感觉。