mxnet与tensorflow的卷积实现细节比较
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