半监督学习

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录


介绍

半监督学习(Semi-Supervised Learning,SSL)是机器学习领域中的一个重要分支,它结合了监督学习和无监督学习的思想,用于处理标签数据稀缺而无标签数据丰富的场景。

常用方法:

  • Self Training自训练
  • Label Propagation标签传播
  • Label Spreading标签扩散

一、Self Training自训练

1、介绍

Self Training自训练是一种简单的半监督学习方法,它首先使用已标记的数据训练一个监督学习模型。然后,该模型用于预测未标记数据的标签。预测最自信的标签可以被选择添加到训练集中,然后模型在新的、更大的训练集上重新训练。先训练一个小模型,再继续预测标签,类似于迁移学习。当无标签数据和有标签数据分布相同时,使用自训练方法效果最佳。

2、代码示例

  • 读入数据

    from IPython.core.interactiveshell import InteractiveShell
    InteractiveShell.ast_node_interactivity = "all"

    import numpy as np
    import pandas as pd
    import warnings
    warnings.filterwarnings("ignore")

    数据预处理计算函数

    def preprocessing(df):
    from sklearn.impute import SimpleImputer
    from sklearn.preprocessing import StandardScaler
    from sklearn.pipeline import Pipeline
    from sklearn.preprocessing import OrdinalEncoder
    from sklearn.compose import ColumnTransformer

    复制代码
      cat_cols= df.select_dtypes(include=["object"])   # 分类型变量
      num_cols= df.select_dtypes(include=["int", "float"])   # 数值型变量
    
      # 连续型数据
      num_imp= SimpleImputer(strategy='mean')  # 缺失值
      num_std= StandardScaler()  # 标准化
      num_pipeline= Pipeline(steps=[("num_imp", num_imp), ("num_std", num_std)])
      # 分类型数据
      cat_imp= SimpleImputer(strategy="most_frequent")  # 缺失值
      cat_encode= OrdinalEncoder()   # 数据编码
      cat_pipeline= Pipeline(steps=[("cat_imp", cat_imp), ("cat_encode", cat_encode)])
    
      col_trans= ColumnTransformer(transformers=[("num_pipeline", num_pipeline, num_cols.columns),
                                             ("cat_pipeline", cat_pipeline, cat_cols.columns),])
      # 数据集处理的计算
      transfer= col_trans.fit(df)
      return transfer

    读入数据

    raw_data= pd.read_csv('半监督学习.csv')
    labels= raw_data.pop("resp_flag") # 标签

  • 缺失数据对比

    print("缺失值/总样本:"+str(labels.isnull().sum())+"/"+str(len(labels)))

  • 数据处理
    注意:切分的测试数据集一定是有标签的样本

    sklearn中的半监督学习算法要求,所有缺失的标签必须用-1填充

    labels_fill= labels.fillna(-1)

    特征数据处理

    transfer= preprocessing(raw_data)
    data_trans= transfer.transform(raw_data)

    data_concat= pd.concat([labels_fill, pd.DataFrame(data_trans)], axis= 1)

    保存一部分有标签样本作为测试集

    mask_labeled= (labels_fill != -1)
    mask_unlabeled= (labels_fill == -1)

    data_labeled= data_concat[mask_labeled]
    data_unlabeled= data_concat[mask_unlabeled]

    切分测试集

    from sklearn.model_selection import train_test_split
    train, test= train_test_split(data_labeled, test_size=0.2, stratify= data_labeled["resp_flag"], random_state= 42)

    Xtrain= pd.concat([train, data_unlabeled])
    Ytrain= Xtrain.pop("resp_flag")

  • 使用模型

    from sklearn.ensemble import RandomForestClassifier
    RF= RandomForestClassifier(oob_score=True)

    Self Training

    from sklearn.semi_supervised import SelfTrainingClassifier
    RF_self_training= SelfTrainingClassifier(RF)
    RF_self_training.fit(Xtrain, Ytrain)

    测试集模型评估

    Xtest= test
    Ytest= Xtest.pop("resp_flag")

    from sklearn.metrics import roc_auc_score
    print("AUC: ", roc_auc_score(Ytest, RF_self_training.predict_proba(Xtest)[:, 1]))

3、参数解释

复制代码
base_estimator: BaseEstimator,# 基学习器
threshold: Float = 0.75,# 默认阈值0.75,大于0.75,小于0.25会被打标签,该参数比k_best更为常用
criterion: Literal['threshold', 'k_best'] = "threshold",# 默认值threshold,为该值时和threshold参数相同,即设阈值,k_best超参数阈值,如为10,则不考虑预测概率,只取排名前10的打标签
k_best: Int = 10,# 超参数阈值,如为10,则不考虑预测概率,只取排名前10的打标签
max_iter: int | None = 10,# 最大迭代次数
verbose: bool = False

二、Label Propagation(标签传播)

在sklearn中,基于图算法的半监督学习有Label Propagation和Label Spreading两种。他们的主要区别是第二种方法带有正则化机制。

1、介绍

Label Propagation(标签传播)基本原理:Label Propagation算法基于图理论。算法首先构建一个图,其中每个节点代表一个数据点,无论是标记的还是未标记的。节点之间的边代表数据点之间的相似性。算法的目的是通过图传播标签信息,使未标记数据获得标签。

