中兴大赛

中兴捧月大赛 :https://zte.hina.com/zte/index

图像去噪赛题背景图像去噪是机器视觉领域重要任务,图像去噪模块在安防,自动驾驶,传感,医学影像,消费电子等领域都是重要的前端图像处理模块。消费级电子产品(例如手机)出于成本考虑,在低照度和高ISO条件下,噪声对成像质量的降级更加严重。对于传统图像处理算法,常见去噪算法包含双边(bilateral)滤波,NLM (non local mean)滤波,BM3D,多帧(3D)降噪方案等多种方案,产品实现上需要兼顾性能和复杂度。
AI可进一步提升图像主客观质量在学术和工业界得到了广泛认证。对于手机产品,AI正快速补充和替代传统手机ISP(Image signal processing)中的痛点难点,例如可进行AI-based去噪,动态范围增强,超分辨,超级夜景,甚至AI ISP等。

提交说明

1. 参赛者需要根据举办方提供的10张noisy图片提交相应10张denoise图片存放至文件夹“data”下,命名方式为denoise0.dng至denoise9.dng,注意上传denoise RAW图值域为[black_level, white_level] = [1024,16383],可参照baseline代码;
2. 参赛者需要提交模型文件和参数文件至文件夹“algorithm/models/”下,模型文件命名方式为network.py,参数文件命名pytorch对应model.pth,tensorflow对应model.h5。模型参数文件大小限制为50M;
3. 若使用非AI方法,算法文件提交至以上相同路径,文件命名为alg.py;
4. 参赛者需要提交文档报告阐述所使用方法,文档存放在algorithm二级目录下;
5. data和algorithm按照二级目录结构进行放置,将二级目录放置于命名为result的一级目录内,将一级目录result压缩成.zip格式上传;

赛题简介本次题目围绕手机图片RAW域去噪问题,参赛者算法方案使用基于AI或传统图像处理算法均可。
比赛目标是提升举办方提供给参赛者10张noisy图片的PSNR和SSIM指标。为了方便参赛者轻松上手流程,举办方为参赛者提供baseline代码示例,以及training dataset(200张图片)以帮助参赛者更好地提升算法性能。根据参赛者所提交算法的原创性,额外有5% bonus分数浮动。

比赛排名 55/1159

项目参考 论文: Simple Baselines for Image Restoration

参考:Simple Baselines for Image Restoration  
单位:旷视  
代码:https://github.com/megvii-research/NAFNet  
论文:https://arxiv.org/abs/2204.0467

项目介绍:

一、网络结构:

1.1使用类Unet结构:

如下图,Unet 网络结构是对称的,形似英文字母 U 所以被称为 Unet。通过拼接的方式将不同层次的特征进行通道拼接。其中网络中主要使用了NAFBlock块。U-Net和FCN非常的相似,U-Net比FCN稍晚提出来,但都发表在2015年,和FCN相比,U-Net的第一个特点是完全对称,也就是左边和右边是很类似的,而FCN的decoder相对简单,只用了一个deconvolution(反卷积)的操作,之后并没有跟上卷积结构。第二个区别就是skip connection,FCN用的是加操作(summation),U-Net用的是叠操作(concatenation)。这些都是细节,重点是它们的结构用了一个比较经典的思路,也就是编码和解码(encoder-decoder),早在2006年就被Hinton大神提出来发表在了nature上.

当时这个结构提出的主要作用并不是分割,而是压缩图像和去噪声。输入是一幅图,经过下采样的编码,得到一串比原先图像更小的特征,相当于压缩,然后再经过一个解码,理想状况就是能还原到原来的图像。这样的话我们存一幅图的时候就只需要存一个特征和一个解码器即可。这个想法我个人认为是很漂亮了。同理,这个思路也可以用在原图像去噪,做法就是在训练的阶段在原图人为的加上噪声,然后放到这个编码解码器中,目标是可以还原得到原图。

后来把这个思路被用在了图像分割的问题上,也就是现在我们看到的U-Net结构,在它被提出的三年中,有很多很多的论文去讲如何改进U-Net或者FCN,不过这个分割网络的本质的拓扑结构是没有改动的。举例来说,ICCV上凯明大神提出的Mask RCNN. 相当于一个检测,分类,分割的集大成者,我们仔细去看它的分割部分,其实使用的也就是这个简单的FCN结构。说明了这种“U形”的编码解码结构确实非常的简洁,并且最关键的一点是好用。

采用Unet的好处我感觉是:网络层越深得到的特征图,有着更大的视野域,浅层卷积关注纹理特征,深层网络关注本质的那种特征,所以深层浅层特征都是有格子的意义的;另外一点是通过反卷积得到的更大的尺寸的特征图的边缘,是缺少信息的,毕竟每一次下采样提炼特征的同时,也必然会损失一些边缘特征,而失去的特征并不能从上采样中找回,因此通过特征的拼接,来实现边缘特征的一个找回。

最后,将网络输出和input做加和,这样实际上是用网络做噪声的预测,想比直接输出图像,输出噪声的实际效果好,个人认为,如果输出的是图像,那么即使用unet结构,在进行conv、layernormal过程中还会造成图像的细节特征损失,对于生成的图像细节方面会差一些。总之,我认为直接预测图像的task会比预测噪声的难度大。

下图1是本次设计的图像去噪网络结构:

Figure 1 NFnet网络结构

二、NAFBlock块

(使用论文Simple Baselines for Image Restoration中的NAFBlock模块)

NAFBlock结构介绍:

  1. Normalization:Layer Normalization
  2. 加速训练(可以使用更大的learning rate)
  3. 防止exploding/vanishing gradients.
  4. 减小参数的initialization对训练的影响
  5. 提高训练效果
  6. layerNorm关注整幅图,也没有超过单张的范围,LN将每个训练样本都归一化到了相同的分布上,某种意义上避免了平滑

对于Normalization,文章采用了Transformer里被通常采用的LayerNorm,并通过实验发现其能提点。其实传统意义上,除了早期的方法,底层视觉一般是不太会增加归一化层,认为其会降点而且让图像模糊,我个人理解这可能和BatchNorm的特性有关,一方面BatchNorm本身训练测试阶段由于统计量不同,就会导致领域不适应问题。另外不同于high-level task倾向于寻找一致性表示,底层视觉的任务与之相反,往往是倾向于学习图片特定性以增强细节的恢复效果(比如之前有人通过捕获图像分布(正态分布)的sigma以增强边缘区域的效果),batchNorm由于是batch内做attention,其实很容易将其他图片的信息引入,忽略了恢复图像的特定信息,导致性能下降。所以之前底层视觉里面用的比较多的norm是instance Norm(比较多的是在风格迁移,图像恢复这边有HI-Net就是用IN),因为只关注同一个图片同一channel内的信息,所以某种意义上避免了平滑,layerNorm关注整幅图,也没有超过单张的范围,所以能够work还是蛮make sense的。

归一化技术在high-level任务中已被广泛应用,但在low-level任务中应用极少。但是,依托于Transformer,LN得到了越来越多的应用。基于该事实,我们猜想:LN可能是达成SOTA复原器的关键,故在上述模块中添加了LN(见上面图示)。LN的引入使得训练更平滑,甚至可以将学习率放大10倍。更大的学习率可以带来显著性能提升。

在Transformer中,数据过Attention层和FFN层后,都会经过一个Add & Norm处理。其中,Add为residule block(残差模块),数据在这里进行residule connection(残差连接)。而Norm即为Normalization(标准化)模块。Transformer中采用的是Layer Normalization(层标准化)方式。

在图片视频分类等特征提取网络中大多数情况BN效果优于IN,在生成式类任务中的网络IN优于BN。

