19、文本分类:多标签分类器与NLTK-Trainer的使用

文本分类:多标签分类器与NLTK-Trainer的使用

1. 多标签分类器的构建

在文本分类任务中,我们通常会遇到需要对文本进行多标签分类的情况。多标签分类器可以为一个文本样本分配多个标签,而不仅仅是一个。下面我们将详细介绍如何使用多个二元分类器来构建一个多标签分类器。

1.1 准备工作

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

from nltk.corpus import reuters
from nltk.collocations import BigramAssocMeasures

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)
1.2 训练二元分类器

我们使用 classification.py 中的 train_binary_classifiers() 函数为每个标签训练一个二元分类器:

import collections

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

为了使用这个函数,我们需要提供一个训练函数,这里我们使用 sklearn 的逻辑回归 SklearnClassifier 类:

from classification import train_binary_classifiers
from nltk.classify import SklearnClassifier
from sklearn.linear_model import LogisticRegression

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

我们定义一个 MultiBinaryClassifier 类,它继承自 nltk.classify.MultiClassifierI 接口:

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())
1.4 评估多标签分类器

我们使用 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)
2. 多标签分类器的工作原理

下面是多标签分类器的工作流程:
1. 计算高信息词 reuters_high_info_words() 函数会为路透社语料库的每个类别构建一个 [(label, words)] 列表,然后将其传递给 high_information_words() 函数,返回路透社语料库中最具信息量的词列表。
2. 创建特征检测器 :使用 bag_of_words_in_set() 函数创建一个特征检测器函数,并将其传递给 reuters_train_test_feats() 函数,该函数会返回两个列表,一个包含所有训练文件的 [(feats, labels)] ,另一个包含所有测试文件的相同信息。
3. 训练二元分类器 train_binary_classifiers() 函数会为每个标签构建两个列表,一个包含正训练特征集,另一个包含负训练特征集。正特征集是那些分类为该标签的特征集,负特征集则来自其他所有标签的正特征集。然后使用给定的训练函数为每个标签训练一个二元分类器。
4. 创建多标签分类器 :使用训练好的二元分类器创建 MultiBinaryClassifier 类的实例,该类扩展了 nltk.classify.MultiClassifierI 接口,需要实现 labels() classify() 两个函数。
5. 评估多标签分类器 :使用 multi_metrics() 函数评估多标签分类器,该函数会计算每个标签的精确率、召回率以及平均Masi距离。

下面是多标签分类器的继承图:

graph TD;
    MultiClassifierI --> MultiBinaryClassifier;
    MultiClassifierI --> labels();
    MultiClassifierI --> classify();
    MultiBinaryClassifier --> labels();
    MultiBinaryClassifier --> classify();
3. 类不平衡问题

路透社语料库的性质会引入类不平衡问题,即某些标签的特征集很少,而其他标签的特征集很多。这会导致二元分类器在训练时偏向负标签,因为负实例远远多于正实例。解决这个问题有一些高级技术,但这里不做详细介绍。

4. 使用NLTK-Trainer训练分类器

NLTK-Trainer是一个可以从命令行训练NLTK分类器的工具。下面我们将介绍如何使用 train_classifier.py 脚本进行分类器的训练。

4.1 基本使用

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

$ python train_classifier.py movie_reviews

运行结果如下:

loading movie_reviews
2 labels: ['neg', 'pos']
using bag of words feature extraction
2000 training feats, 2000 testing feats
training NaiveBayes classifier
accuracy: 0.967000
neg precision: 1.000000
neg recall: 0.934000
neg f-measure: 0.965874
pos precision: 0.938086
pos recall: 1.000000
pos f-measure: 0.968054
dumping NaiveBayesClassifier to ~/nltk_data/classifiers/movie_reviews_NaiveBayes.pickle

我们可以使用 --no-pickle 参数跳过保存分类器,使用 --fraction 参数限制训练集并评估分类器:

$ python train_classifier.py movie_reviews --no-pickle --fraction 0.75
4.2 工作原理

train_classifier.py 脚本会经过以下步骤来训练分类器:
1. 加载分类语料库 :加载指定的语料库。
2. 提取特征 :默认使用词袋(bag of words)特征提取方法。
3. 训练分类器 :默认使用朴素贝叶斯(NaiveBayes)分类器。

根据使用的参数,可能还会有其他步骤,如评估分类器和/或保存分类器。

4.3 其他参数和功能

