mxnet与tensorflow的卷积实现细节比较

时间:2024-01-14 14:20:50

mxnet的卷积 kernel = 3  pad=1边界补充0后,不管stride是否1还是2,imgw = 奇数或者偶数, 都是从图像位置(0,0)开始卷积

tensorlfow的卷积 kernel = 3 pad=‘SAME’边界补充0后,

imgw = 偶数

stride=1, 是从图像位置(0,0)开始卷积

stride=2, 是从图像位置(1,1)开始卷积 与mxnet不同

imgw = 奇数

stride=1, 是从图像位置(0,0)开始卷积

stride=2, 是从图像位置(0,0)开始卷积

tensorlfow的卷积 kernel = 3 pad=‘VAILD’ 边界不补充0,

不管stride是否1还是2,imgw = 奇数或者偶数, 都是从图像位置(1,1)开始卷积

#coding=utf-8
import math
import mxnet as mx
import numpy as np
import tensorflow as tf
from mxnet.gluon import nn
from mxnet import ndarray as nd
# import tensorlayer as tl
# from tensorflow.contrib.layers.python.layers import utils
# import collections
# from tensorlayer.layers import Layer, list_remove_repeat def out_dim(input, kernel, stride, pad, dilate):
x = input
p = pad
s = stride
d = dilate
k = kernel
output = math.floor((x + 2 * p - d * (k - 1) - 1) / s) + 1
return output #比较mxnet与tensorflow的conv batchnorm prelu的计算
#mxnet卷积层
# 输入数据格式是:batch * inchannel * height * width
# 输出数据格式是:batch * outchannel * height * width
# 权重格式: output_channels * in_channels * height * width
#(1)比较卷积
height = 6
width = 6
inchannel = 1
outchannel = 1 # #conv0 (64, 112, 112) kernel (3, 3) stride (1, 1) pad (1, 1)
# wkernel = 3
# stride = 1
# pad = 1
# dilate = 1
# output_height = out_dim(height, wkernel, stride, pad, dilate)
# if output_height == height:
# print("input: ", height, width, " wkernel", wkernel, " stride: ", stride, " pad:", pad, " output_height: ", output_height, output_height, "SAME")
# else:
# print("input: ", height, width, " wkernel", wkernel, " stride: ", stride, " pad:", pad, " output_height: ", output_height, output_height, "VALID") #stage1_unit1_conv2 (64, 56, 56) kernel (3, 3) stride (2, 2) pad (1, 1)
wkernel = 3
stride = 2
pad = 1
dilate = 1
output_height = out_dim(height, wkernel, stride, pad, dilate)
if output_height == height:
print("input: ", height, width, " wkernel", wkernel, " stride: ", stride, " pad:", pad, " output_height: ", output_height, output_height, "SAME")
else:
print("input: ", height, width, " wkernel", wkernel, " stride: ", stride, " pad:", pad, " output_height: ", output_height, output_height, "VALID") # #stage1_unit1_conv1sc (64, 56, 56) kernel (1, 1) stride (2, 2) pad (0, 0)
# wkernel = 1
# stride = 2
# pad = 0
# dilate = 1
# output_height = out_dim(height, wkernel, stride, pad, dilate)
# if output_height == height:
# print("input: ", height, width, " wkernel", wkernel, " stride: ", stride, " pad:", pad, " output_height: ", output_height, output_height, "SAME")
# else:
# print("input: ", height, width, " wkernel", wkernel, " stride: ", stride, " pad:", pad, " output_height: ", output_height, output_height, "VALID") w = nd.arange(wkernel * wkernel * inchannel * outchannel).reshape((outchannel,inchannel,wkernel,wkernel))
b = nd.array([0])
data = nd.arange(height * width * inchannel).reshape((1,inchannel,height,width))
# mxnet直接nd卷积运算nd.Convolution
#out = nd.Convolution(data,w,b,kernel=w.shape[2:],num_filter=outchannel,stride=(1,1), pad=(1, 1))
print('input:',data)
print('weight:',w)
#print('bias:',b)
# print('mxnet ndarray output:',out)
# print('\n') #mxnet利用symbol计算卷积
ws = mx.sym.Variable('w')
bs = mx.sym.Variable('b')
datas = mx.sym.Variable('data')
# outs = mx.sym.Convolution(data=datas, weight=ws, bias=bs, num_filter=w.shape[1], kernel=w.shape[2:], stride=(1,1), pad=(0, 0),
# no_bias=False, name="conv0")
outs = mx.sym.Convolution(data=datas, weight=ws, num_filter=outchannel, kernel=w.shape[2:], stride=(stride,stride), pad=(pad, pad),
no_bias=True, name="conv0")
#outs = mx.sym.Convolution(datas,ws,bs,kernel=w.shape[2:],num_filter=w.shape[1])
ex=outs.bind(mx.cpu(), {'data':data, 'w':w, 'b':b})
ex.forward()
mxnetresult = ex.outputs[0].asnumpy()
print("mxnet symbol:\n", ex.outputs[0].asnumpy())
# output_height = out_dim(height, w.shape[2], stride, pad, dilate)
# output_width = out_dim(width, w.shape[2], stride, pad, dilate)
# print("input_height: ", height, width)
# print("output_height: ", output_height, output_width) #tensorflow计算卷积
#(W-F + 2 p / S)+ 1
# 输入数据格式是:batch * height * width * inchannel
# 输出数据格式是:batch * height * width * outchannel
# 权重格式: height * width * in_channels * output_channels
# w = np.arange(4).reshape((2,2,1,1))
# b = np.array([0])
# data = np.arange(9).reshape((1,3,3,1))
# w = w.reshape((wkernel,wkernel,inchannel,outchannel)).asnumpy()
# data = data.reshape((1, height,width,inchannel)).asnumpy() data = data.asnumpy().transpose(0,2,3,1)
w = w.asnumpy().transpose(2,3,1,0)
b = b.asnumpy()
# print('input:',data)
# print('inputshape:',data.shape)
# print('weight:',w)
# print('weight:',w.shape)
input = tf.Variable(data, dtype=np.float32)
#input_reshape = tf.reshape(input, [1,inchannel,height,width])
filter = tf.Variable(w, dtype=np.float32)
#filter_reshape = tf.reshape(filter, [outchannel,inchannel,wkernel,wkernel])
if pad == 0:
conv = tf.nn.conv2d(input, filter, strides=[1, stride, stride, 1], padding='VALID')
else:
conv = tf.nn.conv2d(input, filter, strides=[1, stride, stride, 1], padding='SAME') kernel_size = 3
kernel_size_effective = kernel_size
pad_total = kernel_size_effective - 1
pad_beg = pad_total // 2
pad_end = pad_total - pad_beg
print(pad_beg, pad_end)
input_PadLayer = tf.pad(input, [[0, 0], [pad_beg, pad_end], [pad_beg, pad_end], [0, 0]], name='padding') if stride==2:
conv_padlayer = tf.nn.conv2d(input_PadLayer, filter, strides=[1, stride, stride, 1], padding='VALID') # nets = tl.layers.Conv2d(inputs, n_filter=num_outputs, filter_size=(kernel_size, kernel_size), b_init=None,
# strides=(strides, strides), W_init=w_init, act=None, padding='VALID', name=scope,
# use_cudnn_on_gpu=True)
#nets = BatchNormLayer(nets, act=tf.identity, is_train=True, trainable=trainable, name=scope+'bn3')
#conv_reshape = tf.reshape(conv, [1,outchannel,output_height,output_height])
#conv_reshape = tf.reshape(conv, [1,1,2,2]) init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
#print("input: \n", sess.run(input))
input_reshape = sess.run(input).transpose(0,3,1,2)
#print("input_reshape: \n", input_reshape)
#print("filter: \n", sess.run(filter))
filter_reshape = sess.run(filter).transpose(3,2,0,1)
#print("filter_reshape: \n", filter_reshape)
#print("conv ", sess.run(conv))
conv_reshape = sess.run(conv).transpose(0,3,1,2)
print("conv_reshape: \n", conv_reshape)
if stride==2:
input_PadLayer_reshape = sess.run(input_PadLayer).transpose(0,3,1,2)
print("input_PadLayer_reshape: \n", input_PadLayer_reshape) conv_padlayer_reshape = sess.run(conv_padlayer).transpose(0,3,1,2)
print("conv_padlayer_reshape: \n", conv_padlayer_reshape) tensorflowresult = conv_padlayer_reshape
else:
tensorflowresult = conv_reshape
#print("tf_height", op2_reshape.shape.as_list())
#print("tf_height", op2_reshape.shape.as_list())
if (tensorflowresult==mxnetresult).all():
print("success ")
else:
print("failed ")

