半监督文本数据分类

在本例中,将探讨如何使用半监督学习技术对20个新闻组数据集进行分类。这个数据集将自动下载。可以通过指定类别名称或设置为None来调整类别数量,以获取全部20个类别。数据集中包含2823个文档,涵盖5个类别。

全监督SGD分类器在100%数据上的表现

在全监督学习中,使用SGD分类器对所有训练样本进行训练。训练样本数量为2117,未标记样本数量为0。在测试集上的微平均F1分数为0.885。

全监督SGD分类器在20%训练数据上的表现

当训练样本数量减少到411,未标记样本数量为0时,SGD分类器在测试集上的微平均F1分数下降到0.773。这说明训练样本数量对模型性能有显著影响。

自训练分类器在20%训练数据上的表现

自训练分类器在只有20%的训练数据上进行训练,其余数据为未标记。在迭代过程中,分类器逐渐为未标记样本添加标签。经过10次迭代,分类器在测试集上的微平均F1分数达到0.834,高于仅使用20%标记数据的全监督SGD分类器

标签传播在20%数据上的表现

标签传播方法同样在20%的训练数据上进行训练,其余数据为未标记。然而,这种方法在测试集上的微平均F1分数仅为0.644,低于自训练分类器。

以下是使用Python和scikit-learn库实现上述半监督分类方法的代码示例。首先,导入必要的库和函数。

import numpy as np from sklearn.datasets import fetch_20newsgroups from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer from sklearn.linear_model import SGDClassifier from sklearn.metrics import f1_score from sklearn.model_selection import train_test_split from sklearn.pipeline import Pipeline from sklearn.preprocessing import FunctionTransformer from sklearn.semi_supervised import LabelSpreading, SelfTrainingClassifier

接下来,加载20个新闻组数据集的前五个类别,并设置SGD分类器的参数。然后,构建了三个管道:全监督管道、自训练管道和标签传播管道。

# 加载数据集 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)) # 参数设置 sdg_params = dict(alpha=1e-5, penalty="l2", loss="log_loss") 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)), ]) # 自训练管道 st_pipeline = Pipeline([ ("vect", CountVectorizer(**vectorizer_params)), ("tfidf", TfidfTransformer()), ("clf", SelfTrainingClassifier(SGDClassifier(**sdg_params), verbose=True)), ]) # 标签传播管道 ls_pipeline = Pipeline([ ("vect", CountVectorizer(**vectorizer_params)), ("tfidf", TfidfTransformer()), ("toarray", FunctionTransformer(lambda x: x.toarray())), ("clf", LabelSpreading()), ])

最后,定义了一个函数来评估和打印分类器的性能指标,并在主函数中调用这个函数来训练和评估分类器。

def eval_and_print_metrics(clf, X_train, y_train, X_test, y_test): print("Number of training samples:", len(X_train)) print("Unlabeled samples in training set:", sum(1 for x in y_train if x == -1)) clf.fit(X_train, y_train) y_pred = clf.predict(X_test) print("Micro-averaged F1 score on test set: %0.3f" % f1_score(y_test, y_pred, average="micro")) print("-"*10) print() if __name__ == "__main__": X, y = data.data, data.target X_train, X_test, y_train, y_test = train_test_split(X, y) print("Supervised SGDClassifier on 100% of the data:") eval_and_print_metrics(pipeline, X_train, y_train, X_test, y_test) # 选择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))) print("Supervised SGDClassifier on 20% of the training data:") eval_and_print_metrics(pipeline, X_20, y_20, X_test, y_test) # 将非掩码子集设置为未标记 y_train[~y_mask] = -1 print("SelfTrainingClassifier on 20% of the training data (rest is unlabeled):") eval_and_print_metrics(st_pipeline, X_train, y_train, X_test, y_test) print("LabelSpreading on 20% of the data (rest is unlabeled):") eval_and_print_metrics(ls_pipeline, X_train, y_train, X_test, y_test)
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485