BN适用于判别模型中,比如图片分类模型。因为BN注重对每个batch进行归一化,从而保证数据分布的一致性,而判别模型的结果正是取决于数据整体分布。但是BN对batchsize的大小比较敏感,由于每次计算均值和方差是在一个batch上,所以如果batchsize太小,则计算的均值、方差不足以代表整个数据分布;

IN适用于生成模型中,比如图片风格迁移。因为图片生成的结果主要依赖于某个图像实例,所以对整个batch归一化不适合图像风格化中,在风格迁移中使用Instance Normalization不仅可以加速模型收敛,并且可以保持每个图像实例之间的独立。

  • Activation:simple gate 引入非线性

(对特征进行了channel-split,分成两个C/2个通道的特征,并相乘)

尽管ReLU是最常用的激活函数,现有SOTA方案中采用GELU进行代替。由于GELU可以保持降噪性能相当且大幅提升去模糊性能,故我们采用GELU替代ReLU,但作者认为 GELU太复杂:因此提出了简化版的GELU。

作者也是从High-Level Task 找到的灵感,将现在大火的GLU和GELU引入并做了简化。 文章先给出了GLU的数学形式:,之后文章认为GELU是GLU的一种特殊情况(这个可以看原文,比较直观),于是只关注于GLU本身。虽然GLU可以提升模型效果,但是也会增加计算量,于是作者为降低计算量,所以对GLU进行了简化。GLU的计算量主要来自于sigmoid和映射函数(上图)。因为GLU本身是具备非线性这一性质的(我个人理解是(元素积)element-wise multiplication引入的),所以文章删除了sigmoid。为了减少计算量,映射函数更是直接删除,同时对特征进行了channel-split,分成两个C/2个通道的特征,并相乘,具体是上面的图。 由于这个简化的simple gate引入了非线性,所以常用的ReLU自然也不需要再加入到网络中了,这也就是为什么这篇文章提出的方法叫做 Nonlinear Activation Free Network (NAFNet)

补充:channel-split 思想来自Channel-Wise Convolutions

【ChannelNets: Compact and Efficient Convolutional Neural Networks via Channel-Wise Convolutions:论文提出channel-wise卷积的概念,将输入输出的维度连接进行稀疏化而非全连接,区别于分组卷积的严格分组,让卷积在channel维度上进行滑动,能够更好地保留channel间的信息交流。基于channel-wise卷积的思想,论文进一步提出了channel-wise深度可分离卷积,并基于该结构替换网络最后的全连接层+全局池化的操作,搭建了ChannelNets。Channel-wise卷积的核心在于输入和输出连接的稀疏化,每个输出仅与部分输入相连,概念上区别于分组卷积,没有对输入进行严格的区分,而是以一定的stride去采样多个相关输入进行输出(在channel维度滑动),能够降少参数量以及保证channel间一定程度的信息流。】

GELU与GLU的实现可以发现:GELU是GLU的一种特例。我们从另一个角度猜想:GLU可视作一种广义激活函数,它是可以用于替代非线性激活函数。提出了一种简化版GLU变种(见上图):直接将特征沿通道维度分成两部分并相乘。

  • Simplified Channel Attention

注意力机制可以说是近年来最火热的研究领域之一,其有效性得到了充分的验证

通过保留通道注意力的两个重要作用(全局信息聚合、通道信息交互),我们提出了如上图的简化版通道注意力。

对于attention,上述的simple Gate操作虽然可以有效减少计算量,但是作者认为channel-wise的操作(导致channel间的信息阻隔)丢失了channel之间的信息,所以在后面的attention上,作者使用了简化的channel attention,减少计算量的同时引入channel的交互,这个看图就可以直接明白。这个其实对我个人有点启发,因为从swin到restormer(用于高分辨率图像恢复的高效Transformer),多少能隐隐的感受到,其实tranformer的全局attention可能没有想象的那么重要,swin里切成window-based仍然可以保持很好的效果,restormer里面干脆放弃了spatial的MSA(多头self注意力)而使用深度卷积和传统的spatial attention(空间注意力),有可能CA对恢复任务更重要一些(有待证明)。

4、1*1卷积

1×1卷积实际上是对每个像素点,在不同的channels上进行线性组合(信息整合),且保留了图片的原有平面结构,调控depth,从而完成升维或降维的功能。

最后,有了上述的基本改进,并将上面的模块组合在了一起。

其他说明:

1、参考论文:

Simple Baselines for Image Restoration,是目前去噪效果比较好的网络。

Github代码实现:https://github.com/megvii-research/NAFNet

2、损失函数:

       使用L1损失、mse损失(Fourier_loss)、

psnrloss【参考https://github.com/megvii-research/NAFNet中提供的psnrloss】、以及相邻像素损失

L1损失:用来预测generate和real 之间的像素级别误差

MSE损失(Fourier_loss):计算generate和real的fft变换后的频域信息。

参考论文:Fouier Space Losses for Efficient Perceptual Image Super-Resolution,在改论文中利用transformer实现图像去雨,提出了Fourier Space Losses,单张图像超分方法在重构高分辨率图像时缺失高频细节。这通常通过有监督的训练来执行,其中使用已知核对真实图像 y 进行下采样,例如 bicubic,得到LR输入图像x。虽然这种方法能够在某种应用中尽可能恢复频率信息,但高频信息却难以恢复,容易出现模糊情况。近几年,许多研究者使用GAN,用于学习高频空间的分布。丢失了频谱空间的高频信息。因此,文章提出了一种用于频域的损失函数。首先,将真实图像和生成图像经过Hann window预处理。接着,计算傅里叶频域损失函数,包括L1范数度量的频谱差异,以及相位角差异

对generate和real进行fft变换,时域变换到频域

参考代码:https://github.com/zzksdu/fourierSpaceLoss/blob/master/Fourier_loss.py

Psnrloss:参考NAFnet。

相邻像素损失:

使用L1loss,比较相邻行之间的像素loss:

Step1:

对gt:求相邻行像素的l1损失,记为 gloss。

Step2:

对denoise求相邻行像素的l1损失,记为 dloss。

Step3:对gloss和dloss求L1损失。

【因为图像在进行预处理时候进行了行列交织,所以再求此损失时候,需要先对图像进行复原,再求相邻像素损失】

3、优化函数 SGD or Adam

SGD虽然训练时间更长,容易陷入鞍点,但是在好的初始化和学习率调度方案的情况下,结果更可靠。SGD现在后期调优时还是经常使用到,但SGD的问题是前期收敛速度慢。SGD前期收敛慢的原因: SGD在更新参数时对各个维度上梯度的放缩是一致的,并且在训练数据分布极不均衡时训练效果很差。而因为收敛慢的问题应运而生的自适应优化算法Adam、AdaGrad、RMSprop 等,但这些自适应的优化算法泛化能力可能比非自适应方法更差,虽然可以在训练初始阶段展现出快速的收敛速度,但其在测试集上的表现却会很快陷入停滞,并最终被 SGD 超过。 实际上,在自然语言处理和计算机视觉方面的一些最新的工作中SGD(或动量)被选为优化器,其中这些实例中SGD 确实比自适应方法表现更好。

主流认为:Adam等自适应学习率算法对于稀疏数据具有优势,且收敛速度很快;但精调参数的SGD(+Momentum)往往能够取得更好的最终结果。

Improving Generalization Performance by Switching from Adam to SGD 提出了Adam+SGD 组合策略。前期用Adam,享受Adam快速收敛的优势;后期切换到SGD,慢慢寻找最优解。这一方法以前也被研究者们用到,不过主要是根据经验来选择切换的时机和切换后的学习率。这篇文章把这一切换过程傻瓜化,给出了切换SGD的时机选择方法,以及学习率的计算方法,效果看起来也不错。

torch.optim.lr_scheduler.StepLR:这是比较常用的等间隔动态调整方法,该方法的原理为:每隔step_size个epoch就对每一参数组的学习率按gamma参数进行一次衰减。