关键特点:

相似性度量:通常使用K近邻(KNN)或者基于核的方法来定义数据点之间的相似性。

标签传播:标签信息从标记数据点传播到未标记数据点,通过迭代过程实现。

适用场景:适合于数据量较大、标记数据稀缺的情况。

  • 以环形数据为例,绿色全是为打标签的数据:

    打标签后数据结果如图:

    from sklearn.semi_supervised import LabelPropagation

    label_propagation = LabelPropagation(kernel="knn")
    label_propagation.fit(X, labels)

    output= np.asarray(label_propagation.transduction_)
    outer_numbers = np.where(output == outer)[0]
    inner_numbers = np.where(output == inner)[0]

    plt.figure(figsize=(4, 4))
    plt.scatter(X[outer_numbers, 0], X[outer_numbers, 1],)
    plt.scatter(X[inner_numbers, 0], X[inner_numbers, 1],);

2、代码示例

复制代码
from sklearn.semi_supervised import LabelPropagation

label_propagation = LabelPropagation(kernel="knn")
label_propagation.fit(Xtrain, Ytrain)

Ytrain_propagation= label_propagation.transduction_

from sklearn.ensemble import RandomForestClassifier
RF_propagation= RandomForestClassifier(oob_score=True)
RF_propagation.fit(Xtrain, Ytrain_propagation)

print("AUC: ", roc_auc_score(Ytest, RF_propagation.predict_proba(Xtest)[:, 1]))

3、参数解释

复制代码
    kernel: ((...) -> Any) | Literal['knn', 'rbf'] = "rbf",# knn:k近邻,RBF核用于计算图中节点之间的相似度。这些相似度值随后用于传播标签信息,从而根据相邻节点的标签来预测未知节点的标签,rbf函数和正态分布比较相似
    *,
    gamma: Float = 20, # rbf函数的系数,可以简单理解为正态分布的方差
    n_neighbors: Int = 7, # 附近的7个样本,哪个样本多,就打成哪个标签,为knn时生效
    max_iter: Int = 1000,# 迭代次数
    tol: float = 0.001,# 算法收敛的阈值
    n_jobs: Int | None = None

三、Label Spreading(标签扩散)

1、介绍

基本原理:Label Spreading和Label Propagation非常相似,但在处理标签信息和正则化方面有所不同。它同样基于构建图来传播标签。

关键特点:

正则化机制:Label Spreading引入了正则化参数,可以控制标签传播的过程,使算法更加健壮。

稳定性:由于正则化的存在,Label Spreading在面对噪声数据时通常比Label Propagation更稳定。

适用场景:同样适用于有大量未标记数据的情况,尤其当数据包含噪声或者不完全标记时。

2、代码示例

复制代码
from sklearn.semi_supervised import LabelSpreading

label_spreading = LabelSpreading(kernel="knn", alpha= 0.2)
label_spreading.fit(Xtrain, Ytrain)

Ytrain_spreading= label_spreading.transduction_

from sklearn.ensemble import RandomForestClassifier
RF_spreading= RandomForestClassifier(oob_score=True)
RF_spreading.fit(Xtrain, Ytrain_spreading)

print("AUC: ", roc_auc_score(Ytest, RF_spreading.predict_proba(Xtest)[:, 1]))

3、参数解释

复制代码
	kernel: ((...) -> Any) | Literal['rbf', 'knn'] = "rbf",
    *,
    gamma: Float = 20,
    n_neighbors: Int = 7,
    alpha: Float = 0.2, # 正则化参数,用于控制算法对标签平滑的程度,值较小时,会更强调邻居节点信息,值较大时,更倾向于保持原始标签
    max_iter: Int = 30,
    tol: Float = 0.001, # 算法收敛的阈值
    n_jobs: Int | None = None
相关推荐
世人万千丶3 小时前
鸿蒙日志体系高级应用:HiLog分级输出/隐私脱敏/远程日志采集/线上问题精准溯源方案
学习·harmonyos·鸿蒙
奔跑中的小象3 小时前
统信UOS + 天数AI卡部署SGLang服务手册
人工智能·uos·sglang·天数智芯
DevSecOps选型指南3 小时前
中国版Mythos,为何是悬镜安全灵脉CodeAI?
人工智能·安全
Shockang4 小时前
LangGraph 状态机实战
人工智能
DLYSB_4 小时前
存储运维实战:基于 Ceph Event 监听与 Python 适配器的分布式存储健康度物理声光响应架构
运维·ceph·python·报警灯
刹那芳华19924 小时前
循环神经网络的从零开始实现(RNN)
人工智能·rnn·深度学习
阿童木写作4 小时前
跨境图片翻译工具多合一,批量图片视频字幕翻译加智能抠图
人工智能·python·音视频·语音识别
科技之门4 小时前
AI3D从建模到贴图、绑骨和动画的完整流程怎么做?V2Fun完整工作流指南
人工智能·3d·贴图
宇宙第一小趴菜4 小时前
二、机器学习的应用领域和发展史
人工智能·机器学习
前端开发江鸟4 小时前
我写过 MCP Server,却一直以为 MCP 只有 Tool
人工智能