CycleGAN pix2pix 风格迁移 深度学习 计算机视觉
CycleGAN & pix2pix — 项目复现、浮世绘风格迁移与改进总结
最后编辑: 2026-05-31 16:57
一、项目概述
本项目基于 pytorch-CycleGAN-and-pix2pix 框架,围绕图像到图像翻译(Image-to-Image Translation)进行了三个阶段的探索:
| 阶段 | 内容 | 状态 |
|---|---|---|
| 复现 | CycleGAN (maps) + pix2pix (facades) 标准数据集训练与测试 | ✅ 完成 |
| 风格迁移 | 浮世绘(ukiyo-e)风格迁移:CycleGAN 在风景照↔浮世绘数据上的完整 40 epoch 训练 | ✅ 完成 |
| 改进 | 自注意力生成器 + AE 判别器 + LPIPS 感知损失的方案设计与代码修正 | ✅ 完成(设计阶段) |
仓库地址:seraphim522/pytorch-CycleGAN-and-pix2pix_re(复现 fork)
二、框架理解
该项目的核心设计是 统一训练骨架 + 动态装配机制:
•••
train.py → 解析参数 → 动态加载模型(models/) + 数据集(data/)
→ 训练循环(不关心具体模型类型)关键设计点
- 模型工厂
models/ __init__.py:根据--model cycle_gan自动导入对应模块 - 数据集工厂
data/ __init__.py:根据--dataset_mode unaligned自动选择数据加载器 - 参数双向修改:模型和数据集可以修改命令行默认值(如
pix2pix默认使用aligned数据集) - 统一基类
BaseModel:所有模型通过set_input→forward→optimize_parameters接口统一
核心网络组件(models/networks.py)
| 组件 | 默认架构 | 用途 |
|---|---|---|
| Generator | resnet_9blocks / unet_256 | 图像生成 |
| Discriminator | basic(70×70 PatchGAN) | 真假判别 |
| GAN Loss | lsgan / vanilla / wgangp | 对抗损失 |
| 归一化 | InstanceNorm(CycleGAN)/ BatchNorm(pix2pix) | 特征归一化 |
CycleGAN 原理
CycleGAN 实现 无配对 图像翻译,核心是 循环一致性:
•••
real_A ─→ G_A ─→ fake_B ─→ D_A(对抗损失)
└─→ G_B ─→ rec_A ≈ real_A(循环损失)
real_A ─→ G_B ─→ idt_B ≈ real_A(恒等损失)训练 4 个网络(G_A, G_B, D_A, D_B),3 类损失协同工作。
三、复现实验
3.1 CycleGAN — maps 数据集
- 数据集:maps(航拍图↔地图),无配对
- 训练:30 epoch,单卡 RTX 3060(6GB)
- 结果:成功完成训练与测试,生成器有效学习域间翻译
3.2 pix2pix — facades 数据集
- 数据集:facades(建筑标签↔照片),配对
- 模式:使用预训练模型
facades_label2photo_pretrained测试 - 结果:
unet_256生成器(54.4M 参数),成功完成标签→照片的翻译
3.3 环境问题修复
- Windows 下
.sh脚本换行符\r兼容:find . -name '*.sh' -exec sed -i 's/\r//' {} \;
四、浮世绘风格迁移
4.1 数据集
| 集合 | 来源 | 数量 |
|---|---|---|
| trainA | 真实风景照片 | 6,290 张 |
| trainB | 浮世绘(ukiyo-e)画作 | 562 张 |
| testA/testB | 对应测试集 | 752 / 263 张 |
特点:trainB 仅 562 张,风格多样性受限,CycleGAN 无配对机制仍有效。
4.2 训练配置
| 参数 | 值 | 说明 |
|---|---|---|
| 生成器 | ResNet-9blocks | ~11M 参数 |
| 判别器 | PatchGAN (70×70) | ~2.7M 参数 |
| GAN 模式 | LSGAN | 最小二乘损失 |
| 循环损失权重 | λ_A = λ_B = 10.0 | L1 逐像素 |
| Identity 权重 | 0.5 | 颜色保持 |
| Epoch | 40(20 恒定 lr + 20 线性衰减) | 总耗时 6h44min |
| Batch size | 1 | 6GB VRAM 限制 |
4.3 训练结果
| 损失 | 起始值 | 最终值 | 改善 |
|---|---|---|---|
| cycle_A(照片→浮世绘→照片) | 2.50 | 1.55 | ↓38% |
| cycle_B(浮世绘→照片→浮世绘) | 3.04 | 0.69 | ↓77% |
| G_A / D_A | 0.54 / 0.26 | 0.73 / 0.03 | 对抗平衡 |
| G_B / D_B | 1.08 / 0.46 | 0.23 / 0.06 | 对抗平衡 |
关键发现:
- 不对称数据集(B 域仅 562 张)下,cycle_B 反而更好 —— "去风格化"比"风格化"更易学
- LSGAN 训练稳定,未出现模式坍塌
- Identity loss 有效抑制不必要的颜色改变
4.4 推理脚本
编写了 infer_ukiyoe.py,支持单张图像推理:
bash
python infer_ukiyoe.py --input photo.jpg --output ukiyoe_result.png --epoch 40五、改进方案
在分析原始架构不足后,设计了四个维度的改进,并修正了原方案中的多处代码 Bug。
5.1 改进点一:自注意力残差块 + U-Net 生成器
在 ResNet-9blocks 基础上引入:
- Self-Attention:bottleneck 层获得全局感受野,
gamma初始化为 0,渐进式学习 - SEA_ResnetBlock:局部卷积 + 全局注意力 + 恒等映射,三层并行
- U-Net 跳跃连接:编码器各层特征直接传递给解码器,保留多尺度空间信息
5.2 改进点二:Auto-Encoder 判别器(EBGAN 风格)
用重建图像替代标量判别:
- 编码器:256 → 8×8 特征图
- 嵌入层:64 维压缩瓶颈
- 解码器:8×8 → 256 重建图像(使用 Upsample+Conv 避免棋盘格)
- 损失:MSE 重建误差(真实图能量低,生成图能量高)
5.3 改进点三:LPIPS 感知损失
用 LPIPS(预训练 AlexNet 特征空间距离)替代 L1 逐像素循环损失,更符合人类视觉感知。
5.4 改进点四:训练稳定性技巧
- 标签平滑(Label Smoothing):Real ∈ [0.7, 1.2],Fake ∈ [0, 0.3]
- 判别器输入加高斯噪声(std=0.05)
- 判别器更新频率 G:D = 1:3
5.5 原方案 Bug 修正
| 严重程度 | 问题 | 修正 |
|---|---|---|
| Critical | norm_layer 通道不匹配 | 每层独立指定通道数 |
| Critical | SA 模块定义了但 forward 未调用 | 整合进 bottleneck Sequential |
| High | WGAN-GP 与 AE 判别器不兼容 | 明确选择 AE + MSE 路线 |
| High | 梯度惩罚公式计算错误 | 修正为 real*ε + fake*(1-ε) |
| Medium | 未定义的类引用 | 移除或替换为正确实现 |
六、总结与展望
| 维度 | 成果 |
|---|---|
| 框架理解 | 深入掌握了统一训练骨架 + 动态装配的设计模式 |
| 复现验证 | maps/facades 数据集成功训练与测试 |
| 风格迁移 | 浮世绘 40 epoch 训练完成,cycle loss 显著下降 |
| 方案设计 | 自注意力 + AE 判别器 + LPIPS 完整方案 + Bug 修复 |
| 推理工具 | 编写了单张图像推理脚本 |
后续优化方向:
- FID/KID 定量评估
- 多尺度判别器
- 频谱归一化
- 数据增强(ColorJitter + RandomAffine)
- 浮世绘数据扩充(博物馆数字档案)