Natural Language Toolkit 简明教程
Natural Language Toolkit - Text Classification
What is text classification?
正如名称所暗示的那样,文本分类是对文本或文档进行分类的方法。但是,这里 возникает вопрос: 为什么我们需要使用文本分类器?一旦检查文档或文本中的单词用法,分类器将能够决定应为其分配哪个类标签。
Text Feature Extraction
正如名称所暗示的那样,文本特征提取是将单词列表转换成本分类器可用的特征集的过程。我们必须将文本转换为 ‘dict’ 样式的特征集,因为自然语言工具包 (NLTK) 需要 ‘dict’ 样式的特征集。
Bag of Words (BoW) model
BoW 是 NLP 中最简单的模型之一,用于从文本或文档片段中提取特征,以便可以在建模中使用它,这样它就可以在 ML 算法中使用。它基本上从实例的所有单词中构造单词存在特征集。此方法背后的概念是,它不关心单词出现多少次或单词的顺序,它只关心单词是否存在于单词列表中。
Training classifiers
在前面的章节中,我们学习了如何从文本中提取特征。所以现在我们可以训练一个分类器。第一个也是最简单的分类器是 NaiveBayesClassifier 类。
Naïve Bayes Classifier
为了预测给定的特征集合属于特定标签的概率,它使用贝叶斯定理。贝叶斯定理的公式如下。
在此,
P(A|B) − 它也被称为后验概率,即在已知第二个事件(即 B)发生的情况下,第一个事件(即 A)发生的概率。
P(B|A) − 它是在第一个事件(即 A)发生后,第二个事件(即 B)发生的概率。
P(A), P(B) − 它也被称为先验概率,即第一个事件(即 A)或第二个事件(即 B)发生的概率。
为了训练朴素贝叶斯分类器,我们将使用 NLTK 中的 movie_reviews 语料库。此语料库有两个类别的文本,即: pos 和 neg 。这些类别使训练它们的分类器成为二元分类器。语料库中的每个文件都由两部分组成,一部分是正面的电影评论,另一部分是负面的电影评论。在我们的例子中,我们将每个文件用作训练和测试分类器的单个实例。
Example
对于训练分类器,我们需要一个标记的特征集合列表,其形式为 [( featureset, label )]. 这里 featureset 变量是一个 dict ,标签是 featureset 的已知类标签。我们准备创建一个名为 label_corpus() 的函数,它将接受一个名为 movie_reviews*and also a function named *feature_detector 的语料库,该语料库默认为 bag of words 。它将构建并返回一个这种形式的映射:{label: [featureset]}。之后,我们将使用此映射来创建一个标记的训练实例和测试实例列表。
import collections
def label_corpus(corp, feature_detector=bow):
label_feats = collections.defaultdict(list)
for label in corp.categories():
for fileid in corp.fileids(categories=[label]):
feats = feature_detector(corp.words(fileids=[fileid]))
label_feats[label].append(feats)
return label_feats
借助上述函数,我们将得到一个映射 {label:fetaureset} 。现在,我们准备定义另一个名为 split 的函数,它将接受 label_corpus() 函数返回的映射,并将每个特征集合的列表分割为标记的训练实例和测试实例。
def split(lfeats, split=0.75):
train_feats = []
test_feats = []
for label, feats in lfeats.items():
cutoff = int(len(feats) * split)
train_feats.extend([(feat, label) for feat in feats[:cutoff]])
test_feats.extend([(feat, label) for feat in feats[cutoff:]])
return train_feats, test_feats
现在,让我们在我们的语料库中使用这些函数,即 movie_reviews −
from nltk.corpus import movie_reviews
from featx import label_feats_from_corpus, split_label_feats
movie_reviews.categories()
Decision Tree Classifier
另一个重要的分类器是决策树分类器。这里为了训练 DecisionTreeClassifier 类将创建一个树结构。在此树结构中,每个节点对应一个特征名称,分支对应特征值。沿着分支向下,我们将到达树叶,即分类标签。
为了训练决策树分类器,我们将使用我们从 movie_reviews 语料库中创建的相同的训练和测试特征,即 train_feats 和 test_feats 变量。
Maximum Entropy Classifier
另一个重要的分类器是 MaxentClassifier ,它也被称为 conditional exponential classifier 或 logistic regression classifier 。在此处为了训练它, MaxentClassifier 类将使用编码将标记的特征集合转换为矢量。
为了训练决策树分类器,我们将使用我们从 movie_reviews 语料库中创建的相同的训练和测试特征,即 train_feats*and *test_feats 变量。
Scikit-learn Classifier
最好的机器学习(ML)库之一是 Scikit-Learn。它实际上包含各种用途的各种 ML 算法,但它们都具有以下相同的拟合设计模式 −
-
将模型拟合到数据中
-
并使用该模型预测
与直接访问 scikit-learn 模型不同,我将使用 NLTK 的 SklearnClassifier 类。此类是 scikit-learn 模型的封装类,用于使其符合 NLTK 的 Classifier 接口。
我们将按照以下步骤训练 SklearnClassifier 类−
Step 1 − 我们先创建训练功能,就像我们在之前的食谱中所做的那样。
Step 2 − 现在,选择并导入 Scikit-learn 算法。
Step 3 − 接下来,我们需要使用所选算法构造 SklearnClassifier 类。
Step 4 − 最后,我们将用训练功能训练 SklearnClassifier 类。
让我们在下面的 Python 食谱中实现这些步骤−
from nltk.classify.scikitlearn import SklearnClassifier
from sklearn.naive_bayes import MultinomialNB
sklearn_classifier = SklearnClassifier(MultinomialNB())
sklearn_classifier.train(train_feats)
<SklearnClassifier(MultinomialNB(alpha = 1.0,class_prior = None,fit_prior = True))>
accuracy(sk_classifier, test_feats)
Measuring precision and recall
在训练各种分类器时,我们还测量了它们的准确性。但除了准确性之外,还有许多其他指标可用于评估分类器。其中两个指标是 precision 和 recall 。
Example
在此示例中,我们将计算我们之前训练的 NaiveBayesClassifier 类的精度和召回率。为此,我们将创建一个名为 metrics_PR() 的函数,它将使用两个参数,一个是训练后的分类器,另一个是带标签的测试功能。这两个参数与我们在计算分类器准确性时传递的参数相同−
import collections
from nltk import metrics
def metrics_PR(classifier, testfeats):
refsets = collections.defaultdict(set)
testsets = collections.defaultdict(set)
for i, (feats, label) in enumerate(testfeats):
refsets[label].add(i)
observed = classifier.classify(feats)
testsets[observed].add(i)
precisions = {}
recalls = {}
for label in classifier.labels():
precisions[label] = metrics.precision(refsets[label],testsets[label])
recalls[label] = metrics.recall(refsets[label], testsets[label])
return precisions, recalls
让我们调用此函数以查找精度和召回率−
from metrics_classification import metrics_PR
nb_precisions, nb_recalls = metrics_PR(nb_classifier,test_feats)
nb_precisions['pos']
Combination of classifier and voting
组合分类器是提高分类性能的最佳方法之一。投票是合并多个分类器的最佳方式之一。对于投票,我们需要奇数个分类器。在以下 Python 食谱中,我们将结合三个分类器,即 NaiveBayesClassifier 类、DecisionTreeClassifier 类和 MaxentClassifier 类。
为了实现这一点,我们将定义一个名为 voting_classifiers() 的函数,如下所示。
import itertools
from nltk.classify import ClassifierI
from nltk.probability import FreqDist
class Voting_classifiers(ClassifierI):
def __init__(self, *classifiers):
self._classifiers = classifiers
self._labels = sorted(set(itertools.chain(*[c.labels() for c in classifiers])))
def labels(self):
return self._labels
def classify(self, feats):
counts = FreqDist()
for classifier in self._classifiers:
counts[classifier.classify(feats)] += 1
return counts.max()
让我们调用此函数以组合三个分类器并找到准确性−
from vote_classification import Voting_classifiers
combined_classifier = Voting_classifiers(NBC, decisiont_classifier, maxent_classifier)
combined_classifier.labels()