3、训练结果:

Batch Size=1,梯度变来变去,非常不准确,网络很难收敛。

Figure 1 loss损失函数值

Figure 2  训练过程中的psnr测试值

Figure 3   训练过程SSIM 测试值

4、数据集处理

对数据进行加噪处理、数据随机翻转等预处理。

因为显存有限,所以将img(4,1736,2312)裁剪为 1736/4, 2312/4的大小送入网络中进行训练。在进行验证/生成去噪图片时,同样裁剪噪声图片分批送入网络,注意,裁剪需要多裁剪20个tensor,然后拼接成完整图片并写入文件,这样拼接成的图片不会有分割线 。

[加噪处理效果不好,我使用的噪声正则项是torch正态分布,原本任务就是去噪,raw域噪声的分布应该跟正态分布不贴合,增加噪声后可能会导致模型效果变差。

数据翻转:这里需要注意label和noise应该使用相同的seed。

因为显存有限,需要裁剪图像,这里我认为如果只是简单的裁剪图像,会导致裁剪前后的相邻像素信息损失,因此我借鉴了unet:Overlap-tile 重叠切片的思想,同时,在生成test图像时候,也要对其进行拼接。]

5、使用加载模型:

from network import NFnet3

net = NFnet3()

net.load_state_dict(torch.load(modelpath))

6、test数据集去噪结果:

Figure 6 原始噪声图像
Figure 7 去噪后图像

去噪结果思考:

对于噪声比较小的图像,去噪效果比较好,而且不会破坏原有图像的结构,但对于噪声特别大的图像:纹理效果不是很好,一些细节处理的不太好。

此外,我认为,如果输入裁剪后的图像能在大一些,效果应该会好一些。或者现在小的图像进行预训练,在使用大图像进行微调,会好一些。

参考论文:

[1] Chen L, Chu X, Zhang X, et al. Simple Baselines for Image Restoration[J]. arXiv preprint arXiv:2204.04676, 2022.

[2] Huang H, Lin L, Tong R, et al. Unet 3+: A full-scale connected unet for medical image segmentation[C]//ICASSP 2020-2020 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2020: 1055-1059.

[3] Wang Y, Huang H, Xu Q, et al. Practical deep raw image denoising on mobile devices[C]//European Conference on Computer Vision. Springer, Cham, 2020: 1-16.

[4] Ba, J.L., Kiros, J.R., Hinton, G.E.: Layer normalization. arXiv preprintarXiv:1607.06450 (2016)

[5] Chen, H., Wang, Y., Guo, T., Xu, C., Deng, Y., Liu, Z., Ma, S., Xu, C., Xu, C., Gao,W.: Pre-trained image processing transformer. In: Proceedings of the IEEE/CVFConference on Computer Vision and Pattern Recognition. pp. 12299–12310 (2021)

[6] Cheng, S., Wang, Y., Huang, H., Liu, D., Fan, H., Liu, S.: Nbnet: Noise basis learning for image denoising with subspace projection. In: Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. pp. 4896–4906 (2021)

[7] Language Modeling with Gated Convolutional Networks

更新:最近Swin Transformer的提出,就有人利用该结构和unet,实现了图像去噪:

SUNet: Swin Transformer UNet for Image Denoising

https://arxiv.org/abs/2202.14009

MAE–transformer模型预训练

假设我们想从图像中识别出不同种类的椅子,然后将购买链接推荐给用户。一种可能的方法是先找出100种常见的椅子,为每种椅子拍摄1,000张不同角度的图像,然后在收集到的图像数据集上训练一个分类模型。这个椅子数据集虽然可能比Fashion-MNIST数据集要庞大,但样本数仍然不及ImageNet数据集中样本数的十分之一。这可能会导致适用于ImageNet数据集的复杂模型在这个椅子数据集上过拟合。同时,因为数据量有限,最终训练得到的模型的精度也可能达不到实用的要求。

为了应对上述问题,一个显而易见的解决办法是收集更多的数据。然而,收集和标注数据会花费大量的时间和资金。例如,为了收集ImageNet数据集,研究人员花费了数百万美元的研究经费。虽然目前的数据采集成本已降低了不少,但其成本仍然不可忽略。

另外一种解决办法是应用迁移学习(transfer learning),将从源数据集学到的知识迁移到目标数据集上。例如,虽然ImageNet数据集的图像大多跟椅子无关,但在该数据集上训练的模型可以抽取较通用的图像特征,从而能够帮助识别边缘、纹理、形状和物体组成等。这些类似的特征对于识别椅子也可能同样有效。

本节我们介绍迁移学习中的一种常用技术:微调(fine tuning)。如图9.1所示,微调由以下4步构成。

  1. 在源数据集(如ImageNet数据集)上预训练一个神经网络模型,即源模型。
  2. 创建一个新的神经网络模型,即目标模型。它复制了源模型上除了输出层外的所有模型设计及其参数。我们假设这些模型参数包含了源数据集上学习到的知识,且这些知识同样适用于目标数据集。我们还假设源模型的输出层跟源数据集的标签紧密相关,因此在目标模型中不予采用。
  3. 为目标模型添加一个输出大小为目标数据集类别个数的输出层,并随机初始化该层的模型参数。
  4. 在目标数据集(如椅子数据集)上训练目标模型。我们将从头训练输出层,而其余层的参数都是基于源模型的参数微调得到的。

当目标数据集远小于源数据集时,微调有助于提升模型的泛化能力。

代码实现微调:

pretrained_net = models.resnet18(pretrained=True)
pretrained_net.load_state_dict(torch.load('/home/kesci/input/resnet185352/resnet18-5c106cde.pth'))

下面打印源模型的成员变量fc。作为一个全连接层,它将ResNet最终的全局平均池化层输出变换成ImageNet数据集上1000类的输出。

print(pretrained_net.fc)

输出:Linear(in_features=512, out_features=1000, bias=True)

可见此时pretrained_net最后的输出个数等于目标数据集的类别数1000。所以我们应该将最后的fc成修改我们需要的输出类别数:

pretrained_net.fc = nn.Linear(512, 2)
print(pretrained_net.fc)

此时,pretrained_netfc层就被随机初始化了,但是其他层依然保存着预训练得到的参数。由于是在很大的ImageNet数据集上预训练的,所以参数已经足够好,因此一般只需使用较小的学习率来微调这些参数,而fc中的随机初始化参数一般需要更大的学习率从头训练。PyTorch可以方便的对模型的不同部分设置不同的学习参数,我们在下面代码中将fc的学习率设为已经预训练过的部分的10倍。

output_params = list(map(id, pretrained_net.fc.parameters()))
feature_params = filter(lambda p: id(p) not in output_params, pretrained_net.parameters())

lr = 0.01
optimizer = optim.SGD([{'params': feature_params},
                       {'params': pretrained_net.fc.parameters(), 'lr': lr * 10}],
                       lr=lr, weight_decay=0.001)

记录: 在MAE的微调训练中,提供了两种 微调

  1. Linear probing: 锁死transformer的参数,只训练CIFAR10的那个Linear层。
  2. Fine-tuning: 接着训练transformer的参数,同时也训练CIFAR10的那个Linear。

论文做了MAE各个部分的不同设置对比实验,这些实验能够揭示MAE更多的特性。首先是masking ratio,从下图可以看到,最优的设置是75%的masking ratio,此时linear probing和finetune效果最好,这比之前的研究要高很多,比如BEiT的masking ratio是40%。另外也可以看到linear probing和finetune的表现不一样,linear probing效果随着masking ratio的增加逐渐提高直至一个峰值后出现下降,而finetune效果在不同making ratio下差异小,masking ratio在40%~80%范围内均能表现较好。 ​

preview

