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提供的功能能帮你快速入门,理解文本分析的原理和方法。
来源: