注意
跳转至页面底部 下载完整的示例代码。
使用 USB 在 PyTorch 上进行半监督学习#
创建日期:2023年12月07日 | 最后更新:2024年03月07日 | 最后验证:未验证
作者: Hao Chen
统一半监督学习基准(Unified Semi-supervised learning Benchmark,简称 USB)是一个基于 PyTorch 构建的半监督学习(SSL)框架。得益于 PyTorch 提供的各种数据集和模块,USB 成为一个灵活、模块化且易于使用的半监督学习框架。它支持多种半监督学习算法,包括 FixMatch、FreeMatch、DeFixMatch、SoftMatch 等。它还支持多种针对非平衡数据的半监督学习算法。USB 包含了计算机视觉、自然语言处理和语音处理等不同数据集的基准测试结果。
本教程将引导您了解 USB 轻量级包的基本使用方法。让我们开始使用预训练的视觉 Transformer (ViT) 在 CIFAR-10 上训练一个 FreeMatch/SoftMatch 模型!我们将展示如何轻松地切换半监督算法并在非平衡数据集上进行训练。
半监督学习中 FreeMatch 和 SoftMatch 简介#
在此我们简要介绍 FreeMatch 和 SoftMatch。首先,我们介绍一个著名的半监督学习基准算法——FixMatch。FixMatch 是一个非常简单的半监督学习框架,它利用强增强技术为无标签数据生成伪标签。它采用置信度阈值策略,通过固定的阈值集合来过滤掉低置信度的伪标签。FreeMatch 和 SoftMatch 是在 FixMatch 基础上的改进算法。FreeMatch 提出了自适应阈值策略以取代 FixMatch 中的固定阈值策略。自适应阈值会根据模型在每个类别上的学习状态逐渐提高阈值。SoftMatch 吸收了置信度阈值的思想并将其作为加权机制。它提出了一种高斯加权机制,以克服伪标签中数量与质量之间的权衡问题。在本教程中,我们将使用 USB 来训练 FreeMatch 和 SoftMatch。
使用 USB 在仅有 40 个标签的 CIFAR-10 上训练 FreeMatch/SoftMatch#
USB 易于使用和扩展,适合小规模团队,并且能够全面地开发和评估 SSL 算法。USB 提供了 14 种基于一致性正则化的 SSL 算法实现,以及 15 个涵盖 CV、NLP 和音频领域的评估任务。它具有模块化设计,允许用户通过添加新算法和任务轻松扩展该包。它还支持 Python API,以便在处理新数据时更容易适配不同的 SSL 算法。
现在,让我们使用 USB 在 CIFAR-10 上训练 FreeMatch 和 SoftMatch。首先,我们需要安装 USB 包 semilearn 并从 USB 中导入必要的 API 函数。如果您在 Google Colab 中运行此代码,请通过运行以下命令安装 semilearn:!pip install semilearn。
以下是我们从 semilearn 中使用的函数列表:
get_dataset:用于加载数据集,此处我们使用 CIFAR-10get_data_loader:用于创建训练(有标签和无标签)和测试数据加载器
加载器,训练无标签加载器将提供无标签数据的强增强和弱增强 - get_net_builder:用于创建模型,此处我们使用预训练的 ViT - get_algorithm:用于创建半监督学习算法,此处我们使用 FreeMatch 和 SoftMatch - get_config:用于获取算法的默认配置 - Trainer:用于在数据集上训练和评估算法的训练器类
请注意,使用 semilearn 包进行训练需要具备 CUDA 环境的后端。请参阅 在 Google Colab 中启用 CUDA 获取相关指导。
import semilearn
from semilearn import get_dataset, get_data_loader, get_net_builder, get_algorithm, get_config, Trainer
导入必要的函数后,我们首先设置算法的超参数。
config = {
'algorithm': 'freematch',
'net': 'vit_tiny_patch2_32',
'use_pretrain': True,
'pretrain_path': 'https://github.com/microsoft/Semi-supervised-learning/releases/download/v.0.0.0/vit_tiny_patch2_32_mlp_im_1k_32.pth',
# optimization configs
'epoch': 1,
'num_train_iter': 500,
'num_eval_iter': 500,
'num_log_iter': 50,
'optim': 'AdamW',
'lr': 5e-4,
'layer_decay': 0.5,
'batch_size': 16,
'eval_batch_size': 16,
# dataset configs
'dataset': 'cifar10',
'num_labels': 40,
'num_classes': 10,
'img_size': 32,
'crop_ratio': 0.875,
'data_dir': './data',
'ulb_samples_per_class': None,
# algorithm specific configs
'hard_label': True,
'T': 0.5,
'ema_p': 0.999,
'ent_loss_ratio': 0.001,
'uratio': 2,
'ulb_loss_ratio': 1.0,
# device configs
'gpu': 0,
'world_size': 1,
'distributed': False,
"num_workers": 4,
}
config = get_config(config)
然后,我们加载数据集并创建训练和测试的数据加载器。接着指定要使用的模型和算法。
dataset_dict = get_dataset(config, config.algorithm, config.dataset, config.num_labels, config.num_classes, data_dir=config.data_dir, include_lb_to_ulb=config.include_lb_to_ulb)
train_lb_loader = get_data_loader(config, dataset_dict['train_lb'], config.batch_size)
train_ulb_loader = get_data_loader(config, dataset_dict['train_ulb'], int(config.batch_size * config.uratio))
eval_loader = get_data_loader(config, dataset_dict['eval'], config.eval_batch_size)
algorithm = get_algorithm(config, get_net_builder(config.net, from_name=False), tb_log=None, logger=None)
现在我们可以开始在 CIFAR-10(40 个标签)上训练算法。我们训练 500 次迭代,并每 500 次迭代评估一次。
trainer = Trainer(config, algorithm)
trainer.fit(train_lb_loader, train_ulb_loader, eval_loader)
最后,让我们在验证集上评估训练好的模型。在仅使用 CIFAR-10 的 40 个标签对 FreeMatch 进行 500 次迭代训练后,我们得到了一个在验证集上达到约 87% 准确率的分类器。
trainer.evaluate(eval_loader)
在非平衡 CIFAR-10 上使用特定非平衡算法训练 SoftMatch#
现在假设我们有一个非平衡的有标签集和无标签集的 CIFAR-10,并且我们想要在其上训练 SoftMatch 模型。我们通过将 lb_imb_ratio 和 ulb_imb_ratio 设置为 10,来创建非平衡的 CIFAR-10 有标签集和无标签集。此外,我们将 algorithm 替换为 softmatch 并将 imbalanced 设置为 True。
config = {
'algorithm': 'softmatch',
'net': 'vit_tiny_patch2_32',
'use_pretrain': True,
'pretrain_path': 'https://github.com/microsoft/Semi-supervised-learning/releases/download/v.0.0.0/vit_tiny_patch2_32_mlp_im_1k_32.pth',
# optimization configs
'epoch': 1,
'num_train_iter': 500,
'num_eval_iter': 500,
'num_log_iter': 50,
'optim': 'AdamW',
'lr': 5e-4,
'layer_decay': 0.5,
'batch_size': 16,
'eval_batch_size': 16,
# dataset configs
'dataset': 'cifar10',
'num_labels': 1500,
'num_classes': 10,
'img_size': 32,
'crop_ratio': 0.875,
'data_dir': './data',
'ulb_samples_per_class': None,
'lb_imb_ratio': 10,
'ulb_imb_ratio': 10,
'ulb_num_labels': 3000,
# algorithm specific configs
'hard_label': True,
'T': 0.5,
'ema_p': 0.999,
'ent_loss_ratio': 0.001,
'uratio': 2,
'ulb_loss_ratio': 1.0,
# device configs
'gpu': 0,
'world_size': 1,
'distributed': False,
"num_workers": 4,
}
config = get_config(config)
然后,我们重新加载数据集并创建训练和测试的数据加载器。并指定要使用的模型和算法。
dataset_dict = get_dataset(config, config.algorithm, config.dataset, config.num_labels, config.num_classes, data_dir=config.data_dir, include_lb_to_ulb=config.include_lb_to_ulb)
train_lb_loader = get_data_loader(config, dataset_dict['train_lb'], config.batch_size)
train_ulb_loader = get_data_loader(config, dataset_dict['train_ulb'], int(config.batch_size * config.uratio))
eval_loader = get_data_loader(config, dataset_dict['eval'], config.eval_batch_size)
algorithm = get_algorithm(config, get_net_builder(config.net, from_name=False), tb_log=None, logger=None)
现在我们可以开始在 CIFAR-10 上训练算法。我们训练 500 次迭代,并每 500 次迭代评估一次。
trainer = Trainer(config, algorithm)
trainer.fit(train_lb_loader, train_ulb_loader, eval_loader)
最后,让我们在验证集上评估训练好的模型。
trainer.evaluate(eval_loader)
参考文献:- [1] USB: microsoft/Semi-supervised-learning - [2] Kihyuk Sohn et al. FixMatch: Simplifying Semi-Supervised Learning with Consistency and Confidence - [3] Yidong Wang et al. FreeMatch: Self-adaptive Thresholding for Semi-supervised Learning - [4] Hao Chen et al. SoftMatch: Addressing the Quantity-Quality Trade-off in Semi-supervised Learning