tensorflow版darknet——darkflow 升级depthwise_convolutional layer


要想人前显贵,必定人后遭罪————一次小小的记录

一、darkflow安装

首先从github上git下来源码,然后安装cython,最后将工程封装成python下的一个可执行文件

git clone https://github.com/thtrieu/darkflow.git
cd darkflow
python3 setup.py build_ext --inplace

pip3 install -e .
# 或者
pip3 install .

二、darkflow升级

darkflow如何将darknet与tensorflow联系起来的呢?

1、网络结构方面:darknet网络结构定义采用cfg来定义,所以darkflow首先要解析cfg文件,从而构建计算图。

2、网络权重方面:darknet的权重是以.weights后缀的二进制文件保存,而tensorflow训练时主要以ckpt文件、meta文件等形式保存,因而,需要根据cfg解析.weights文件,读取进tensorflow计算图,训练后保存生成tensorflow权重文件。

废话说多了,开撸~~

(1)升级cfg文件解析模块

1、位置:utils文件夹下,process.py文件,cfg_yielder()函数修改

增加如下代码:

#---------------added by wei------------------
	elif d['type'] == '[depthwise_convolutional]':
		#n = d.get('filters', 1) dw_conv do not need this param
		#            its input channels are equal to output channels
		size = d.get('size', 1)
		stride = d.get('stride', 1)
		pad = d.get('pad', 0)
		padding = d.get('padding', 0)
		if pad: padding = size // 2
		activation = d.get('activation', 'logistic')
		batch_norm = d.get('batch_normalize', 0) or conv
		yield ['depthwise_convolutional', i, size, c, c,
			stride, padding, batch_norm,
			activation]
		if activation != 'linear': yield [activation, i]
		w_ = (w + 2 * padding - size) // stride + 1
		h_ = (h + 2 * padding - size) // stride + 1
		w, h, c = w_, h_, c
		l = w * h * c
#-----------------------------------------------------

这段代码是为了解析cfg文件中我在darknet原始框架下增加的,层名标志为:[depthwise_convolutional],关于原始框架的升级这里就跳过啦,有需要后面再更新吧。

depthwise layer不需要filter参数,它的filter是由上一个节点的输入所决定的,dw卷积前后通道保持不变(这个版本的dw_conv还需要与1x1的普通点卷积配合使用),这是与普通卷积层所不一样的。因此,这里的n(filter数量) 应该是等于c(输入的channels)的。

2、位置:darflow/dark/darkop.py

增加层名索引词典,为后面加载.weights权重做准备

插入如下词典:

    'depthwise_convolutional': depthwise_convolutional_layer,

顺其自然,接下来就要增加 depthwise_convolutional_layer类的实现。

(2)升级weights文件解析模块

1、位置:darkflow/dark/convolution.py

depthwise_convolutional_layer类的实现

#------------------------------------added by wei -------------------------------------
class depthwise_convolutional_layer(Layer):
    def setup(self, ksize, c, n, stride, pad, batch_norm, activation):
        #          核大小-输入c-核数
        print('Layer:','dw_conv','ksize=',ksize,'  c=', c,'  n=', n)
        self.batch_norm = bool(batch_norm)
        self.activation = activation
        self.stride = stride
        self.ksize = ksize
        self.pad = pad
        self.dnshape = [1, c, ksize, ksize] # darknet shape第一个维度n要换成1
        self.wshape = dict({
            'biases': [n],
            'kernel': [ksize, ksize, c, 1]#最后一个维度n换成1
        })
        if self.batch_norm:
            self.wshape.update({
                'moving_variance'  : [n],
                'moving_mean': [n],
                'gamma' : [n]
            })
            self.h['is_training'] = {
                'feed': True,
                'dfault': False,
                'shape': ()
            }

    def finalize(self, _):
        """deal with darknet"""
        kernel = self.w['kernel']
        if kernel is None: return
        kernel = kernel.reshape(self.dnshape)
        kernel = kernel.transpose([2,3,1,0])
        self.w['kernel'] = kernel

功能:解析weights文件中的depthwise_convolutional 层

2、位置:darkflow/utils/loader.py