train_classifier.py 脚本支持许多其他参数,以下是一些常见的参数和功能:
- 保存分类器 :不使用 --no-pickle 参数时,脚本会将分类器保存为 ~/nltk_data/classifiers/NAME.pickle ,其中 NAME 是语料库名称和训练算法的组合。可以使用 --filename 参数指定自定义文件名。
- 使用不同的训练实例 :默认使用单个文件作为训练实例,也可以使用段落或句子作为训练实例,例如:

$ 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 参数选择不同的分类器,例如:
$ 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
  • 使用Maxent和LogisticRegression分类器 :可以使用 --classifier 参数指定Maxent和LogisticRegression分类器,例如:
$ 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
  • 使用SVM分类器 :可以使用 --classifier 参数指定SVM分类器,例如:
$ 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 参数组合多个分类器,例如:
$ 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
4.4 分析分类器

NLTK-Trainer还包含一个名为 analyze_classifier_coverage.py 的脚本,可以用来分析分类器对给定语料库的分类情况。以下是一个示例:

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

通过以上介绍,我们可以看到如何使用多个二元分类器构建多标签分类器,以及如何使用NLTK-Trainer工具进行分类器的训练和评估。这些方法和工具可以帮助我们更好地完成文本分类任务。

文本分类:多标签分类器与NLTK-Trainer的使用

5. 不同参数和功能的详细对比

为了更直观地了解 train_classifier.py 脚本不同参数和功能的效果,下面我们通过表格的形式进行对比:
| 参数或功能 | 说明 | 示例命令 | 主要效果 |
| — | — | — | — |
| --no-pickle | 跳过保存分类器 | python train_classifier.py movie_reviews --no-pickle | 不将训练好的分类器保存到本地 |
| --fraction | 限制训练集大小 | python train_classifier.py movie_reviews --no-pickle --fraction 0.75 | 按比例划分训练集和测试集 |
| --filename | 指定分类器保存的自定义文件名 | python train_classifier.py movie_reviews --filename path/to/classifier.pickle | 分类器保存到指定路径和文件名 |
| --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 | 选择不同的分类器 | python train_classifier.py movie_reviews --no-pickle --fraction 0.75 --classifier DecisionTree | 可以使用不同的分类算法进行训练 |
| --min_score --ngrams | 使用高信息词和二元组作为特征 | python train_classifier.py movie_reviews --no-pickle --fraction 0.75 --classifier NaiveBayes --min_score 5 --ngrams 1 2 | 只使用满足分数要求的词和指定的n-gram作为特征 |
| --cross-fold | 进行交叉验证 | python train_classifier.py movie_reviews --classifier sklearn.LogisticRegression --cross-fold 10 | 评估分类算法的稳定性 |

6. 组合分类器的效果分析

在之前的介绍中,我们提到了可以使用 train_classifier.py 脚本组合多个分类器。下面我们通过具体的例子来分析组合分类器的效果。

$ python train_classifier.py movie_reviews --no-pickle --fraction 0.75 --classifier sklearn.LogisticRegression sklearn.MultinomialNB sklearn.NuSVC

运行上述命令后,会得到组合分类器的评估结果。与单个分类器相比,组合分类器通过将多个分类器的概率相加来产生最终的概率分布,从而进行分类。这种方法可以综合多个分类器的优势,提高分类的准确性。

例如,在某些情况下,逻辑回归(LogisticRegression)可能对某些特征的分类效果较好,而多项式朴素贝叶斯(MultinomialNB)对另一些特征的分类效果较好。通过组合这两个分类器,可以在不同的特征上发挥各自的优势,从而提高整体的分类性能。

7. 高信息词和二元组的应用优势

使用高信息词和二元组作为特征可以提高分类的准确性。当我们使用 --min_score --ngrams 参数时, train_classifier.py 脚本会只选择那些信息增益高的词和指定的n-gram作为特征。

$ python train_classifier.py movie_reviews --no-pickle --fraction 0.75 --classifier NaiveBayes --min_score 5 --ngrams 1 2

这样做的好处是可以减少特征的数量,同时保留最具信息量的特征。在文本分类中,很多词可能对分类的贡献不大,甚至会引入噪声。通过选择高信息词和二元组,可以提高分类器的效率和准确性。

8. 交叉验证的重要性

交叉验证是评估分类算法稳定性的重要方法。通过 --cross-fold 参数, train_classifier.py 脚本可以将训练语料库分成多个折叠,依次使用不同的折叠进行测试。

$ python train_classifier.py movie_reviews --classifier sklearn.LogisticRegression --cross-fold 10

