半监督文本分类

Machine LearningMachine LearningBeginner
立即练习

This tutorial is from open-source community. Access the source code

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在本实验中,你将学习如何使用scikit-learn对文本数据集进行半监督分类。半监督学习是一种机器学习类型,其中模型在有标签和无标签的数据上进行训练。本实验将介绍如何使用自训练和标签传播算法进行半监督文本分类。我们将使用20新闻组数据集来训练和测试我们的模型。

虚拟机提示

虚拟机启动完成后,点击左上角切换到“笔记本”标签以访问Jupyter Notebook进行练习。

有时,你可能需要等待几秒钟让Jupyter Notebook完成加载。由于Jupyter Notebook的限制,操作验证无法自动化。

如果你在学习过程中遇到问题,请随时向Labby提问。课程结束后提供反馈,我们将立即为你解决问题。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL sklearn(("Sklearn")) -.-> sklearn/AdvancedDataAnalysisandDimensionalityReductionGroup(["Advanced Data Analysis and Dimensionality Reduction"]) ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) sklearn(("Sklearn")) -.-> sklearn/CoreModelsandAlgorithmsGroup(["Core Models and Algorithms"]) sklearn(("Sklearn")) -.-> sklearn/DataPreprocessingandFeatureEngineeringGroup(["Data Preprocessing and Feature Engineering"]) sklearn(("Sklearn")) -.-> sklearn/ModelSelectionandEvaluationGroup(["Model Selection and Evaluation"]) sklearn(("Sklearn")) -.-> sklearn/UtilitiesandDatasetsGroup(["Utilities and Datasets"]) sklearn/CoreModelsandAlgorithmsGroup -.-> sklearn/linear_model("Linear Models") sklearn/DataPreprocessingandFeatureEngineeringGroup -.-> sklearn/preprocessing("Preprocessing and Normalization") sklearn/DataPreprocessingandFeatureEngineeringGroup -.-> sklearn/feature_extraction("Feature Extraction") sklearn/DataPreprocessingandFeatureEngineeringGroup -.-> sklearn/pipeline("Pipeline") sklearn/ModelSelectionandEvaluationGroup -.-> sklearn/model_selection("Model Selection") sklearn/ModelSelectionandEvaluationGroup -.-> sklearn/metrics("Metrics") sklearn/AdvancedDataAnalysisandDimensionalityReductionGroup -.-> sklearn/semi_supervised("Semi-Supervised Learning") sklearn/UtilitiesandDatasetsGroup -.-> sklearn/datasets("Datasets") ml/FrameworkandSoftwareGroup -.-> ml/sklearn("scikit-learn") subgraph Lab Skills sklearn/linear_model -.-> lab-49281{{"半监督文本分类"}} sklearn/preprocessing -.-> lab-49281{{"半监督文本分类"}} sklearn/feature_extraction -.-> lab-49281{{"半监督文本分类"}} sklearn/pipeline -.-> lab-49281{{"半监督文本分类"}} sklearn/model_selection -.-> lab-49281{{"半监督文本分类"}} sklearn/metrics -.-> lab-49281{{"半监督文本分类"}} sklearn/semi_supervised -.-> lab-49281{{"半监督文本分类"}} sklearn/datasets -.-> lab-49281{{"半监督文本分类"}} ml/sklearn -.-> lab-49281{{"半监督文本分类"}} end

加载数据集

我们将使用20新闻组数据集,该数据集包含约18,000篇关于20个主题的新闻组文章。在这一步中,我们将加载数据集并打印出有关它的一些基本信息。

import numpy as np
from sklearn.datasets import fetch_20newsgroups

## 加载前五个类别的数据集
data = fetch_20newsgroups(
    subset="train",
    categories=[
        "alt.atheism",
        "comp.graphics",
        "comp.os.ms-windows.misc",
        "comp.sys.ibm.pc.hardware",
        "comp.sys.mac.hardware",
    ],
)

## 打印有关数据集的信息
print("%d documents" % len(data.filenames))
print("%d categories" % len(data.target_names))

