DANN 无监督域适应教程:从零跑通 PyTorch 域对抗训练
【免费下载链接】DANNpytorch implementation of Domain-Adversarial Training of Neural Networks项目地址: https://gitcode.com/gh_mirrors/da/DANN
DANN 是一个基于 PyTorch 1.0 实现的无监督领域自适应(domain adaptation)训练框架:它不需要目标域的任何标签,就能把源域上学到的分类能力迁移到新分布的数据上。本教程以官方的 MNIST 到 mnist_m 迁移示例为线索,带你先看懂原理,再完成环境配置、数据集准备和首次训练。跑通全流程只需要三条命令:克隆、解压、运行。
🔍 DANN 原理 3 分钟看懂:梯度反转层如何实现无监督域适应
先看问题:你有一个带标签的源域(MNIST 线条手写数字),还有一个目标域(mnist_m,彩色手写数字照片),两者分布不一致,而目标域没有标签,没法用常规监督方式直接训练。
DANN 的解法是域对抗训练:在网络里加一个域分类器,让它猜测特征来自源域还是目标域;同时用梯度反转层让特征提取器"欺骗"这个分类器——分类器越分不出来源,特征就越接近与域无关。
梯度反转层实现在 models/functions.py:正向传播时特征原样通过、数据不被改动,反向传播时取负梯度再乘以强度 α。这就像记账:付款时金额照实记一笔(正向不变),月底对账时却把这笔从"收入"改记到"支出"(反向翻号),数字没变,影响方向反了。α 不是常数,它随训练进度 p 按 S 曲线从接近 0 逐渐升到 2,即域适应压力前期轻、后期强。
结构上整体是双分支:特征提取器(两层卷积加批归一化与池化)的输出,一路送进类别分类器(10 个数字类别),另一路经梯度反转层送进域分类器(源/目标 2 类),三路损失相加后一起反向传播。
🚀 从零跑通 DANN:环境准备与 mnist_m 数据集配置
- 准备环境:Python 2.7 加 PyTorch 1.0,可选 CUDA 加速。代码使用了 xrange、print 语句等 Python 2 语法,Python 3 无法运行。
- 克隆仓库,然后进入 DANN 目录:
git clone https://gitcode.com/gh_mirrors/da/DANN- 配置数据集:源域 MNIST 会被代码自动下载,无需操作;目标域 mnist_m 需按 README 中的地址手动下载,放入 dataset 目录后在 mnist_m 子目录中解压:
cd dataset mkdir mnist_m cd mnist_m tar -zxvf mnist_m.tar.gz解压后该目录内应包含 mnist_m_train、mnist_m_test 两个子目录和 mnist_m_train_labels.txt、mnist_m_test_labels.txt 两个标签文件。 4. 运行训练:
cd train && python main.py控制台每个 batch 会打印 err_s_label(源域分类损失)与 err_s_domain、err_t_domain(两项域分类损失);每轮结束模型保存为 models 下的 mnist_mnistm_model_epoch_N.pth,并评估两个数据集的准确率,随时可检查进度或从存档断点续训。
🎚️ 关键参数怎么调:学习率、批次与训练轮数调参建议
可调项集中在 train/main.py 顶部:
| 参数 | 默认值 | 调整建议 |
|---|---|---|
| 学习率(Adam 优化器) | 1e-3 | 损失震荡时降到 5e-4;收敛过慢可试 2e-3 |
| 批次大小 batch size | 128 | 显存紧张时降到 64;显存充裕可升到 256 提速 |
| 训练轮数 n_epoch | 100 | 目标域准确率仍在上升则延长到 150~200;提前平台期可减到 50 |
| α 域适应强度 | 0→2 随进度调度 | 由 S 曲线公式自动计算,一般无需改;想加压或减压可调公式中的指数系数 -10 |
🧰 出错时先查这里:Python 版本与数据集配置
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| 启动即报 SyntaxError,指向 xrange 或 print | 用了 Python 3 运行,项目仅支持 2.7 | 换 Python 2.7 加 PyTorch 1.0 环境重跑 |
| 抛出 FileNotFoundError / IOError | mnist_m 未放在 dataset/mnist_m,或标签文件缺失 | 检查两个数据集子目录与两份 labels txt 是否齐全 |
| 训练明显偏慢 | 未使用 CUDA,或数据读取线程不足 | 用 GPU 环境训练;适当调整 DataLoader 的 num_workers |
🧩 改造成你的场景:数据、结构与多领域
自定义数据集:改动 dataset/data_loader.py 中目标域的读取逻辑。GetLoader 从文本列表里读取每张图片的相对路径与标签,你只需按同样格式准备图片与列表文件;源域也可以在 main.py 中换成任意带标签数据集。
调整网络层:特征提取器与两个分类器都定义在 models/model.py,可增删卷积层与全连接层。注意类别分类器输入是 50×4×4,若改动特征层输出尺寸,需同步修改全连接层的输入维度。
扩展到多领域:当前域分类器输出 2 类,只区分源与目标。要支持 K 个领域,把它的最后一层改为 K 类,为每个领域分配独立标签,并在同一训练循环中并入各领域数据即可。
最快的上手路径是先跑通这个 MNIST 到 mnist_m 的示例:看 train/main.py 确认超参设置,读 models/functions.py 弄清梯度反转层的工作原理,之后换成自己的数据时从数据加载部分入手修改即可。
【免费下载链接】DANNpytorch implementation of Domain-Adversarial Training of Neural Networks项目地址: https://gitcode.com/gh_mirrors/da/DANN
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考