# Pytorch_Project **Repository Path**: qingge_dada/gan_Project ## Basic Information - **Project Name**: Pytorch_Project - **Description**: 存放Pytorch的落地项目 1. 卡通动漫头像生成项目 2. Transformer写古诗 3.图像风格迁移 ... - **Primary Language**: Python - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 0 - **Created**: 2023-05-25 - **Last Updated**: 2024-03-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 说明 这个库专门用于存放Pytorch落地相关的项目,供参考、学习。 ## GAN_Generate_Anime_Avatars 选取开源的Anime-Face-Dataset数据集,动漫头像在$3*90*90$ ~$3*120*120$ - checkpoints: 保存模型 - imgs:保存生成头像 - data/:保存训练所需的图像 - main.py: 模型定义 - visualize.py:可视化工具Visdom封装 - requiments.txt:安装第三方库 ### 训练过程 - 初始化生成器和判别器,随机初始化 - 交替训练 - 训练判别器 - 固定生成器,只修改判别器的参数 - 训练生成器 - 固定判别器,只修改生成器的参数 ### 网络结构设计思路 判别器的目标是判断输入的图像是真还是假,可以看作二分类网络,设计一个简单的卷积网络实现判别器的功能。生成器的目标是从噪声中生成一张彩色图像,广泛使用DCGAN。 网络的输入是一个100维的噪声,输出一张$3*64*64$的图像,输入看作一张$100*1*1$的图像,通过转置卷积逐渐增大。 DCGAN中判别器和生成器完全对称,在生成器中采用上采样的转置卷积,在判别器中采用下采样的普通卷积。生成器根据噪声输出一张$3*64*64$的图像,判别器根据输入的$3*64*64$的图像输出它属于正负样本的分数。 标准GAN损失函数 $$ L_G = E_{x\~P_r}[log(1-D(G(x)))] \\ L_D = -E_{x\~P_r}[log(D(x))] - E_{x\~P_r}[log(1-D(G(x)))]\\ P_f:噪声分布\\ P_r:真实分布\\ D(G(x)) 表示判别器对生成样本 G(x) 的输出结果\\ 1-D(G(x)):判别器认定为假的分数,L_G使其尽量为0,则G(x)越接近1\\ 判别器损失由两部分构成:\\ -输入噪声数据,将生成的假图像区分开 \\ -输入真实图像,判别器输出的分数更高 $$ - 第一项 -E_{x~P_r}[log(D(x))] 表示判别器希望能够准确地将真实样本 x 分类为真实(**即 D(x) 接近 1**)。因此,它的目标是最小化 D(x) 的对数概率,即使 D(x) 趋近于 1。 - 第二项 -E_{x~P_r}[log(1-D(G(x)))] 表示判别器希望能够准确地将生成样本 G(x) 分类为假(即 **D(G(x)) 接近 0**)。因此,它的目标是最小化 1-D(G(x)) 的对数概率,即使 D(G(x)) 趋近于 0。 通过最小化 L_D,判别器的目标是将真实样本的判别结果最大化(接近1),同时将生成样本的判别结果最小化(接近0),从而使生成器生成更逼真的样本。 对于判别器,使用的损失函数是Hinge Loss。 ```python r_f_diff = (r_preds - f_preds.mean()).clamp(max=1) f_r_diff = (f_preds - r_preds.mean()).clamp(min=-1) loss_d_real = (1 - r_f_diff).mean() loss_d_fake = (1 + f_r_diff).mean() loss_d = loss_d_real + loss_d_fake ``` 对于生成器,使用的损失函数是Relativistic average HingeGAN Loss。 ``` r_preds = netd(real_img) f_preds = netd(fake_img) r_f_diff = r_preds - t.mean(f_preds) f_r_diff = f_preds - t.mean(r_preds) error_g = t.mean(t.nn.ReLU()(1+r_f_diff))+t.mean(t.nn.ReLU()(1-f_r_diff)) ``` 训练GAN需要注意 - 训练生成器时无需调整判别器参数,反之也是 - 训练判别器时,对于生成器生成的图像需要用`detach`操作进行计算图截断,避免反向传播到生成器中。因此在训练判别器时不需要训练生成器,也不需要生成训练器梯度。 ### 最终效果图 ![image-20230601163442269](imgs/image-20230601163442269.png) 更多详情见`https://gitee.com/qingge_dada/gan_Project/tree/master/GAN_Generate_Anime_Avatars` ## Style_Ttransfer 风格迁移有两类图像,一类是风格图像,通常是极具艺术风格的作品;另一类是内容图像,通常来自现实世界,利用风格迁移技术,将内容图像转换成具有艺术家风格的图像。 **核心:自适应实例标准化AdaIN** 思路:通过特征图的均值和标准差反映一张图像的风格,对内容图像去风格化,再使用风格图像的风格对其进行复原,得到风格迁移后的图像。 采用ImageNet与训练好的VGG19作为Encoder。 ### 损失函数设计 两个要求 - 生成的图像在内容、细节上尽量与风格图像相似 - 生成的图像在风格上尽可能与风格图像相似 #### 内容损失函数L_c 通过欧氏距离对生成的图像的内容、细节进行衡量 $$ L_c = ||Encoder(z) - AdaIN(x)||_2\\ Encoder(z):风格迁移后的图像z的特征 \\ AdaIN(x):AdaIN网络输出 $$ #### 风格损失函数L_s L_s通过欧氏距离对生成的图像风格进行衡量,提取风格迁移后的`图像z`和`风格图像s`在VGG19中每一层的特征,计算均值与标准差之间的差异。 $$ L_s = \sum_{i=1}^L||\mu[f_i(z)] - \mu[f_i(s)||_2\\ + \sum_{i=1}^L||\theta[f_i(z)] - \theta[f_i(s)] ||_2\\ f_i(.):在VGG19中间层的输出 $$ ### 训练步骤 - 将内容图像c与风格图像s输入到预训练好的VGG19,提取中间层的输出,如relu1_1、relu2_1、relu3_1、relu4_1(eg:relu1_1:第一个卷积块的第一个卷积层,类推) - 根据L_c损失函数进行自适应实例标准化,将结果输入到与VGG19呈对称结构的Decoder,得到风格化后的图像。 - 根据两个损失函数计算内容损失与风格损失,相加,反向传播,更新网络参数 - 回到第一步,继续训练网络 ### 文件组织结构 - checkpoints: 保存模型 - imgs:保存生成头像 - data/:保存训练所需的图像 - content_data - style_data - utils.py:AdaIN计算 - main.py: 模型定义与训练 - requiments.txt:安装第三方库 内容图像选自COCO数据集,风格数据集选自Kaggle的各种风格艺术照。 ### 最终效果图 ![image-20230601163525922](imgs/image-20230601163525922.png) 项目详情见`https://gitee.com/qingge_dada/gan_Project/tree/master/GAN_Style_Ttransfer` ## Transformer写诗 项目详情见`https://gitee.com/qingge_dada/gan_Project/tree/master/Transformer`