Pytorch Image Models –timm快速使用

原文:Getting Started with PyTorch Image Models (timm): A Practitioner’s Guide – 2022.02.02

中文教程: https://www.aiuai.cn/aifarm1967.html

Github: rwightman/pytorch-image-models

PyTorch Image Models(timm) 是一个优秀的图像分类 Python 库,其包含了大量的图像模型(Image Models)、Optimizers、Schedulers、Augmentations 等等.里面提供了许多计算机视觉的SOTA模型,可以当作是torchvision的扩充版本,并且里面的模型在准确度上也较高。

timm 提供了参考的 training 和 validation 脚本,用于复现在 ImageNet 上的训练结果;以及更多的 官方文档 和 timmdocs project.

timm的安装

关于timm的安装,我们可以选择以下两种方式进行:

  1. 通过pip安装
pip install timm
  1. 通过git与pip进行安装
git clone https://github.com/rwightman/pytorch-image-models
cd pytorch-image-models && pip install -e .

如何查看预训练模型种类

  1. 查看timm提供的预训练模型 截止到2022.3.27日为止,timm提供的预训练模型已经达到了592个,我们可以通过timm.list_models()方法查看timm提供的预训练模型(注:本章测试代码均是在jupyter notebook上进行)
import timm
avail_pretrained_models = timm.list_models(pretrained=True)
len(avail_pretrained_models)
  1. 查看特定模型的所有种类 每一种系列可能对应着不同方案的模型,比如Resnet系列就包括了ResNet18,50,101等模型,我们可以在timm.list_models()传入想查询的模型名称(模糊查询),比如我们想查询densenet系列的所有模型。
all_densnet_models = timm.list_models("*densenet*")
all_densnet_models

我们发现以列表的形式返回了所有densenet系列的所有模型。

['densenet121',
 'densenet121d',
 'densenet161',
 'densenet169',
 'densenet201',
 'densenet264',
 'densenet264d_iabn',
 'densenetblur121d',
 'tv_densenet121']
  1. 查看模型的具体参数 当我们想查看下模型的具体参数的时候,我们可以通过访问模型的default_cfg属性来进行查看,具体操作如下
model = timm.create_model('resnet34',num_classes=10,pretrained=True)
model.default_cfg
{'url': 'https://github.com/rwightman/pytorch-image-models/releases/download/v0.1-weights/resnet34-43635321.pth',
 'num_classes': 1000,
 'input_size': (3, 224, 224),
 'pool_size': (7, 7),
 'crop_pct': 0.875,
 'interpolation': 'bilinear',
 'mean': (0.485, 0.456, 0.406),
 'std': (0.229, 0.224, 0.225),
 'first_conv': 'conv1',
 'classifier': 'fc',
 'architecture': 'resnet34'}

除此之外,我们可以通过访问这个链接 查看提供的预训练模型的准确度等信息。

使用和修改预训练模型

在得到我们想要使用的预训练模型后,我们可以通过timm.create_model()的方法来进行模型的创建,我们可以通过传入参数pretrained=True,来使用预训练模型。同样的,我们也可以使用跟torchvision里面的模型一样的方法查看模型的参数,类型/

import timm
import torch

model = timm.create_model('resnet34',pretrained=True)
x = torch.randn(1,3,224,224)
output = model(x)
output.shape
torch.Size([1, 1000])
  • 查看某一层模型参数(以第一层卷积为例)
model = timm.create_model('resnet34',pretrained=True)
list(dict(model.named_children())['conv1'].parameters())
[Parameter containing:
 tensor([[[[-2.9398e-02, -3.6421e-02, -2.8832e-02,  ..., -1.8349e-02,
            -6.9210e-03,  1.2127e-02],
           [-3.6199e-02, -6.0810e-02, -5.3891e-02,  ..., -4.2744e-02,
            -7.3169e-03, -1.1834e-02],
            ...
           [ 8.4563e-03, -1.7099e-02, -1.2176e-03,  ...,  7.0081e-02,
             2.9756e-02, -4.1400e-03]]]], requires_grad=True)]
            
  • 修改模型(将1000类改为10类输出)
model = timm.create_model('resnet34',num_classes=10,pretrained=True)
x = torch.randn(1,3,224,224)
output = model(x)
output.shape
torch.Size([1, 10])
  • 改变输入通道数(比如我们传入的图片是单通道的,但是模型需要的是三通道图片) 我们可以通过添加in_chans=1来改变
model = timm.create_model('resnet34',num_classes=10,pretrained=True,in_chans=1)
x = torch.randn(1,1,224,224)
output = model(x)

模型的保存

timm库所创建的模型是torch.model的子类,我们可以直接使用torch库中内置的模型参数保存和加载的方法,具体操作如下方代码所示

torch.save(model.state_dict(),'./checkpoint/timm_model.pth')
model.load_state_dict(torch.load('./checkpoint/timm_model.pth'))

使用示例

# replace
# optimizer = torch.optim.Adam(model.parameters(), lr=0.01)

# with
optimizer = timm.optim.AdamP(model.parameters(), lr=0.01)

for epoch in num_epochs:
    for batch in training_dataloader:
        inputs, targets = batch
        outputs = model(inputs)
        loss = loss_function(outputs, targets)

        loss.backward()
        optimizer.step()
        optimizer.zero_grad()
        
        
#
optimizer = timm.optim.Adahessian(model.parameters(), lr=0.01)

is_second_order = (
    hasattr(optimizer, "is_second_order") and optimizer.is_second_order
)  # True

for epoch in num_epochs:
    for batch in training_dataloader:
        inputs, targets = batch
        outputs = model(inputs)
        loss = loss_function(outputs, targets)

        loss.backward(create_graph=second_order)
        optimizer.step()
        optimizer.zero_grad()

CVPR 2022 | 重新审视池化:你的感受野不是最理想的

作者丨简单来源丨CV技术指南

本文提出了一种简单而有效的动态优化池操作( Dynamically Optimized Pooling operation),称为DynOPool,它通过学习每一层感受野的最佳大小和形状来优化特征映射的端到端比例因子。

前言

本文提出了一种简单而有效的动态优化池操作( Dynamically Optimized Pooling operation),称为DynOPool,它通过学习每一层感受野的最佳大小和形状来优化特征映射的端到端比例因子。深度神经网络中任何类型的调整大小模块都可以用DynOPool操作以最小的成本替换。此外,DynOPool通过引入一个限制计算成本的附加损失项来控制模型的复杂性。

Pooling Revisited: Your Receptive Field is Suboptima

论文:https://arxiv.org/abs/2205.15254

公众号后台回复“DynOPool”获取论文PDF

背景

尽管深度神经网络在计算机视觉、自然语言处理、机器人、生物信息学等各种应用中取得了前所未有的成功,但最优网络结构的设计仍然是一个具有挑战性的问题。而感受野的大小和形状决定了网络如何聚集本地信息,并对模型的整体性能产生显著影响。神经网络中的许多组成部分,例如用于卷积和池化运算的内核大小和步长,都会影响感受野的配置。然而,它们仍然依赖于超参数,现有模型的感受野会导致形状和大小不理想

本文通过介绍固定大小和形状的传统感受野是次优的问题,讨论了DynOPool如何通过CIFAR-100上的VGG-16玩具实验解决这个问题。

固定大小和形状的传统感受野存在的问题:

1.不对称分布的信息

最佳感受野形状会根据数据集中固有的空间信息不对称性而改变。而大多数情况下固有的不对称性是不可测量的。此外,通常用于预处理的输入大小调整有时也会导致信息不对称。在人工设计的网络中,图像的长宽比经常被调整以满足模型的输入规格。然而,这种网络中的感受野不是用来处理操作的。