在loder类中,层字典改成下面这样,加一层dw:

VAR_LAYER = ['convolutional','depthwise_convolutional','connected', 'local',
                 'select', 'conv-select',
                 'extract', 'conv-extract']

在weights_loader类中,字典改成这样:

_W_ORDER = dict({ # order of param flattened into .weights file
        'convolutional': [
            'biases','gamma','moving_mean','moving_variance','kernel'
        ],
        'depthwise_convolutional': [
            'biases', 'gamma', 'moving_mean', 'moving_variance', 'kernel'
        ],
        'connected': ['biases', 'weights'],
        'local': ['biases', 'kernels']
    })
    #权重、偏置、bn参数索引名称

另外,在weights_walker类中,更改如下:

self.offset = 20#原来是16

这个参数是控制读取地址偏移的,初值也就代表着起始地址偏移,darknet的权重文件起始有十六个字节是废的,存储了版本号、迭代次数什么乱七八糟的,因此在转换时要跳过。

(3)升级tensorflow加载模块

1、位置:darkflow/net/ops/_init.py
增加tensorflow加载层索引词典:

	'depthwise_convolutional': depthwise_convolutional,

2、位置:darkflow/net/ops/covolution.py

增加tensorflow加载时dw_conv类的实现方式:

#-----------------------added by wei-------------------------------

class depthwise_convolutional(BaseOp):
    def forward(self):
        pad = [[self.lay.pad, self.lay.pad]] * 2;
        temp = tf.pad(self.inp.out, [[0, 0]] + pad + [[0, 0]])
        temp = tf.nn.depthwise_conv2d(temp, self.lay.w['kernel'], padding = 'VALID',
            name = self.scope, strides = [1] + [self.lay.stride] * 2 + [1])
        if self.lay.batch_norm:
            temp = self.batchnorm(self.lay, temp)
        self.out = tf.nn.bias_add(temp, self.lay.w['biases'])

    def batchnorm(self, layer, inp):
        if not self.var:
            temp = (inp - layer.w['moving_mean'])
            temp /= (np.sqrt(layer.w['moving_variance']) + 1e-5)
            temp *= layer.w['gamma']
            return temp
        else:
            args = dict({
                'center' : False, 'scale' : True,
                'epsilon': 1e-5, 'scope' : self.scope,
                'updates_collections' : None,
                'is_training': layer.h['is_training'],
                'param_initializers': layer.w
                })
            return slim.batch_norm(inp, **args)
    def speak(self):
        l = self.lay
        args = [l.ksize] * 2 + [l.pad] + [l.stride]
        args += [l.batch_norm * '+bnorm']
        args += [l.activation]
        msg = 'dw_conv {}x{}p{}_{}  {}  {}'.format(*args)
        return msg

#----------------------------------------------------------------

这里我们就直接调tf.tf.nn.depthwise_conv2d()可以了,其他没什么变化,kernel形状我们前面就加以限制了。

三、其他

另外,我还增加了relu激活函数支持,类似的激活函数都可以往op_types里面添加:
位置:darkflow/net/ops/_init.py

op_types = {
	'convolutional': convolutional,
	'depthwise_convolutional': depthwise_convolutional,
	'conv-select': conv_select,
	'connected': connected,
	'maxpool': maxpool,
	'leaky': leaky,
	'relu': relu,        #added by wei
	'dropout': dropout,
	'flatten': flatten,
	'avgpool': avgpool,
	'softmax': softmax,
	'identity': identity,
	'crop': crop,
	'local': local,
	'select': select,
	'route': route,
	'reorg': reorg,
	'conv-extract': conv_extract,
	'extract': extract
}

下面添加relu的实现
位置:darkflow/net/ops/simple.py

#------------------------------------added by wei -------------------------------------
class relu(BaseOp):
	def forward(self):
		self.out = tf.nn.relu(
			self.inp.out,
	        name = self.scope
	    )
	def speak(self):
		return 'relu'

四、总结

至此,darkflow的depthwise_conv layer升级就实现了,其他层升级步骤也差不多是这样。就这样,thats all~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_learnWay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值