input: 6 6 wkernel 3 stride: 2 pad: 1 output_height: 3 3 VALID
input:
[[[[ 0. 1. 2. 3. 4. 5.]
[ 6. 7. 8. 9. 10. 11.]
[ 12. 13. 14. 15. 16. 17.]
[ 18. 19. 20. 21. 22. 23.]
[ 24. 25. 26. 27. 28. 29.]
[ 30. 31. 32. 33. 34. 35.]]]]
<NDArray 1x1x6x6 @cpu(0)>
weight:
[[[[ 0. 1. 2.]
[ 3. 4. 5.]
[ 6. 7. 8.]]]]
<NDArray 1x1x3x3 @cpu(0)>
mxnet symbol:
[[[[ 103. 196. 262.]
[ 411. 618. 690.]
[ 735. 1050. 1122.]]]]
1 1
conv_reshape:
[[[[ 366. 438. 294.]
[ 798. 870. 546.]
[ 451. 481. 271.]]]]
input_PadLayer_reshape:
[[[[ 0. 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 1. 2. 3. 4. 5. 0.]
[ 0. 6. 7. 8. 9. 10. 11. 0.]
[ 0. 12. 13. 14. 15. 16. 17. 0.]
[ 0. 18. 19. 20. 21. 22. 23. 0.]
[ 0. 24. 25. 26. 27. 28. 29. 0.]
[ 0. 30. 31. 32. 33. 34. 35. 0.]
[ 0. 0. 0. 0. 0. 0. 0. 0.]]]]
conv_padlayer_reshape:
[[[[ 103. 196. 262.]
[ 411. 618. 690.]
[ 735. 1050. 1122.]]]]
success