为了验证所提出的方法,作者在CIFAR-stretch-V上进行实验,如图1(a)所示,相较于人工设计模型,形状通过DynOPool动态优化的特征映射通过在水平方向上提取更具有价值的信息提高性能。

图片

图1  用来自CIFAR-100的三个不同的合成数据集进行玩具实验:(a)随机裁剪垂直拉伸的图像 (b)在4×4网格中平铺缩小的图像 (c)放大缩小的图像。

2.密集分布或稀疏分布信息

局部性是设计最优模型的组成部分。CNN通过级联的方式聚合局部信息来学习图像的复杂表示。而局部信息的重要性很大程度上取决于每个图像的属性。例如,当一个图像被模糊化时,大多数有意义的微观模式,如物体的纹理,都会被抹去。在这种情况下,最好在早期层中扩展感受野,集中于全局信息。另一方面,如果一幅图像在局部细节中包含大量类特定的信息,例如纹理,则识别局部信息将会更加重要。

为了验证假设,作者构建了CIFAR-100数据集的两个变体,CIFAR-tile和CIFAR-large,如图1(b)和(c)所示。作者模型在很大程度上优于人工设计的模型。

贡献

为了缓解人工构建的体系结构和操作的次优性,作者提出了动态优化池操作(DynOPool),这是一个可学习的调整大小模块,可以替代标准的调整大小操作。该模块为在数据集上学习的操作找到感受野的最佳比例因子,从而将网络中的中间特征图调整为适当的大小和形状。

论文的主要贡献:

1、解决了深度神经网络中现有尺度算子依赖于预定超参数的局限性。指出了在中间特征图中寻找最佳空间分辨率和感受野的重要性。

2、提出了一个可学习的调整尺寸大小的模块DynOPool,它可以找到中间特征图的最佳比例因子和感受域。DynOPool使用学习到的比例因子识别某一层的最佳分辨率和感受野,并将信息传播到后续层,从而在整个网络中实现规模优化。

3、证明了在图像分类和语义分割任务中,使用DynOPool的模型在多个数据集和网络架构上优于基线算法。它还显示了精度和计算成本之间的理想权衡。

方法

1.动态优化池(DynOPool)

图片

图2 DynOPool中的调整大小模块

模块通过优化一对输入和输出特征映射之间的比例因子r来优化查询点q的位置以及获得中间特征映射的最佳分辨率。DynOPool在不影响其他算子的情况下,自适应控制较深层接收域的大小和形状。

图片

图3 DynOPool整个的优化过程

针对比例因子r梯度不稳定,会产生梯度爆炸导致训练过程中分辨率发生显著变化的问题,使用a重新参数化r如下:

图片

2.模型复杂性约束

为了最大化模型的精度,DynOPool有时会有较大的比例因子,增加了中间特征图的分辨率。因此,为了约束计算代价,减少模型规模,引入了一个额外的损失项LGMACs,它由每次训练迭代t的分层GMACs计数的简单加权和给出,如下所示:

图片

实验

图片

表1 人工设计模型与使用DynOPool模型的精度(%)和GMACs比较

图片

图4 在VGG-16上使用人工设计的Shape Adaptor与使用DynOPool的训练模型可视化

图片

表2 在CIFAR-100数据集上DynOPool和Shape Adaptor的比较

图片

表3 在ImageNet数据集上EfficientNet-B0+DynOPool的性能

图片

表4 基于PascalVOC的HRNet-W48语义分割结果

结论

作者提出了一种简单而有效的动态优化池操作(DynOPool),它通过学习每个层中感受野的理想大小和形状来优化端到端的特征映射的比例因子,调整中间特征图的大小和形状,有效提取局部细节信息,从而优化模型的整体性能;

DynOPool还通过引入一个额外的损失项来限制计算成本,从而控制模型的复杂性。实验表明,在多个数据集上,该模型在图像分类和语义分割方面均优于基线网络。

NVIDIA训练深度学习模型加速:APEX库

最近在跑目标检测和图像分类模型,发现很多时候教程里需要 安装apex库,于是我就去网上搜索一下这个,发现apex大有来头;

官方:

https://nvidia.github.io/apex/amp.html

https://docs.nvidia.com/deeplearning/performance/mixed-precision-training/index.html

APEX 是来自英伟达 (NVIDIA) 的一个很好用的深度学习加速库。由英伟达开源,完美支持PyTorch框架,用于改变数据格式来减小模型显存占用的工具。其中最有价值的是 amp (Automatic Mixed Precision) ,将模型的大部分操作都用 Float16 数据类型测试,一些特别操作仍然使用 Float32。并且用户仅仅通过三行代码即可完美将自己的训练代码迁移到该模型。实验证明,使用 Float16 作为大部分操作的数据类型,并没有降低参数,在一些实验中,反而由于可以增大 Batch size,带来精度上的提升,以及训练速度上的提升。

使用理由

使用精度低于32位浮点的数值格式有许多好处。首先,它们需要更少的内存,从而能够训练和部署更大的神经网络。其次,它们需要较少的内存带宽,从而加快数据传输操作。第三,数学运算在降低精度方面运行得更快,特别是在具有TensorCore支持的GPU上。混合精度训练(Mixed Precision Training)实现了所有这些好处,同时确保与完全精度训练相比,不会丢失特定任务的准确性。它这样做的方法是识别需要完全精度的步骤,只对这些步骤使用32位浮点,而在其他地方使用16位浮点。

在PyTorch中的使用:
首先需要安装其apex库(我还没装过),其github地址:https://github.com/NVIDIA/apex。
然后在训练的脚本(代码)中简单添加几句就可以了

from apex import amp

amp.init()
amp.init_trainer(trainer)
with amp.scale_loss(loss, trainer) as scaled_loss:
   autograd.backward(scaled_loss) 

APEX的配置

前提是你安装好了CUDA和CUDNN,以及你的系统是Ubuntu系统。

git clone https://github.com/NVIDIA/apex
cd apex
pip install -v --no-cache-dir --global-option="--cpp_ext" --global-option="--cuda_ext" 

Apex 还通过以下方式支持仅 Python 构建 (Pytorch 0.4 需要)。

pip install -v --disable-pip-version-check --no-cache-dir ./

安装之后,clone下来的apex文件夹就可以删除了。

查看能否正确导入apex:

from apex import amp

深度学习中的 Attention 机制总结与代码实现(2017-2021年)

转载自作者:mayiwei1998
本文转载自:GiantPandaCV
原文链接:
深度学习中的Attention总结

github地址:

https://github.com/xmu-xiaoma666/External-Attention-pytorch

1. External Attention

1.1. 引用

Beyond Self-attention: External Attention using Two Linear Layers for Visual Tasks.—arXiv 2021.05.05

论文地址:https://arxiv.org/abs/2105.02358

1.2. 模型结构

图片

1.3. 简介

这是五月份在arXiv上的一篇文章,主要解决的Self-Attention(SA)的两个痛点问题:(1)O(n^2)的计算复杂度;(2)SA是在同一个样本上根据不同位置计算Attention,忽略了不同样本之间的联系。因此,本文采用了两个串联的MLP结构作为memory units,使得计算复杂度降低到了O(n);此外,这两个memory units是基于全部的训练数据学习的,因此也隐式的考虑了不同样本之间的联系。

1.4. 使用方法

from attention.ExternalAttention import ExternalAttention
import torch


input=torch.randn(50,49,512)
ea = ExternalAttention(d_model=512,S=8)
output=ea(input)
print(output.shape)

2. Self Attention

2.1. 引用

Attention Is All You Need—NeurIPS2017

论文地址:https://arxiv.org/abs/1706.03762

2.2. 模型结构

2.3. 简介