创建监督学习管道

在这一步中,我们将创建一个用于监督学习的管道。该管道将由一个CountVectorizer(用于将文本数据转换为词元计数矩阵)、一个TfidfTransformer(用于对计数矩阵应用词频 - 逆文档频率归一化)和一个SGDClassifier(用于训练模型)组成。

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.linear_model import SGDClassifier
from sklearn.pipeline import Pipeline

## SGDClassifier的参数
sdg_params = dict(alpha=1e-5, penalty="l2", loss="log_loss")

## CountVectorizer的参数
vectorizer_params = dict(ngram_range=(1, 2), min_df=5, max_df=0.8)

## 创建管道
pipeline = Pipeline(
    [
        ("vect", CountVectorizer(**vectorizer_params)),
        ("tfidf", TfidfTransformer()),
        ("clf", SGDClassifier(**sdg_params)),
    ]
)

训练和评估监督模型

在这一步中,我们将把数据集拆分为训练集和测试集,然后训练并评估我们在第二步中创建的监督模型管道。

from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score

## 将数据集拆分为训练集和测试集
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y)

## 训练并评估监督模型管道
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)
print(
    "测试集上的微平均F1分数: %0.3f"
    % f1_score(y_test, y_pred, average="micro")
)

创建自训练管道

在这一步中,我们将创建一个使用自训练的半监督学习管道。该管道将与监督管道类似,但我们将使用SelfTrainingClassifier而不是SGDClassifier。

from sklearn.semi_supervised import SelfTrainingClassifier

## 创建自训练管道
st_pipeline = Pipeline(
    [
        ("vect", CountVectorizer(**vectorizer_params)),
        ("tfidf", TfidfTransformer()),
        ("clf", SelfTrainingClassifier(SGDClassifier(**sdg_params), verbose=True)),
    ]
)

训练和评估自训练模型

在这一步中,我们将对20%的已标注数据使用自训练方法。我们将随机选择20%的已标注数据,在这些数据上训练模型,然后使用该模型为其余未标注数据预测标签。

import numpy as np

## 选择20%的训练数据
y_mask = np.random.rand(len(y_train)) < 0.2
X_20, y_20 = map(
    list, zip(*((x, y) for x, y, m in zip(X_train, y_train, y_mask) if m))
)

## 将未掩码的子集设置为未标注
y_train[~y_mask] = -1

## 训练并评估自训练管道
st_pipeline.fit(X_train, y_train)
y_pred = st_pipeline.predict(X_test)
print(
    "测试集上的微平均F1分数: %0.3f"
    % f1_score(y_test, y_pred, average="micro")
)

创建标签传播管道

在这一步中,我们将创建一个使用标签传播的半监督学习管道。该管道将与监督管道类似,但我们将使用标签传播算法代替SGDClassifier。

from sklearn.semi_supervised import LabelSpreading
from sklearn.preprocessing import FunctionTransformer

## 创建标签传播管道
ls_pipeline = Pipeline(
    [
        ("vect", CountVectorizer(**vectorizer_params)),
        ("tfidf", TfidfTransformer()),
        ("toarray", FunctionTransformer(lambda x: x.toarray())),
        ("clf", LabelSpreading()),
    ]
)

训练和评估标签传播模型

在这一步中,我们将对20%的已标注数据使用标签传播方法。我们将随机选择20%的已标注数据,在这些数据上训练模型,然后使用该模型为其余未标注数据预测标签。

## 训练并评估标签传播管道
ls_pipeline.fit(X_train, y_train)
y_pred = ls_pipeline.predict(X_test)
print(
    "测试集上的微平均F1分数: %0.3f"
    % f1_score(y_test, y_pred, average="micro")
)

总结

在这个实验中,我们学习了如何使用scikit-learn对文本数据集进行半监督分类。我们使用了自训练和标签传播算法来训练和测试我们的模型。当可用的标注数据量有限时,半监督学习会很有用,并且它可以通过纳入未标注数据来帮助提高模型的性能。