交叉验证的流程如下:

graph LR;
    A[将训练语料库分成10个折叠] --> B[选择一个折叠作为测试集,其余9个作为训练集];
    B --> C[训练分类器并评估];
    C --> D[重复步骤B和C,直到每个折叠都作为测试集使用过一次];
    D --> E[计算所有折叠的评估结果的平均值和方差];

通过交叉验证,可以避免训练集的偏差对评估结果的影响,更准确地评估分类算法的性能。例如,如果只使用一次划分的训练集和测试集进行评估,可能会因为训练集和测试集的分布不均匀而得到不准确的结果。而交叉验证可以通过多次使用不同的训练集和测试集,得到更稳定和可靠的评估结果。

9. 分析分类器脚本的使用场景

analyze_classifier_coverage.py 脚本可以帮助我们分析分类器对给定语料库的分类情况。以下是使用该脚本的具体步骤:
1. 准备工作 :确保已经有训练好的分类器保存为pickle文件,并且知道语料库的名称。
2. 运行脚本 :使用以下命令运行脚本:

$ python analyze_classifier_coverage.py movie_reviews --classifier classifiers/movie_reviews_NaiveBayes.pickle --metrics --speed
  1. 分析结果 :脚本会输出分类器的准确率、精确率、召回率等指标,以及平均分类时间。通过这些结果,我们可以了解分类器的性能和效率。

这个脚本的使用场景包括:
- 评估分类器的性能 :在训练好分类器后,使用该脚本可以快速评估分类器在给定语料库上的性能。
- 比较不同分类器 :可以使用该脚本对不同的分类器进行评估和比较,选择性能最好的分类器。
- 优化分类器 :通过分析分类器的错误分类情况,可以找出分类器的不足之处,从而进行优化。

10. 总结与展望

通过本文的介绍,我们详细了解了如何使用多个二元分类器构建多标签分类器,以及如何使用NLTK-Trainer工具进行分类器的训练和评估。多标签分类器可以为文本样本分配多个标签,适用于很多实际的文本分类任务。NLTK-Trainer工具提供了丰富的参数和功能,可以帮助我们灵活地训练和评估分类器。

在未来的文本分类任务中,我们可以进一步探索以下方向:
- 更复杂的特征工程 :除了高信息词和二元组,还可以尝试使用其他的特征工程方法,如词嵌入、词性标注等,以提高分类的准确性。
- 更先进的分类算法 :随着机器学习和深度学习的发展,不断有新的分类算法出现。可以尝试使用这些新的算法,如深度学习中的卷积神经网络(CNN)、循环神经网络(RNN)等,来提高分类的性能。
- 多模态分类 :结合文本、图像、音频等多种模态的信息进行分类,以应对更复杂的分类任务。

通过不断地探索和实践,我们可以在文本分类领域取得更好的成果。

(Kriging_NSGA2)克里金模型结合多目标遗传算法求最优因变量及对应的最佳自变量组合研究(Matlab代码实现)内容概要:本文介绍了克里金模型(Kriging)多目标遗传算法NSGA-II相结合的方法,用于求解最优因变量及其对应的最佳自变量组合,并提供了完整的Matlab代码实现。该方法首先利用克里金模型构建高精度的代理模型,逼近复杂的非线性系统响应,减少计算成本;随后结合NSGA-II算法进行多目标优化,搜索帕累托前沿解集,从而获得多个最优折衷方案。文中详细阐述了代理模型构建、算法集成流程及参数设置,适用于工程设计、参数反演等复杂优化问题。此外,文档还展示了该方法在SCI一区论文中的复现应用,体现了其科学性实用性。; 适合人群:具备一定Matlab编程基础,熟悉优化算法和数值建模的研究生、科研人员及工程技术人员,尤其适合从事仿真优化、实验设计、代理模型研究的相关领域工作者。; 使用场景及目标:①解决高计算成本的多目标优化问题,通过代理模型降低仿真次数;②在无法解析求导或函数高度非线性的情况下寻找最优变量组合;③复现SCI高水平论文中的优化方法,提升科研可信度效率;④应用于工程设计、能源系统调度、智能制造等需参数优化的实际场景。; 阅读建议:建议读者结合提供的Matlab代码逐段理解算法实现过程,重点关注克里金模型的构建步骤NSGA-II的集成方式,建议自行调整测试函数或实际案例验证算法性能,并配合YALMIP等工具包扩展优化求解能力。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值