这是Google在NeurIPS2017发表的一篇文章,在CV、NLP、多模态等各个领域都有很大的影响力,目前引用量已经2.2w+。Transformer中提出的Self-Attention是Attention的一种,用于计算特征中不同位置之间的权重,从而达到更新特征的效果。首先将input feature通过FC映射成Q、K、V三个特征,然后将Q和K进行点乘的得到attention map,再将attention map与V做点乘得到加权后的特征。最后通过FC进行特征的映射,得到一个新的特征。(关于Transformer和Self-Attention目前网上有许多非常好的讲解,这里就不做详细的介绍了)

2.4. 使用方法

from attention.SelfAttention import ScaledDotProductAttention
import torch

input=torch.randn(50,49,512)
sa = ScaledDotProductAttention(d_model=512, d_k=512, d_v=512, h=8)
output=sa(input,input,input)
print(output.shape)

3. Squeeze-and-Excitation(SE) Attention

3.1. 引用

Squeeze-and-Excitation Networks—CVPR2018

论文地址:https://arxiv.org/abs/1709.01507

3.2. 模型结构

图片

3.3. 简介

这是CVPR2018的一篇文章,同样非常具有影响力,目前引用量7k+。本文是做通道注意力的,因其简单的结构和有效性,将通道注意力掀起了一波小高潮。大道至简,这篇文章的思想可以说非常简单,首先将spatial维度进行AdaptiveAvgPool,然后通过两个FC学习到通道注意力,并用Sigmoid进行归一化得到Channel Attention Map,最后将Channel Attention Map与原特征相乘,就得到了加权后的特征。

3.4. 使用方法

from attention.SEAttention import SEAttention
import torch

input=torch.randn(50,512,7,7)
se = SEAttention(channel=512,reduction=8)
output=se(input)
print(output.shape)

4. Selective Kernel(SK) Attention

4.1. 引用

Selective Kernel Networks—CVPR2019

论文地址:https://arxiv.org/pdf/1903.06586.pdf

4.2. 模型结构

图片

4.3. 简介

这是CVPR2019的一篇文章,致敬了SENet的思想。在传统的CNN中每一个卷积层都是用相同大小的卷积核,限制了模型的表达能力;而Inception这种“更宽”的模型结构也验证了,用多个不同的卷积核进行学习确实可以提升模型的表达能力。作者借鉴了SENet的思想,通过动态计算每个卷积核得到通道的权重,动态的将各个卷积核的结果进行融合。

个人认为,之所以所这篇文章也能够称之为lightweight,是因为对不同kernel的特征进行通道注意力的时候是参数共享的(i.e. 因为在做Attention之前,首先将特征进行了融合,所以不同卷积核的结果共享一个SE模块的参数)。

本文的方法分为三个部分:Split,Fuse,Select。Split就是一个multi-branch的操作,用不同的卷积核进行卷积得到不同的特征;Fuse部分就是用SE的结构获取通道注意力的矩阵(N个卷积核就可以得到N个注意力矩阵,这步操作对所有的特征参数共享),这样就可以得到不同kernel经过SE之后的特征;Select操作就是将这几个特征进行相加。

4.4. 使用方法

from attention.SKAttention import SKAttention
import torch

input=torch.randn(50,512,7,7)
se = SKAttention(channel=512,reduction=8)
output=se(input)
print(output.shape)

5. CBAM Attention

5.1. 引用

CBAM: Convolutional Block Attention Module—ECCV2018

论文地址:https://openaccess.thecvf.com/content_ECCV_2018/papers/Sanghyun_Woo_Convolutional_Block_Attention_ECCV_2018_paper.pdf

5.2. 模型结构

图片
图片

5.3. 简介

这是ECCV2018的一篇论文,这篇文章同时使用了Channel Attention和Spatial Attention,将两者进行了串联(文章也做了并联和两种串联方式的消融实验)。

Channel Attention方面,大致结构还是和SE相似,不过作者提出AvgPool和MaxPool有不同的表示效果,所以作者对原来的特征在Spatial维度分别进行了AvgPool和MaxPool,然后用SE的结构提取channel attention,注意这里是参数共享的,然后将两个特征相加后做归一化,就得到了注意力矩阵。

Spatial Attention和Channel Attention类似,先在channel维度进行两种pool后,将两个特征进行拼接,然后用7×7的卷积来提取Spatial Attention(之所以用7×7是因为提取的是空间注意力,所以用的卷积核必须足够大)。然后做一次归一化,就得到了空间的注意力矩阵。

5.4. 使用方法

from attention.CBAM import CBAMBlock
import torch

input=torch.randn(50,512,7,7)
kernel_size=input.shape[2]
cbam = CBAMBlock(channel=512,reduction=16,kernel_size=kernel_size)
output=cbam(input)
print(output.shape)

6. BAM Attention

6.1. 引用

BAM: Bottleneck Attention Module—BMCV2018

论文地址:https://arxiv.org/pdf/1807.06514.pdf

6.2. 模型结构

图片

6.3. 简介

这是CBAM同作者同时期的工作,工作与CBAM非常相似,也是双重Attention,不同的是CBAM是将两个attention的结果串联;而BAM是直接将两个attention矩阵进行相加。

Channel Attention方面,与SE的结构基本一样。Spatial Attention方面,还是在通道维度进行pool,然后用了两次3×3的空洞卷积,最后将用一次1×1的卷积得到Spatial Attention的矩阵。

最后Channel Attention和Spatial Attention矩阵进行相加(这里用到了广播机制),并进行归一化,这样一来,就得到了空间和通道结合的attention矩阵。

6.4.使用方法

from attention.BAM import BAMBlock
import torch

input=torch.randn(50,512,7,7)
bam = BAMBlock(channel=512,reduction=16,dia_val=2)
output=bam(input)
print(output.shape)

7. ECA Attention

7.1. 引用

ECA-Net: Efficient Channel Attention for Deep Convolutional Neural Networks—CVPR2020

论文地址:https://arxiv.org/pdf/1910.03151.pdf

7.2. 模型结构

图片

7.3. 简介

这是CVPR2020的一篇文章。

如上图所示,SE实现通道注意力是使用两个全连接层,而ECA是需要一个的卷积。作者这么做的原因一方面是认为计算所有通道两两之间的注意力是没有必要的,另一方面是用两个全连接层确实引入了太多的参数和计算量。

因此作者进行了AvgPool之后,只是使用了一个感受野为k的一维卷积(相当于只计算与相邻k个通道的注意力),这样做就大大的减少的参数和计算量。(i.e.相当于SE是一个global的注意力,而ECA是一个local的注意力)。

7.4. 使用方法:

from attention.ECAAttention import ECAAttention
import torch

input=torch.randn(50,512,7,7)
eca = ECAAttention(kernel_size=3)
output=eca(input)
print(output.shape)

8. DANet Attention

8.1. 引用

Dual Attention Network for Scene Segmentation—CVPR2019

论文地址:https://arxiv.org/pdf/1809.02983.pdf

8.2. 模型结构

图片
图片
图示, 示意图  描述已自动生成

8.3. 简介

这是CVPR2019的文章,思想上非常简单,就是将self-attention用到场景分割的任务中,不同的是self-attention是关注每个position之间的注意力,而本文将self-attention做了一个拓展,还做了一个通道注意力的分支,操作上和self-attention一样,不同的通道attention中把生成Q,K,V的三个Linear去掉了。最后将两个attention之后的特征进行element-wise sum。

8.4. 使用方法

from attention.DANet import DAModule
import torch

input=torch.randn(50,512,7,7)
danet=DAModule(d_model=512,kernel_size=3,H=7,W=7)
print(danet(input).shape)

9. Pyramid Split Attention(PSA)

9.1. 引用

EPSANet: An Efficient Pyramid Split Attention Block on Convolutional Neural Network—arXiv 2021.05.30

论文地址:https://arxiv.org/pdf/2105.14447.pdf

9.2. 模型结构

图片
图片

9.3. 简介

