NLTK玩转文本!Python自然语言处理不再难~

NLTK,全称Natural Language Toolkit,听起来就很专业是吧?其实就是一个帮助Python开发者搞定“自然语言处理”的工具包。搞什么自然语言处理呢?你可以用它做分词、词性标注、文本分类、情感分析、甚至生成句子。通俗来说,它能让你的代码“读懂”文本的含义。今天就来看看NLTK有哪些功能,以及怎么用它在文本世界里来回遨游。

NLTK的安装

写代码的第一步,当然是装包了。装这个包很简单,用Python的pip安装一下就行:

pip install nltk

装完之后,还得下载一些数据集和模型,因为NLTK很多功能都依赖这些资源,运行下面的代码就能打开NLTK的资源下载界面了:

import nltk
nltk.download()

NLTK里的数据集丰富得像个小图书馆,你可以下载自己需要的,比如常用的punkt(分词用),averaged_perceptron_tagger(词性标注用)等等。


文本分词:拆解句子的第一步

分词,就是把一句话拆成一个个的单词。NLTK提供的word_tokenize方法可以轻松完成这一步。举个简单的例子:

from nltk.tokenize import word_tokenize

sentence = "NLTK is a powerful tool for natural language processing."
tokens = word_tokenize(sentence)
print(tokens)

输出结果是这样的:

['NLTK', 'is', 'a', 'powerful', 'tool', 'for', 'natural', 'language', 'processing', '.']

这时候,句子就被拆成了一个个小块,这对后续的处理非常有帮助。要做词频统计、情感分析,甚至是生成新句子,分词都得先跑一遍。

温馨提示

分词这个步骤看着简单,但别掉以轻心。像“I'm”这种带缩写的词,分出来可能会变成“I”和“'m”,有时候会影响分析结果。所以分词后的数据,大家可以稍微扫一眼,看是不是都符合你的需求。


词性标注:告诉你哪个词是动词哪个是名词

如果说分词是拆句子,词性标注(POS tagging)就是给每个词贴标签。NLTK的pos_tag函数能帮你完成这一步。

from nltk import pos_tag

tokens = word_tokenize(sentence)
tagged_tokens = pos_tag(tokens)
print(tagged_tokens)

输出大概会是这个样子:

[('NLTK', 'NNP'), ('is', 'VBZ'), ('a', 'DT'), ('powerful', 'JJ'), ('tool', 'NN'), ('for', 'IN'), ('natural', 'JJ'), ('language', 'NN'), ('processing', 'NN'), ('.', '.')]

这里的标记看着有点头大,但其实只要掌握几个关键的就好:

  • NN 表示名词(noun)
  • VB 表示动词(verb)
  • JJ 表示形容词(adjective)

有了这些标签,你的代码就知道哪个词是主角(名词),哪个是动作(动词),哪个是修饰词(形容词),大大增加了理解句子结构的能力。


词干提取和词形还原:回归词汇的本源

人类说话,习惯把单词的形态变来变去,比如“running”、“ran”、“runs”,其实都是“run”。词干提取词形还原就是把这些变体还原成最初的样子,这一步能让你的代码更“通透”地理解句子的意思。

词干提取(Stemming)

NLTK有一个经典的词干提取器:PorterStemmer。它的作用就是把单词变成它的“干”,不论单词是什么形态。

from nltk.stem import PorterStemmer

stemmer = PorterStemmer()
print(stemmer.stem("running"))  # 输出:run
print(stemmer.stem("ran"))      # 输出:ran
print(stemmer.stem("runs"))     # 输出:run

这个方法简单粗暴,但好处是快。不过它有时候会让结果看着有点“机械”,比如"better"会变成"bet"。

词形还原(Lemmatization)

NLTK的WordNetLemmatizer可以更精准地还原词形。比起词干提取,它的结果更贴合人类的语言习惯:

from nltk.stem import WordNetLemmatizer

lemmatizer = WordNetLemmatizer()
print(lemmatizer.lemmatize("running", pos="v"))  # 输出:run
print(lemmatizer.lemmatize("better", pos="a"))   # 输出:good

词形还原需要提供词性,效果更好。比如上例中的“better”,给它一个形容词的标记,它就能识别出它的原形是“good”。


停用词:那些常见却无用的词

英文中的“the”“is”“at”这类词叫做停用词(stopwords),几乎每句话都有,但对分析意义不大。NLTK内置了一份停用词的列表,用它可以轻松去除掉这些词:

from nltk.corpus import stopwords

stop_words = set(stopwords.words("english"))
tokens = word_tokenize(sentence)
filtered_tokens = [word for word in tokens if word.lower() not in stop_words]
print(filtered_tokens)

输出就会少了“is”和“for”这种词,方便你集中精力分析那些更有信息量的词。


文本分类:从新闻到情感分析

到了分类这一步,NLTK基本就成了你的私人AI助手。用它来分辨一段文字的类别,或者判断一条评论是正面还是负面,这都不是梦!

准备数据

首先要有数据,比如一堆已经贴好标签的文字数据(正面、负面、新闻类别等等)。NLTK自带一个movie_reviews的语料库,可以用来训练模型。

from nltk.corpus import movie_reviews
from nltk.classify import NaiveBayesClassifier
from nltk.classify.util import accuracy

# 准备数据
documents = [(list(movie_reviews.words(fileid)), category)
             for category in movie_reviews.categories()
             for fileid in movie_reviews.fileids(category)]

提取特征

下一步需要告诉模型我们要用哪些特征。简单起见,用词频来作为特征:

import random
random.shuffle(documents)

all_words = nltk.FreqDist(w.lower() for w in movie_reviews.words())
word_features = list(all_words)[:2000]

def document_features(document):
    document_words = set(document)
    features = {}
    for word in word_features:
        features[f"contains({word})"] = (word in document_words)
    return features

featuresets = [(document_features(d), c) for (d,c) in documents]

训练和评估模型

最后一步,用特征来训练一个分类器,经典的朴素贝叶斯分类器就能跑出不错的结果:

train_set, test_set = featuresets[100:], featuresets[:100]
classifier = NaiveBayesClassifier.train(train_set)

print("Accuracy:", accuracy(classifier, test_set))  # 输出准确率
classifier.show_most_informative_features(5)       # 显示最具代表性的特征

这样一个简单的文本分类器就完成了,准确率在0.7以上。拿它去分析电影评论、情感分类、文章主题等等,都可以得到不错的结果。


小结

NLTK作为Python里的自然语言处理瑞士军刀,功能还远不止这些。用它可以处理文本、分词、标注、分类等等,为文本分析铺平了道路。当然,在实战中自然语言处理还有不少挑战,比如数据量的大小、模型的选择。不过NLTK提供的功能能帮你快速入门,理解文本分析的原理和方法。

来源:沐子 沐子曰

THE END