对darknet53中@wrap(Conv2D)的理解

今天在学习darknet53这个网络的时候,发现了@wrap(Conv2D)这么一行代码,这里谈一下我对这个函数装饰器的理解。
详细的@wrap装饰器可以参见[这里],这篇文章只谈对参数的操作。(https://www.runoob.com/w3cnote/python-func-decorators.html)

@wrap这个装饰器传入的是一个已经有的函数a,返回的是一个新的函数b。
那么为什么要进行这样的操作呢,两个函数前后可以有什么变化呢?

我这里的理解是:可以通过@wrap这个装饰器,在函数a的基础上,根据自己的需求,修改一些a中已经存在的参数,然后返回一个新的函数b供我们使用,这样做的好处应该就是在沿用函数a的默认参数的基础上,方便进行我们进行一些修改。

下面是一个简单的例子:

from functools import wraps
#定义一个函数Fun_1 返回name1+name2+name3
#默认的结果就是: N1 +' _ ' +  N2 + ' _ ' + N3
def Fun_1(name1 ='N1', name2 = 'N2', name3='N3'):
    return name1+ ' _ ' + name2 + ' _ ' + name3

@wraps(Fun_1)
def Fun_2(*args, **kwargs):
    #在这里 就可以对Fun1中的参数 进行操作
    Fun1_kwargs = {'name3':'N3_new'}#这里可以修改默认的参数值
    #还可以根据一个参数的值, 去修改其他参数的值
    Fun1_kwargs['name1'] = 'N1_new' if kwargs.get('name2') == 'N2' else 'N1_old'
    Fun1_kwargs.update(**kwargs)
    return Fun_1(*args, **Fun1_kwargs)

print(Fun_1())
print(Fun_2(name2='N2'))

输出结果:
N1 _ N2 _ N3
N1_new _ N2 _ N3_new

结论:
Fun_1中有name1 name2 name3三个参数,默认情况下分别是N1 N2 N3
通过装饰器生成的Fun_2这个函数实现了两个功能:
1.可以对Fun_1里面传入的默认参数进行修改
例子中实现代码:(Fun1_kwargs = {‘name3’:‘N3_new’})
2.可以根据一个参数的值, 去修改其他参数的值
例子中实现代码:Fun1_kwargs[‘name1’] = ‘N1_new’ if kwargs.get(‘name2’) == ‘N2’ else ‘N1_old’
也就是在Fun_2中,如果我传入了name=‘N2’,那么name1的值就会修改为’N1_new’。

这样就可以理解darknet53中DarknetConv2D这段代码了,其实就是对
from keras.layers import Conv2D这里面的Con2D进行了两处修改变为了Darknet中所需要的卷积方式(为什么要这么改呢 可以去看yolo3的论文):
1.正则化方式改为L2正则化,默认是None
2.当步长为2时, padding的方式才为valid。默认情况下是步长为1,padding为valid。


@wraps(Conv2D)
def DarknetConv2D(*args, **kwargs):
"""Wrapper to set Darknet parameters for Convolution2D."""
darknet_conv_kwargs = {'kernel_regularizer': l2(5e-4)}
darknet_conv_kwargs['padding'] = 'valid' if kwargs.get('strides')==(2,2) else 'same'
darknet_conv_kwargs.update(kwargs)
return Conv2D(*args, **darknet_conv_kwargs)
#这里是Con2D里面的所有参数
    def __init__(self, filters,
                 kernel_size,
                 strides=(1, 1),
                 padding='valid',
                 data_format=None,
                 dilation_rate=(1, 1),
                 activation=None,
                 use_bias=True,
                 kernel_initializer='glorot_uniform',
                 bias_initializer='zeros',
                 kernel_regularizer=None,
                 bias_regularizer=None,
                 activity_regularizer=None,
                 kernel_constraint=None,
                 bias_constraint=None,
                 **kwargs):

其实我感觉如果不用修饰符生成新的函数也是可以实现这些功能的,但是如果不封装成一个函数的话,可能在搭建网络结构的时候就没那么清晰吧。这样用起来比较方便,不用每次都去设置参数了。

  • 9
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值