这是深大5月30日在arXiv上上传的一篇文章,本文的目的是如何获取并探索不同尺度的空间信息来丰富特征空间。网络结构相对来说也比较简单,主要分成四步,第一步,将原来的feature根据通道分成n组然后对不同的组进行不同尺度的卷积,得到新的特征W1;第二步,用SE在原来的特征上进行SE,从而获得不同的阿头疼托尼;第三步,对不同组进行SOFTMAX;第四步,将获得attention与原来的特征W1相乘。

9.4. 使用方法

from attention.PSA import PSAimport torchinput=torch.randn(50,512,7,7)psa = PSA(channel=512,reduction=8)output=psa(input)print(output.shape)

10. Efficient Multi-Head Self-Attention(EMSA)

10.1. 引用

ResT: An Efficient Transformer for Visual Recognition—arXiv 2021.05.28

论文地址:https://arxiv.org/abs/2105.13677

10.2. 模型结构

图片

10.3. 简介

这是南大5月28日在arXiv上上传的一篇文章。本文解决的主要是SA的两个痛点问题:(1)Self-Attention的计算复杂度和n(n为空间维度大小)呈平方关系;(2)每个head只有q,k,v的部分信息,如果q,k,v的维度太小,那么就会导致获取不到连续的信息,从而导致性能损失。这篇文章给出的思路也非常简单,在SA中,在FC之前,用了一个卷积来降低了空间的维度,从而得到空间维度上更小的K和V。

10.4. 使用方法

from attention.EMSA import EMSAimport torchfrom torch import nnfrom torch.nn import functional as Finput=torch.randn(50,64,512)emsa = EMSA(d_model=512, d_k=512, d_v=512, h=8,H=8,W=8,ratio=2,apply_transform=True)output=emsa(input,input,input)print(output.shape)

深度学习调参技巧

以下文章来源于AI算法与图像处理 ,作者AI_study

最近在跑模型,发现自己跑出来的性能总是跟论文里的有些差别,对于很多参数,学习率、批次大小等没啥概念。。。

训练深度神经网络是困难的。它需要知识和经验,以适当的训练和获得一个最优模型。在这篇文章中,我想分享我在训练深度神经网络时学到的东西。以下提示和技巧可能对你的研究有益,并可以帮助你加速网络架构或参数搜索。

  • 1、

在你开始建立你的网络体系结构,你需要做的第一件事是验证输入到网络的数据,确保输入(x)对应于一个标签(y)。在预测的情况下,确保真实标签(y)正确编码标签索引(或者one-hot-encoding)。否则,训练就不起作用。

  • 2、

决定是选择使用预模型还是从头开始训练你的网络?

如果问题域中的数据集类似于ImageNet数据集,则对该数据集使用预训练模型。使用最广泛的预训练模型有VGG net、ResNet、DenseNet或Xception等。有许多层架构,例如,VGG(19和16层),ResNet(152, 101, 50层或更少),DenseNet(201, 169和121层)。注意:不要尝试通过使用更多的层网来搜索超参数(例如VGG-19, ResNet-152或densen -201层网络,因为它在计算量很大),而是使用较少的层网(例如VGG-16, ResNet-50或densen -121层)。选择一个预先训练过的模型,你认为它可以用你的超参数提供最好的性能(比如ResNet-50层)。在你获得最佳超参数后,只需选择相同但更多的层网(如ResNet-101或ResNet-152层),以提高准确性。ImageNet:http://www.image-net.org/challenges/LSVRC/2012/VGG net :https://arxiv.org/abs/1409.1556ResNet:https://arxiv.org/abs/1512.03385DenseNet:https://arxiv.org/abs/1608.06993Xception :https://arxiv.org/abs/1610.02357

微调几层,或者如果你有一个小的数据集,只训练分类器,你也可以尝试在你要微调的卷积层之后插入Dropout层,因为它可以帮助对抗网络中的过拟合。Dropout:http://jmlr.org/papers/v15/srivastava14a.html

如果你的数据集与ImageNet数据集不相似,你可以考虑从头构建并训练你的网络。

  • 3、

在你的网络中始终使用归一化层(normalization layers)。如果你使用较大的批处理大小(比如10个或更多)来训练网络,请使用批标准化层(BatchNormalization)。否则,如果你使用较小的批大小(比如1)进行训练,则使用InstanceNormalization层。请注意,大部分作者发现,如果增加批处理大小,那么批处理规范化会提高性能,而当批处理大小较小时,则会降低性能。但是,如果使用较小的批处理大小,InstanceNormalization会略微提高性能。或者你也可以尝试组规范化(GroupNormalization)。BatchNormalization:https://arxiv.org/abs/1502.03167InstanceNormalization:https://arxiv.org/abs/1607.08022GroupNormalization:https://arxiv.org/abs/1803.08494

  • 4、SpatialDropout

如果你有两个或更多的卷积层(比如Li)对相同的输入(比如F)进行操作(参考下面的示意图理解),那么在特征连接后使用SpatialDropout。由于这些卷积层是在相同的输入上操作的,因此输出特征很可能是相关的。因此,SpatialDropout删除了那些相关的特征,并防止网络中的过拟合。注意: 它主要用于较低的层而不是较高的层。SpatialDropout:https://arxiv.org/abs/1411.4280

SpatialDropout是Tompson等人在图像领域提出的一种dropout方法。普通的dropout会随机地将部分元素置零,而SpatialDropout会随机地将部分区域置零,该dropout方法在图像识别领域实践证明是有效的。Dropout操作随机地将部分元素置零,并且对非零部分做了一个尺度变换。尺度变换的幅度跟初始化的drop_rate有关。
作用
一般,我们会将dropout理解为“一种低成本的集成策略”,这是对的,具体过程可以大概这样理解:
经过上述置零操作后,我们可以认为零的部分是被丢弃的,丢失了一部分信息。因而,逼着模型用剩下的信息去拟合目标。然而每次dropout是随机的。我们就不能侧重于某些节点,所以总的来说就是—每次逼着模型用少量的特征学习,每次被学习的特征又不同,那么就是说,每个特征都应该对
模型的预测有所贡献(而不是侧重于部分特征,导致过拟合)。

通的dropout会随机独立地将部分元素置零,而SpatialDropout1D会随机地对某个特定的纬度全部置零。因此SpatialDropout1D需要指定Dropout维度,即对应dropout函数中的参数noise_shape。

  • 5、

为了确定你的网络容量,尝试用一小部分训练例子来超载你的网络(andrej karpathy的提示)。如果它没有超载,增加你的网络容量。在过拟合后,使用正则化技巧如L1、L2、Dropout或其他技术来对抗过拟合。L1:https://keras.io/regularizers/L2:https://keras.io/regularizers/Dropout:http://jmlr.org/papers/v15/srivastava14a.html

  • 6、

另一种正则化技术是约束或限制你的网络权值。这也有助于防止网络中的梯度爆炸问题,因为权值总是有界的。与L2正则化相反,在你的损失函数中惩罚高权重,这个约束直接正则化你的权重。你可以在Keras中轻松设置权重约束

  • 7、

对数据进行均值减法有时会产生非常糟糕的效果,特别是对灰度图像进行减法(我个人在前景分割领域就遇到过这个问题)。

  • 8、在训练前和训练期间,确保打乱训练数据,以防你不能从时序数据中获取有用信息。这可能有助于提高您的网络性能。
  • 9、如果你的问题域与稠密预测(dense prediction)相关(如语义分割),我建议你使用膨胀残差网络作为预训练模型,因为它最适合稠密预测。Dilated Residual Networks:https://arxiv.org/abs/1705.09914
  • 10. 要捕获对象周围的上下文信息,可以使用多尺度特性的池化模块。该思想成功地应用于语义分割或前景分割中。semantic segmentation:https://arxiv.org/abs/1802.02611foreground segmentation:https://arxiv.org/abs/1808.01477
  • 11 、 Opt-out void labels(或模糊区域)从您的损失或精度计算,如果有。这可以帮助你的网络在预测时更有信心。
  • 12、如果你有高度不平衡的数据问题,在训练期间应用类别加权操作。换句话说,给稀少的类更多的权重,但给主要类更少的权重。使用sklearn可以很容易地计算类权重。或者尝试使用过采样和欠采样技术重新采样你的训练集。这也可以帮助提高预测的准确性。
  • 13、选择一个正确的优化器。有许多流行的自适应优化器,如Adam, Adagrad, Adadelta,或RMSprop等。SGD+动量被广泛应用于各种问题领域。有两件事需要考虑:第一,如果你关心快速收敛,使用自适应优化器,如Adam,但它可能会陷入局部极小,提供了糟糕的泛化(下图)。第二,SGD+momentum可以实现找到全局最小值,但它依赖于鲁棒初始化,而且可能比其他自适应优化器需要更长的时间来收敛(下图)。我建议你使用SGD+动量,因为它能达到更好的最佳效果。有三个学习率起点(即1e- 1,1e -3和1e-6)。如果您对预训练模型进行微调,请考虑小于1e-3(比如1e-4)的低学习率。如果您从头开始训练您的网络,请考虑一个大于或等于1e-3的学习率。您可以尝试这些起点,并调整它们,看看哪个是最好的,选择那个。还有一件事,您可以考虑通过使用 Learning Rate Schedulers来降低训练过程中的学习率。这也可以帮助提高网络性能。
  • 14、 除了Learning Rate Schedule 外,即在一定的次数后降低学习率,还有另一种方式,我们可以由一些因素减少学习率,如果验证损loss在某些epoch(比如5)停止改善,减小学习率和如果验证损失停止改善在某些epoch(比如10),停止训练过程。这可以通过在Keras中使用early stop的ReduceLROnPlateau很容易做到。
  • 15、如果您在dense prediction领域工作,如前景分割或语义分割,您应该使用跳过连接,因为对象边界或有用的信息会由于最大池化操作或strided convolutions而丢失。这也可以帮助您的网络轻松地学习特征空间到图像空间的特征映射,有助于缓解网络中的消失梯度问题。
  • 16、数据越多越好!总是使用数据增强,如水平翻转,旋转,缩放裁剪等。这可以帮助大幅度提高精确度。
  • 17、你必须要有一个高速的GPU来进行训练,但是这有点昂贵。如果你想使用免费的云GPU,我推荐使用谷歌Colab。如果你不知道从哪里开始,看看我之前的文章或者尝试各种云GPU平台,如Floydhub或Paperspace等。
  • 18、

在ReLU之前使用最大池化来节省一些计算。由于ReLU阈值的值为0:f(x)=max(0,x)和最大池化只有max激活:f(x)=max(x1,x2,…,xi),使用Conv > MaxPool > ReLU 而不是Conv > ReLU > MaxPool。例如,假设我们有两个从Conv来的激活值(即0.5和-0.5):因此MaxPool > ReLU = max(0, max(0.5,-0.5)) = 0.5和ReLU > MaxPool = max(max(0,0.5), max(0,-0.5)) = 0.5看到了吗?这两个操作的输出仍然是0.5。在这种情况下,使用MaxPool > ReLU可以节省一个max 操作。

19、 考虑采用深度可分离卷积运算,与常规的卷积运算相比,该运算速度快,且参数数量大大减少。Depthwise Separable Convolution:https://arxiv.org/abs/1610.02357

神经网络和相关算法的简单 PyTorch 实现

github地址:

https://github.com/labmlai/annotated_deep_learning_paper_implementations

这是神经网络和相关算法的简单 PyTorch 实现的集合。这些实现与解释一起记录,

该网站 将这些呈现为并排格式化的注释。我们相信这些将帮助您更好地理解这些算法。

截屏

我们几乎每周都在积极维护这个 repo 并添加新的实现。 更新。

模块:

✨ Transformers

✨ Recurrent Highway Networks

✨ LSTM

✨ HyperNetworks – HyperLSTM

✨ ResNet

✨ ConvMixer

✨ Capsule Networks

✨ Generative Adversarial Networks

✨ Diffusion models

✨ Sketch RNN

✨ Graph Neural Networks

✨ Counterfactual Regret Minimization (CFR)

Solving games with incomplete information such as poker with CFR.

✨ Reinforcement Learning

✨ Optimizers

✨ Normalization Layers

✨ Distillation

✨ Adaptive Computation

✨ Uncertainty

Installation

pip install labml-nn

DALL·E-2:从文本生成图像

去年 1 月 6 日,OpenAI 发布了新模型 DALL·E,不用跨界也能从文本生成图像,打破了自然语言与视觉次元壁,引起了 AI 圈的一阵欢呼。时隔一年多后,DALL·E 迎来了升级版本——DALL·E 2。

DALL·E 2 是一个新的人工智能系统,可以根据自然语言的描述创建逼真的图像和艺术。

链接:

1、试玩 https://openai.com/dall-e-2/

2、论文地址:https://cdn.openai.com/papers/dall-e-2.pdf

3、github : https://github.com/lucidrains/DALLE2-pytorch

示例:

TEXT DESCRIPTION 文本描述:

An astronautTeddy bearsA bowl of soup

输出:

unknown

网络:(具体细节还没仔细看论文)

生成模型的迭代

DALL·E 2 建立在 CLIP 之上,OpenAI 研究科学家 Prafulla Dhariwal 说:「DALL·E 1 只是从语言中提取了 GPT-3 的方法并将其应用于生成图像:将图像压缩成一系列单词,并且学会了预测接下来会发生什么。」这是许多文本 AI 应用程序使用的 GPT 模型。但单词匹配并不一定能符合人们的预期,而且预测过程限制了图像的真实性。CLIP 旨在以人类的方式查看图像并总结其内容,OpenAI 迭代创建了一个 CLIP 的倒置版本——「unCLIP」,它能从描述生成图像,而 DALL·E 2 使用称为扩散(diffusion)的过程生成图像。

训练数据集由图像 x 及其对应的字幕 y 对 (x, y) 组成。给定图像 x, z_i 和 z_t 分别表示 CLIP 图像和文本嵌入。OpenAI 生成堆栈以使用两个组件从字幕生成图像:

  • 先验 P(z_i |y) 生成以字幕 y 为条件的 CLIP 图像嵌入 z_i;
  • 解码器 P(x|z_i , y) 以 CLIP 图像嵌入 z_i(以及可选的文本字幕 y)为条件生成图像 x。

解码器允许研究者在给定 CLIP 图像嵌入的情况下反演图像(invert images),而先验允许学习图像嵌入本身的生成模型。堆叠这两个组件产生一个图像 x 、给定字幕 y 的生成模型 P(x|y) :

DALL·E 的完整模型从未公开发布,但其他开发人员在过去一年中已经构建了一些模仿 DALL·E 功能的工具。最受欢迎的主流应用程序之一是 Wombo 的 Dream 移动应用程序,它能够根据用户描述的各种内容生成图片。 

图片

OpenAI 已经采取了一些内置的保护措施。该模型是在已剔除不良数据的数据集上进行训练的,理想情况下会限制其产生令人反感的内容的能力。为避免生成的图片被滥用,DALL·E 2 在生成的图片上都标有水印,以表明该作品是 AI 生成的。此外,该模型也无法根据名称生成任何可识别的面孔。DALL·E 2 将由经过审查的合作伙伴进行测试,但有一些要求:禁止用户上传或生成「可能造成伤害」的图像。他们还必须说明用 AI 生成图像的作用,并且不能通过应用程序或网站将生成的图像提供给其他人。