Yolov3-darknet53代码学习笔记

1.make_layer循环堆叠残差块网络结构

2.BN与Relu的作用

3.网络结构构建()与输出值(输入参数X自动使用forward类方法)

4.类与实例化与继承

nn.BatchNorm2d(palnes[0])详解

torch.nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)

num_features:通道数,eps用于分母添加一个极小数防止除以0

affine:对gamma,beta参数具有可学习能力

momentum:用来计算平均值和方差的值,默认值为0.1

输入参数(N,C,H,W)输出(N,C,H,W)

作用:把每层神经网络任意神经元这个输入值的分布强行拉回到均值为0方差为1的标准正态分布,其实就是把越来越偏的分布强制拉回比较标准的分布,这样使得激活输入值落在非线性函数对输入比较敏感的区域,这样输入的小变化就会导致损失函数较大的变化,意思是这样让梯度变大,避免梯度消失问题产生,而且梯度变大意味着学习收敛速度快,能大大加快训练速度。
 

3x3,1x1卷积块

        # 进行权值初始化
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
                m.weight.data.normal_(0, math.sqrt(2. / n))##初始化权重
            elif isinstance(m, nn.BatchNorm2d):
                m.weight.data.fill_(1)##BN归一化
                m.bias.data.zero_()

初始化

class DarkNet(nn.Module):
    def __init__(self, layers):
        super(DarkNet, self).__init__()

继承类创建,super继承父类,模板,layers为调用Darknet需要初始化的参数

残差块创建

    def _make_layer(self, planes, blocks):
        layers = []
        # 下采样,步长为2,卷积核大小为3
        layers.append(("ds_conv", nn.Conv2d(self.inplanes, planes[1], kernel_size=3, stride=2, padding=1, bias=False)))
        layers.append(("ds_bn", nn.BatchNorm2d(planes[1])))
        layers.append(("ds_relu", nn.LeakyReLU(0.1)))

 larers.append处通道数已变为[1]

class BasicBlock(nn.Module):
    def __init__(self, inplanes, planes):
        super(BasicBlock, self).__init__()
        self.conv1  = nn.Conv2d(inplanes, planes[0], kernel_size=1, stride=1, padding=0, bias=False)
        self.bn1    = nn.BatchNorm2d(planes[0])
        self.relu1  = nn.LeakyReLU(0.1)
        
        self.conv2  = nn.Conv2d(planes[0], planes[1], kernel_size=3, stride=1, padding=1, bias=False)
        self.bn2    = nn.BatchNorm2d(planes[1])
        self.relu2  = nn.LeakyReLU(0.1)

在残差块中通道数:planes[1]->[0]->[1]

        for i in range(0, blocks):##迭代创建残差块层结构
            layers.append(("residual_{}".format(i), BasicBlock(self.inplanes, planes)))
        return nn.Sequential(OrderedDict(layers))##列表转字典转容器

循环创建残差块blocks,创建个数

通过makelayer创建多个类似的残差块堆叠结构

        self.inplanes = 32
        # 416,416,3 -> 416,416,32
        self.conv1  = nn.Conv2d(3, self.inplanes, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn1    = nn.BatchNorm2d(self.inplanes)
        self.relu1  = nn.LeakyReLU(0.1)

        # 416,416,32 -> 208,208,64
        self.layer1 = self._make_layer([32, 64], layers[0])
        # 208,208,64 -> 104,104,128
        self.layer2 = self._make_layer([64, 128], layers[1])
        # 104,104,128 -> 52,52,256
        self.layer3 = self._make_layer([128, 256], layers[2])
        # 52,52,256 -> 26,26,512
        self.layer4 = self._make_layer([256, 512], layers[3])
        # 26,26,512 -> 13,13,1024
        self.layer5 = self._make_layer([512, 1024], layers[4])

        self.layers_out_filters = [64, 128, 256, 512, 1024]

3->32->64->128->256->512->1024

layers参数为残差块迭代次数(个数)

        # 进行权值初始化
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
                m.weight.data.normal_(0, math.sqrt(2. / n))##初始化权重
            elif isinstance(m, nn.BatchNorm2d):
                m.weight.data.fill_(1)##BN归一化
                m.bias.data.zero_()

权重、参数初始化

for m in self.modules

self.modules是nn.Module的类方法,会返回所有的网络结构

conv初始化w,batch初始化b

 n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels

w的参数个数卷积块长宽尺寸与通道数相乘如下图3x3x3

m.weight.data->得到一个张量tensor

m.weight->得到可训练参数list

上述构建的为具体的网络结构,应用还需要具体的值

m = nn.LeakyReLU(0.1) # 构建LeakyReLU函数
input = torch.randn(2) # 输入
output = m(input) # 对输入应用LeakyReLU函数

需要对应的input值与如m的值来封装网络结构

darknet实例化

if __name__=="__main__":
    import torch
    # from torchvision.models.detection import darknet53
    # 创建DarkNet53模型
    model = darknet53()
   def forward(self, x):
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu1(x)

        x = self.layer1(x)
        x = self.layer2(x)
        out3 = self.layer3(x)
        out4 = self.layer4(out3)
        out5 = self.layer5(out4)

        return out3, out4, out5
    input_image = torch.randn(1, 3, 416, 416)

    # 将输入数据送入模型进行前向传播
    out3, out4, out5 = model(input_image)

实例化后输入参数x(处理图像),自动调用类中含有X的函数forword得到三个特征提取层

该forword为darknet的类方法,输入张量x传递给网络即会自动使用

class BasicBlock(nn.Module):
    def __init__(self, inplanes, planes):
        super(BasicBlock, self).__init__()
        self.conv1  = nn.Conv2d(inplanes, planes[0], kernel_size=1, stride=1, padding=0, bias=False)
        self.bn1    = nn.BatchNorm2d(planes[0])
        self.relu1  = nn.LeakyReLU(0.1)
        
        self.conv2  = nn.Conv2d(planes[0], planes[1], kernel_size=3, stride=1, padding=1, bias=False)
        self.bn2    = nn.BatchNorm2d(planes[1])
        self.relu2  = nn.LeakyReLU(0.1)

    def forward(self, x):
        residual = x

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu1(out)

        out = self.conv2(out)
        out = self.bn2(out)
        out = self.relu2(out)

        out += residual
        return out

残差块构建,当输入张量x时使用类方法forward

        for i in range(0, blocks):##迭代创建残差块层结构
            layers.append(("residual_{}".format(i), BasicBlock(self.inplanes, planes)))

再darknet中的forward类方法中的make_layer会循环进入basicblock启用forward类方法

实例化的网络结构可以处理x参数而不需要说明?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值