Python中Scikit-learn如何实现半监督学习_利用LabelPropagation
LabelPropagation要求数据具备局部平滑性,特征须标准化,未标记样本标签必须为-1,且需至少两个已标记类别;拟合用transduction_获取全部预测,不提供置信度,对噪声敏感。
LabelPropagation 在 scikit-learn 中的适用前提
LabelPropagation 不是万能半监督工具,它要求数据天然具备“局部平滑性”——即相似样本大概率共享标签。如果特征空间中同类样本离散、或距离度量失真(比如未标准化的混合类型特征),算法会传播错误标签。它默认使用 RBF 核构建相似图,对 n_neighbors 和 gamma 敏感,且不支持稀疏标签矩阵(即不能只给部分样本标 0/1,其余为 np.nan;必须显式用 -1 表示未标记)。
实际使用前务必检查:
- 特征已标准化(
StandardScaler或MinMaxScaler),尤其当量纲差异大时 - 未标记样本用
-1填充y,不是None、np.nan或字符串 - 训练集里至少有 2 个不同类别的已标记样本,否则图拉普拉斯矩阵奇异
正确初始化和拟合 LabelPropagation
LabelPropagation 的关键参数不是越多越好。默认 kernel='rbf' 足够多数场景;若改用 'knn',需设 n_neighbors(通常 5–10),但要注意小数据集上过小的 n_neighbors 会导致图不连通。拟合时传入的是完整 X(含未标记样本)和带 -1 的 y,不是只喂已标记子集。
典型写法:
from sklearn.semi_supervised import LabelPropagation from sklearn.preprocessing import StandardScalerX_scaled = StandardScaler().fit_transform(X) y_semi = y.copy() y_semi[unlabeled_indices] = -1 # 必须是整数 -1
lp = LabelPropagation(kernel='rbf', gamma=20, max_iter=1000) lp.fit(X_scaled, y_semi) ypred = lp.transduction # 注意:不是 predict(),是 transduction_ 属性
注意:transduction_ 是模型对全部输入样本的预测结果(含原先未标记的),而 predict() 只能用于新样本——但它内部仍依赖训练时构建的图,泛化能力弱,一般不用。
LabelPropagation 输出结果的解读与陷阱
LabelPropagation 的输出 transduction_ 是硬标签(int 类别),不提供置信度。它不保证所有未标记样本都被重新赋值——若某样本在相似图中孤立(如 KNN 图中邻居全未标记),其标签可能保持为 -1(取决于收敛行为)。更隐蔽的问题是:它对噪声标签极其敏感,一个错标样本可能污染整片邻域。
Python 3.14.3
微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。
排查建议:
- 检查
lp.n_iter_是否达到max_iter,若是,说明未收敛,可调大max_iter或减小gamma - 对比
transduction_[labeled_indices]和原始y[labeled_indices],确认无已标记样本被覆盖(正常情况下不会,但若gamma过大或图构造异常可能发生) - 用
lp.score(X_scaled[labeled_indices], y[labeled_indices])看已标记部分准确率,骤降往往意味着传播失控
LabelPropagation vs LabelSpreading:选哪个?
两者核心区别在目标函数:LabelPropagation 是硬约束(已标记点标签绝对固定),LabelSpreading 是软约束(允许已标记点在迭代中微调,加了正则项)。实践中,LabelSpreading 更鲁棒,对参数不敏感,且默认就带 alpha 控制已标记点影响力(推荐从 alpha=0.2 试起);而 LabelPropagation 更适合你完全信任已标注样本、且数据流形结构非常清晰的场景。
简单判断依据:
- 如果你发现
LabelPropagation对已标记样本的预测出错,立刻换LabelSpreading - 如果你需要概率输出,两个都不行——得接
predict_proba的替代方案(如用传播后的伪标签训一个RandomForestClassifier) -
LabelSpreading的kernel参数行为一致,但多一个alpha,少一个gamma(RBF 下用gamma,KNN 下不用)
真正麻烦的从来不是调参,而是未标记样本的分布偏移——如果它们和已标记样本根本不在同一子流形上,再准的图模型也只会把错误扩散得更自信。