19、文本分类:多标签与命令行训练探索

文本分类:多标签与命令行训练探索

多标签分类器的构建与评估

在文本分类任务中,我们通常会遇到需要对文本进行多标签分类的情况。传统的二元分类器只能对文本进行二选一的分类,而多标签分类器则可以为文本分配多个标签。下面我们将详细介绍如何使用路透社语料库构建和评估多标签分类器。

准备工作

路透社语料库包含了多标签文本,我们可以利用这些文本进行训练和评估。首先,我们需要计算路透社语料库中的高信息词,这可以通过 featx.py 文件中的 reuters_high_info_words() 函数来实现:

from nltk.corpus import reuters
def reuters_high_info_words(score_fn=BigramAssocMeasures.chi_sq):
    labeled_words = []
    for label in reuters.categories():
        labeled_words.append((label, reuters.words(categories=[label])))
    return high_information_words(labeled_words, score_fn=score_fn)

接下来,我们需要根据这些高信息词获取训练和测试特征集。这可以通过 featx.py 文件中的 reuters_train_test_feats() 函数来实现:

def reuters_train_test_feats(feature_detector=bag_of_words):
    train_feats = []
    test_feats = []
    for fileid in reuters.fileids():
        if fileid.startswith('training'):
            featlist = train_feats
        else:  # fileid.startswith('test')
            featlist = test_feats
        feats = feature_detector(reuters.words(fileid))
        labels = reuters.categories(fileid)
        featlist.append((feats, labels))
    return train_feats, test_feats

我们可以使用这两个函数来获取多标签训练和测试特征集的列表:

from featx import reuters_high_info_words, reuters_train_test_feats
rwords = reuters_high_info_words()
featdet = lambda words: bag_of_words_in_set(words, rwords)
multi_train_feats, multi_test_feats = reuters_train_test_feats(featdet)
训练多个二元分类器

得到多标签训练特征集后,我们可以使用 classification.py 文件中的 train_binary_classifiers() 函数为每个标签训练一个二元分类器:

def train_binary_classifiers(trainf, labelled_feats, labelset):
    pos_feats = collections.defaultdict(list)
    neg_feats = collections.defaultdict(list)
    classifiers = {}
    for feat, labels in labelled_feats:
        for label in labels:
            pos_feats[label].append(feat)
        for label in labelset - set(labels):
            neg_feats[label].append(feat)
    for label in labelset:
        postrain = [(feat, label) for feat in pos_feats[label]]
        negtrain = [(feat, '!%s' % label) for feat in neg_feats[label]]
        classifiers[label] = trainf(postrain + negtrain)
    return classifiers

为了使用这个函数,我们需要提供一个训练函数,该函数接受一个参数,即训练数据。这里我们使用一个简单的 lambda 包装器来包装 sklearn 逻辑回归 SklearnClassifier 类:

from classification import train_binary_classifiers
trainf = lambda train_feats: SklearnClassifier(LogisticRegression()).train(train_feats)
labelset = set(reuters.categories())
classifiers = train_binary_classifiers(trainf, multi_train_feats, labelset)
构建多标签分类器

在训练完多个二元分类器后,我们可以使用 classification.py 文件中的 MultiBinaryClassifier 类来构建一个多标签分类器:

from nltk.classify import MultiClassifierI
class MultiBinaryClassifier(MultiClassifierI):
    def __init__(self, *label_classifiers):
        self._label_classifiers = dict(label_classifiers)
        self._labels = sorted(self._label_classifiers.keys())

    def labels(self):
        return self._labels
    def classify(self, feats):
        lbls = set()
        for label, classifier in self._label_classifiers.items():
            if classifier.classify(feats) == label:
                lbls.add(label)
        return lbls

我们可以使用刚刚创建的二元分类器来构建这个类:

from classification import MultiBinaryClassifier
multi_classifier = MultiBinaryClassifier(*classifiers.items())
评估多标签分类器

为了评估多标签分类器,我们可以使用精确率和召回率,但不能使用准确率。因为准确率函数假设的是单值,没有考虑部分匹配的情况。因此,我们使用 masi 距离来评估分类器, masi 距离可以衡量两个集合之间的部分重叠程度。 classification.py 文件中的 multi_metrics() 函数可以计算每个标签的精确率和召回率,以及平均 masi 距离:

import collections
from nltk import metrics
def multi_metrics(multi_classifier, test_feats):
    mds = []
    refsets = collections.defaultdict(set)
    testsets = collections.defaultdict(set)
    for i, (feat, labels) in enumerate(test_feats):
        for label in labels:
            refsets[label].add(i)
        guessed = multi_classifier.classify(feat)
        for label in guessed:
            testsets[label].add(i)
        mds.append(metrics.masi_distance(set(labels), guessed))
    avg_md = sum(mds) / float(len(mds))
    precisions = {}
    recalls = {}
    for label in multi_classifier.labels():
        precisions[label] = metrics.precision(refsets[label], testsets[label])
        recalls[label] = metrics.recall(refsets[label], testsets[label])
    return precisions, recalls, avg_md

使用这个函数来评估我们刚刚创建的多标签分类器:

from classification import multi_metrics
multi_precisions, multi_recalls, avg_md = multi_metrics(multi_classifier, multi_test_feats)

下面是多标签分类器构建和评估的流程图:

graph TD;
    A[计算高信息词] --> B[获取训练和测试特征集];
    B --> C[训练多个二元分类器];
    C --> D[构建多标签分类器];
    D --> E[评估多标签分类器];
NLTK-Trainer训练分类器

除了上述的多标签分类器构建方法,我们还可以使用 NLTK-Trainer 中的 train_classifier.py 脚本来从命令行训练 NLTK 分类器。

基本使用

train_classifier.py 脚本的唯一必需参数是语料库的名称,语料库必须有 categories() 方法。以下是在 movie_reviews 语料库上运行 train_classifier.py 的示例:

$ python train_classifier.py movie_reviews

这个命令将加载 movie_reviews 语料库,使用词袋特征提取方法,训练一个 NaiveBayes 分类器,并输出准确率、精确率、召回率和F值等评估指标。

我们还可以使用 --no-pickle 参数跳过保存分类器,使用 --fraction 参数限制训练集的大小,并对分类器进行测试:

$ python train_classifier.py movie_reviews --no-pickle --fraction 0.75
选择不同的分类器

可以使用 --classifier 参数选择不同的分类器,例如 DecisionTreeClassifier

$ python train_classifier.py movie_reviews --no-pickle --fraction 0.75 --classifier DecisionTree --trace 0 --entropy_cutoff 0.8 --depth_cutoff 5 --support_cutoff 30 --binary
其他功能
  • 保存分类器 :可以使用 --filename 参数指定分类器的保存文件名:
$ python train_classifier.py movie_reviews --filename path/to/classifier.pickle
  • 使用不同的训练实例 :默认情况下, train_classifier.py 使用单个文件作为训练实例,但我们可以使用 --instances 参数指定使用段落或句子作为训练实例:
$ python train_classifier.py movie_reviews --no-pickle --fraction 0.75 --instances sents
  • 查看最具信息性的特征 :可以使用 --show-most-informative 参数查看最具信息性的特征:
$ python train_classifier.py movie_reviews --no-pickle --fraction 0.75 --show-most-informative 5
  • 使用不同的分类算法 :可以使用 --classifier 参数选择不同的分类算法,例如 Maxent LogisticRegression SVM 等:
$ python train_classifier.py movie_reviews --no-pickle --fraction 0.75 --classifier GIS --max_iter 10 --min_lldelta 0.5
$ python train_classifier.py movie_reviews --no-pickle --fraction 0.75 --classifier sklearn.LogisticRegression
$ python train_classifier.py movie_reviews --no-pickle --fraction 0.75 --classifier sklearn.LinearSVC
$ python train_classifier.py movie_reviews --no-pickle --fraction 0.75 --classifier sklearn.NuSVC
  • 组合分类器 :可以使用 --classifier 参数指定多个分类器, train_classifier.py 会将这些分类器组合起来:
$ python train_classifier.py movie_reviews --no-pickle --fraction 0.75 --classifier sklearn.LogisticRegression sklearn.MultinomialNB sklearn.NuSVC
  • 使用高信息词和二元组 :可以使用 --min_score --ngrams 参数指定使用高信息词和二元组作为特征:
$ python train_classifier.py movie_reviews --no-pickle --fraction 0.75 --classifier NaiveBayes --min_score 5 --ngrams 1 2
  • 交叉验证 :可以使用 --cross-fold 参数进行交叉验证:
$ python train_classifier.py movie_reviews --classifier sklearn.LogisticRegression --cross-fold 10

下面是 train_classifier.py 脚本的使用流程表格:
| 功能 | 参数 | 示例 |
| ---- | ---- | ---- |
| 基本使用 | 语料库名称 | python train_classifier.py movie_reviews |
| 跳过保存分类器 | --no-pickle | python train_classifier.py movie_reviews --no-pickle |
| 限制训练集大小 | --fraction | python train_classifier.py movie_reviews --fraction 0.75 |
| 选择分类器 | --classifier | python train_classifier.py movie_reviews --classifier DecisionTree |
| 保存分类器 | --filename | python train_classifier.py movie_reviews --filename path/to/classifier.pickle |

文本分类:多标签与命令行训练探索

分析分类器

除了训练分类器,我们还可以使用 NLTK-Trainer 中的 analyze_classifier_coverage.py 脚本来分析分类器对给定语料库的分类情况。该脚本需要语料库的名称和一个已保存的分类器的路径作为输入。如果语料库是有分类标注的,还可以使用 --metrics 参数来获取准确率、精确率和召回率等评估指标。此外,使用 --speed 参数可以查看分类器的分类速度。

以下是一个使用 analyze_classifier_coverage.py 脚本来分析一个保存的 NaiveBayesClassifier movie_reviews 语料库的分类情况的示例:

$ python analyze_classifier_coverage.py movie_reviews --classifier classifiers/movie_reviews_NaiveBayes.pickle --metrics --speed

这个命令会输出加载时间、准确率、精确率、召回率、F值、每个分类的数量以及平均每个特征的分类时间。

下面是分析分类器的操作步骤列表:
1. 准备好语料库和已保存的分类器。
2. 运行 analyze_classifier_coverage.py 脚本,并传入语料库名称和分类器路径。
3. 根据需要添加 --metrics 参数获取评估指标,添加 --speed 参数查看分类速度。

总结与注意事项

在构建和评估多标签分类器以及使用 NLTK-Trainer 训练和分析分类器的过程中,有以下几点需要注意:

多标签分类器
  • 类不平衡问题 :路透社语料库存在类不平衡问题,即某些标签的特征集很少,而其他标签的特征集很多。这会导致二元分类器对负标签有很强的偏向性,难以得到正结果。虽然这种偏向反映了数据的实际情况,但可能会影响分类器的性能。可以参考相关技术来解决这个问题。
  • 评估指标 :对于多标签分类器,不能使用准确率来评估,而应使用精确率、召回率和 masi 距离等指标,因为准确率函数假设的是单值,没有考虑部分匹配的情况。
NLTK-Trainer
  • 参数使用 train_classifier.py analyze_classifier_coverage.py 脚本支持很多参数,可以根据需要灵活使用这些参数来实现不同的功能,如选择不同的分类器、保存分类器、使用不同的训练实例等。
  • 结果稳定性 :由于 PYTHONHASHSEED 环境变量的影响,运行 train_classifier.py 时,准确率、精确率和召回率等结果可能会有所不同。如果需要得到一致的结果,可以设置 PYTHONHASHSEED 环境变量,例如:
$ PYTHONHASHSEED=0 python train_classifier.py movie_reviews

下面是多标签分类和 NLTK-Trainer 使用的整体流程图:

graph LR;
    A[多标签分类器构建] --> B[计算高信息词];
    B --> C[获取训练和测试特征集];
    C --> D[训练多个二元分类器];
    D --> E[构建多标签分类器];
    E --> F[评估多标签分类器];
    G[NLTK-Trainer使用] --> H[train_classifier.py训练];
    H --> I[选择不同参数和分类器];
    J --> K[analyze_classifier_coverage.py分析];
    K --> L[获取评估指标和速度];
    A -.-> G;

通过以上介绍,我们详细了解了如何构建和评估多标签分类器,以及如何使用 NLTK-Trainer 从命令行训练和分析分类器。这些方法和工具可以帮助我们更高效地进行文本分类任务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值