scikit-learn 半监督学习完全指南:SelfTrainingClassifier、LabelPropagation 与 LabelSpreading 的原理与实践
scikit-learn 半监督学习完全指南SelfTrainingClassifier、LabelPropagation 与 LabelSpreading 的原理与实践【免费下载链接】scikit-learnscikit-learn: machine learning in Python项目地址: https://gitcode.com/gh_mirrors/sc/scikit-learn在真实业务中数据标注往往是最昂贵的环节——大量样本未被标注只有一小部分带标签。scikit-learn 的sklearn.semi_supervised模块正是为此而生它提供的SelfTrainingClassifier、LabelPropagation和LabelSpreading三种估计器能够利用海量无标签数据刻画数据分布的形状从而在标注样本极少的情况下显著提升泛化性能。读完本文你将掌握这三种算法的适用场景、核心参数、调用方式与底层实现原理并能在自己的分类任务中直接复现官方示例。半监督学习概念与数据约定半监督学习Semi-supervised learning指的是训练数据中部分样本没有标签的情形。sklearn.semi_supervised中的估计器能够利用这部分额外的无标签数据更好地捕捉底层数据分布的形状从而对新样本泛化得更好。当标注点很少、无标注点很多时这类算法通常表现出色。无标签样本的标识-1使用fit方法训练模型时必须为无标签样本分配一个标识符本模块使用的标识符是整数-1。也就是说你只需要把不知道标签的样本在y中记为-1其余样本保持真实标签即可。需要注意一个容易踩坑的细节如果使用字符串标签y的 dtype 必须为object这样数组才能同时容纳字符串和整数-1。这一点在 SelfTrainingClassifier 的 fit 实现中有直接体现源码会对y.dtype.kind in [U, S]即 Unicode 或字节字符串类型抛出ValueError提示用户改用 object 类型。算法假设半监督算法要获得性能提升必须对数据集分布做出假设例如流形假设处于同一结构区域的无标签样本与已标签样本大概率属于同一类别。因此这类算法并非在任意数据上都有效使用时需要结合数据本身的分布结构判断是否适用。自训练Self Training自训练实现基于 David Yarowsky 1995 年提出的算法Unsupervised word sense disambiguation rivaling supervised methodsACL 95。核心思想很直观把任意实现了predict_proba的有监督分类器包装成半监督分类器让它逐步自学无标签数据。工作流程SelfTrainingClassifier的迭代逻辑见 fit 实现如下初始化复制y为transduction_初始化labeled_iter_原始有标签样本记为迭代 0无标签样本记为 -1迭代循环在max_iter限制内反复执行——用当前已标签样本训练底层estimator对无标签样本调用predict_proba得到概率依据选择准则挑出置信度最高的子集把子集的预测标签写入transduction_并将其标记为已标签记录迭代轮次终止直到没有新样本被选中、全部样本都被标注、或达到max_iter最终拟合用扩充后的标签集对底层估计器做最后一次拟合存入estimator_属性。max_iter可以设为None此时算法会一直迭代直到所有样本都有标签或某轮没有选出新样本为止。参数详解SelfTrainingClassifier的完整参数与默认值如下均可在 类定义与参数约束表中确认参数默认值说明estimatorNone任意实现了fit和predict_proba的监督分类器。fit时会克隆传入的估计器训练结果保存在estimator_。注意estimator是 1.6 版本中替代base_estimator引入的源码threshold0.75选择准则为threshold时的判定阈值取值区间[0, 1)。预测概率超过该值的伪标签会被加入训练集criterionthreshold选择准则二选一threshold选取概率超过阈值的所有样本k_best每次选取概率最高的k_best个样本k_best10每次迭代添加的样本数仅在criterionk_best时生效必须是正整数max_iter10最大迭代次数需大于等于 0设为None时持续迭代直到没有新伪标签或全部样本都被标注verboseFalse是否输出每轮迭代添加的标签数量从 参数约束可以看到threshold被限定在[0, 1)左闭区间k_best必须为正整数max_iter为不小于 0 的整数或None。另外约束中刻意不要求estimator在构造时就具备predict_proba以允许传入拟合后才暴露predict_proba的元估计器如CalibratedClassifierCV。训练后属性拟合完成后可以访问以下属性见 类文档estimator_最终拟合好的底层估计器transduction_形状为(n_samples,)记录最终拟合所用的全部标签含迭代过程中加入的伪标签labeled_iter_形状为(n_samples,)记录每个样本在哪一轮被标注——0 表示原始就有标签-1 表示从未被标注n_iter_实际执行的自训练轮数termination_condition_停止原因取值为max_iter达到最大迭代、no_change某轮没有新标签产生或all_labeled所有无标签样本都在max_iter之前被标注完毕。这些属性在官方测试中有严格验证例如 test_self_training.py 断言有标签样本的labeled_iter_ 0、原始标签在训练中不被改变、且max(labeled_iter_) n_iter_ max_itertest_k_best则验证了k_best模式下每轮恰好添加k_best个标签直至全部标注。使用示例Iris 半监督分类官方 docstring 提供了一个最小可复现示例import numpy as np from sklearn import datasets from sklearn.semi_supervised import SelfTrainingClassifier from sklearn.linear_model import LogisticRegression rng np.random.RandomState(42) iris datasets.load_iris() # 随机将 30% 的标签置为 -1无标签 random_unlabeled_points rng.rand(iris.target.shape[0]) 0.3 iris.target[random_unlabeled_points] -1 clf LogisticRegression() self_training_model SelfTrainingClassifier(clf) self_training_model.fit(iris.data, iris.target)拟合后可用predict、predict_proba、decision_function、predict_log_proba和score等方法进行推理——这些方法都通过available_if按底层估计器的能力条件暴露见 源码例如底层没有predict_proba时SelfTrainingClassifier.predict_proba也不会被暴露。阈值选择对效果的影响threshold的选择直接决定自训练效果官方示例 plot_self_training_varying_threshold.py 用乳腺癌症数据集569 个样本中仅保留 50 个标签做了系统实验阈值过低约 0.4~0.5模型会吸收大量低置信度样本其中混入不少错误标签导致精度下降此时几乎所有样本都被标注且只需一轮迭代阈值过高约 0.9~1.0几乎没有样本能通过置信门槛模型退化为普通的有监督分类器——例如阈值为 0.9999 时精度与纯监督学习一致最优区间约 0.7 附近达到精度峰值。另外示例使用了CalibratedClassifierCV(SVC(...))作为底层估计器这印证了文档中的建议使用threshold准则时底层分类器的概率校准calibration至关重要未经校准的概率值不宜直接与阈值比较。可参考 文档中的校准章节 了解CalibratedClassifierCV的用法。底层估计器选择与predict_proba语义在 plot_semi_supervised_versus_svm_iris.py 中SelfTrainingClassifier与SVC基估计器配对并外接CalibratedClassifierCV与LabelSpreading在 Iris 数据上对比决策边界。当标注数据达到 100% 时SelfTrainingClassifier退化为一个纯监督的SVC因为没有无标签样本可供打伪标签。关于predict_proba的语义示例给出了关键结论SelfTrainingClassifier的predict_proba只是直接委托给最终拟合好的estimator_见 predict_proba 实现因此推理阶段不需要存储训练数据决策规则完全由底层模型承载。标签传播Label Propagation标签传播Label Propagation是一族基于图的半监督推理算法scikit-learn 提供了两个模型LabelPropagation与LabelSpreading。两者都先在输入数据集的所有样本含无标签样本上构造相似度图再沿图将标签从已标注样本扩散到未标注样本。两个模型的差异图矩阵与钳制Clamping两个模型的核心差异有二相似度矩阵的处理方式LabelPropagation直接使用从数据构造的原始相似度矩阵不做额外修改LabelSpreading则最小化一个带正则化性质的损失函数迭代使用的是原始图的修正版本——通过计算归一化图拉普拉斯矩阵normalized graph Laplacian来归一化边权重。这一过程与 scikit-learn 中的谱聚类spectral clustering共用同一套工具函数源码中使用sklearn.utils.fixes.laplacian。因此LabelSpreading对噪声通常更鲁棒。标签钳制clamping方式钳制允许算法在某种程度上改变真实标注数据的权重。LabelPropagation执行硬钳制hard clamping即钳制因子alpha 0已标注样本的标签分布在迭代中保持不变fit 实现中y_static直接回填原始分布LabelSpreading采用软钳制soft clampingalpha默认 0.2。这意味着迭代时始终保留 80% 的原始标签分布算法只能在 20% 的范围内调整置信度源码中每一轮label_distributions_ alpha * 传播结果 y_static。alpha的语义可以这样理解alpha0表示完全保留初始标签信息alpha1表示完全用邻居信息替换初始标签。源码约束alpha必须落在开区间(0, 1)内见 LabelSpreading 参数约束。内置核函数两个标签传播模型都内置两种核函数选择会同时影响可扩展性和算法性能核公式参数图矩阵特征rbfexp(-gamma * |x-y|^2)gamma 0gamma默认 20全连接图稠密矩阵knn1[x 属于 x 的 k 近邻]n_neighbors默认 7稀疏邻接图两者在内存与运行时间上有显著差异源码注释见 _label_propagation.pyRBF 核生成全连接图内存中由稠密矩阵表示大小约为O(N^2)N 为样本总数每一轮迭代还要执行完整的矩阵乘法复杂度约O(N^3)在大数据集上运行时间可能长得无法接受KNN 核生成稀疏矩阵规模约O(k*N)内存占用小得多能大幅缩短运行时间。此外kernel参数还接受任意可调用对象只要该函数接受两个形状均为(n_samples, n_features)的输入并返回形状为(n_samples, n_samples)的权重矩阵即可见 参数文档与_get_kernel的实现。参数与属性一览两个模型的公共参数继承自BaseLabelPropagation见 基类参数LabelPropagation默认值LabelSpreading默认值说明kernelrbfrbfknn、rbf或自定义可调用对象gamma2020RBF 核参数须大于 0n_neighbors77KNN 核参数严格正整数alpha无固定硬钳制0.2软钳制因子仅LabelSpreading可用max_iter100030最大迭代次数tol1e-31e-3收敛容差分布变化小于该值时认为达到稳态n_jobsNoneNone并行任务数-1表示使用全部处理器拟合后主要属性X_输入数据、classes_类别标签、label_distributions_形状(n_samples, n_classes)的类别分布、transduction_fit 过程中为每个样本分配的标签、n_iter_实际迭代轮数。图构建与迭代的源码视角LabelPropagation._build_graph源码直接用核函数生成亲和矩阵然后按行归一化affinity_matrix / normalizer[:, np.newaxis]得到行随机矩阵用于迭代LabelSpreading._build_graph源码对亲和矩阵计算归一化拉普拉斯csgraph_laplacian(affinity_matrix, normedTrue)取负号并将对角线置 0 后作为迭代矩阵两者在 fit 的迭代循环中反复执行label_distributions_ graph_matrix label_distributions_直到分布变化小于tol若达到max_iter仍未收敛会发出ConvergenceWarning警告。应用示例示例 1结构学习同心圆。官方示例 plot_label_propagation_structure.py 生成 200 个样本的同心圆数据只保留两个标注样本外圈 0、内圈 1其余全部标为 -1import numpy as np from sklearn.datasets import make_circles from sklearn.semi_supervised import LabelSpreading n_samples 200 X, y make_circles(n_samplesn_samples, shuffleFalse) outer, inner 0, 1 labels np.full(n_samples, -1.0) labels[0] outer labels[-1] inner label_spread LabelSpreading(kernelknn, alpha0.8) label_spread.fit(X, labels) # 查看每个样本被传播到的标签 output_labels label_spread.transduction_这个例子直观展示了文档中无标签观测的结构与类别结构一致因此类别标签可以传播到无标签观测的论断——由于外圈与内圈各自位于独立形状中仅凭两个标签即可让标签沿流形正确传播。示例 2标签稀缺下的新闻组文本分类。官方示例 plot_semi_supervised_newsgroups.py 在 20 Newsgroups 数据集前 5 个类别上对比四种方案100% 标注的监督SGDClassifier、20% 标注的监督基线、SelfTrainingClassifier20% 标注 80% 无标签、LabelSpreading同样 20% 80%。无标签样本通过y_train_semi[~y_mask] -1掩码生成评测指标为 micro 平均 F1。该示例与文档开头的Examples列表一一对应是理解半监督方法如何用无标签数据追赶全监督上限的绝佳入口。示例 3标签传播数字识别。plot_label_propagation_digits.py与plot_label_propagation_digits_active_learning.py均在 examples/semi_supervised/ 目录下演示了在手写数字数据集上使用标签传播后者还结合了主动学习active learning思想在迭代中挑选最有信息量的样本进行标注。半监督分类器的推理语义对比在 plot_semi_supervised_versus_svm_iris.py 的后半部分官方对两类方法的predict_proba语义做了精确澄清LabelSpreading.predict_proba对新样本先计算它与所有训练样本的 RBF 相似度权重再对label_distributions_做加权平均并归一化。该示例用手写方式复现了这一过程并与 API 输出对比验证。需要特别注意的是这些概率是基于图的分数graph-based scores并非校准后的后验概率不要过度解读其绝对值。此外标签传播的推理必须保留训练数据X_因为预测依赖训练集上的标签分布。SelfTrainingClassifier.predict_proba直接委托给最终拟合的estimator_训练结束后推理不依赖训练数据。何时选择哪种算法算法适用场景优势注意点SelfTrainingClassifier已有成熟的有监督分类器希望直接复用任意predict_proba分类器即插即用推理无需存储训练集threshold/k_best灵活控制置信策略依赖底层模型概率质量threshold准则下需概率校准迭代可能放大早期错误伪标签LabelPropagation数据分布有明显流形/聚类结构标注极少硬钳制保证已标注样本不被改动max_iter默认 1000容忍更慢收敛RBF 核下内存与算力开销大O(N^2)内存、O(N^3)迭代预测依赖训练集LabelSpreading数据含噪声需要更强的鲁棒性软钳制 归一化拉普拉斯对噪声更稳健同样存在图构建开销alpha需权衡保留原始标签与采纳邻居信息的比例参考资料David Yarowsky.Unsupervised word sense disambiguation rivaling supervised methods.Proceedings of the 33rd annual meeting on Association for Computational Linguistics (ACL 95), 189-196. 这是SelfTrainingClassifier的算法出处见 docstring 引用。Yoshua Bengio, Olivier Delalleau, Nicolas Le Roux.Semi-Supervised Learning(2006), pp. 193-216.Olivier Delalleau, Yoshua Bengio, Nicolas Le Roux.Efficient Non-Parametric Function Induction in Semi-Supervised Learning.AISTAT 2005.Xiaojin Zhu, Zoubin Ghahramani.Learning from labeled and unlabeled data with label propagation.CMU-CALD-02-107LabelPropagation的出处见 类引用。Dengyong Zhou, Olivier Bousquet, Thomas Navin Lal, Jason Weston, Bernhard Schoelkopf.Learning with local and global consistency(2004)LabelSpreading的出处见 类引用。进一步探索三个估计器的完整 API 与全部示例模块导出定义见 sklearn/semi_supervised/init.py导出LabelPropagation、LabelSpreading、SelfTrainingClassifier三个类源码实现sklearn/semi_supervised/_self_training.py、sklearn/semi_supervised/_label_propagation.py测试用例可验证本文所述行为test_self_training.py、test_label_propagation.py官方示例全部位于 examples/semi_supervised/ 目录包括结构传播、数字识别、主动学习、新闻组对比与阈值影响分析。【免费下载链接】scikit-learnscikit-learn: machine learning in Python项目地址: https://gitcode.com/gh_mirrors/sc/scikit-learn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →