TYS的博客

算法小白努力学习中

0%

pytorch与mmcv源码学习

MMCV官方文档

https://mmcv.readthedocs.io/en/latest/api.html#module-mmcv.cnn

mmdetection中使用了注册机制,使用字典进行字符串向类的映射,在norm.py中,使用了如下的代码,以norm layer为例。

1
2
3
4
5
6
7
8
9
/mmcv/cnn/bricks/registry.py
NORM_LAYERS = Registry('norm layer')

/mmcv/cnn/bricks/norm.py
NORM_LAYERS.register_module('BN', module=nn.BatchNorm2d)
NORM_LAYERS.register_module('BN1d', module=nn.BatchNorm1d)
NORM_LAYERS.register_module('BN2d', module=nn.BatchNorm2d)

registry类实现在mmcv/runner/utils/registry.py文件中

build_norm_layer函数,通过type”BN”返回提前注册的类nn.BatchNorm2d,并用该类根据输入的num_features构造相应的归一化层,默认需要梯度(requires_grad=True)。

Pytorch源码学习

nn.Module

torch.utils.checkpoint 不缓存中间变量,时间换显存空间

ResNet源码阅读

preview

在mmcv的resnet.py文件中,对于resnet18与34,对应的block为BasicBlock,而50层以上的block为Bottleneck
卷积层分为stem与四个stage,stride=(1, 2, 2, 2),stride=2是第一个3x3的卷积层。在reset中,只有第一个块的stride是2,其余均为1。

self.downsample在第一层需要对原输入x进行大小与通道数的调整,后续的block不需要进行该操作。

1
2
if self.downsample is not None:
identity = self.downsample(x)

代码中的dcn为可变形卷积(deformable convlution)

_freeze_stage,将前几个stage的梯度更新设置为false,model设置为eval()模式。

block 每一个模块有num_blocks,对于blocks之间的连接,只有第一个block是进行残差学习。

在每一个block连接中,inplanes = planes * expansion,在每一个res_layer之间的连接中,planes = base_channels * 2 ** i ,在res_layer结束后,将inplanes设置为当前的planes * expansion

model.eval()

eval将dropout层设置为无效,batchnorm层的running_meanrunning_var不更新。BatchNorm层的均值与方差采用momentum进行更新$\hat{x}_{new} = (1 - momentum) \times \hat{x} + momentum \times x_t$。

drop_out实现原理

1
2
3
4
5
6
7
8
def dropout(X,drop_prob):
X = X.float()
assert 0<=drop_prob<=1
keep_prob = 1-drop_prob
if keep_prob==0:
return torch.torch.zeros_like(X)
mask = (torch.rand(X.shape)<keep_prob).float()
return mask * X / keep_prob