使k210支持Tensorflow卷积

我昨天咋编译模型的时候,碰到k210 model-compiler提示ValueError: conv2d MobilenetV1/Conv2d_12_depthwise/depthwise:0 should use padding=SAME.他说我的卷积输入不正确,让我使用samepadding.但是我查看了代码,的确使用的same卷积.所以今天就来解决下这个问题.

1. 查看代码

首先我看了下出错的代码:

1
2
3
if self.input_shape[1:3] != self.output_shape[1:3]:
print(self.input_shape, self.output_shape)
raise ValueError('conv2d {} should use padding=SAME'.format(tensor_info.get('name', 'noname')))

上面的意思是要卷积输入输出中间两维形状要相等.然后我print了一下我的shape:

1
2
3
4
[layer 23]: MobilenetV1/Conv2d_12_depthwise/Relu6:0
shape(HWC): 15x20x256 ==> 16x20x256
scale,bias: (0.023529411764705882,0.0) ==> (0.023529411764705882,0.0)
[5, 15, 20, 256] [5, 16, 20, 256]

可以看到,他这里提示15与16不匹配了.

2. 查看原图

因为我是强行把mobilenet的224输入改成了(240,320)的输入.所以会有一些维度上的冲突.

我查看原图的节点时发现:

1
[?,15,20,256]=== stride=2 padding='same' ===>[?,8,10,256]

3. 原因

这里我就想通了,在Tensorflow中,对于samepadding输出为: \[ new\_height=new\_weight=\lceil\frac{W}{S}\rceil \] 对于vaild输出为: \[ new\_height=new\_weight=\lceil\frac{(W-F+1)}{S}\rceil \]

所以\(\lceil15/2\rceil=8\) 但是在k210中应该是不支持这个操作,应该是内部操作只支持整数的操作.所以我们需要修改代码.

4. 解决方案

  1. 首先尝试padding之后用same卷积. 因为这里的使用的是depthwise_conv2d_native卷积.所以不知道k210中是否支持这个卷积的same操作.所以先试试. 我使用类似于下面的操作进行padding:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    a = tf.constant(np.zeros((1, 15, 20, 256)), dtype=tf.float32)
    b = tf.space_to_batch(a, [[1, 0], [0, 0]], block_size=1)
    c = tf.nn.depthwise_conv2d_native(b, tf.ones((3, 3, 256, 1)), strides=[1, 2, 2, 1], padding='SAME')
    print(a)
    print(b)
    print(c)
    """
    Tensor("Const_3:0", shape=(1, 15, 20, 256), dtype=float32)
    Tensor("SpaceToBatchND_7:0", shape=(1, 16, 20, 256), dtype=float32)
    Tensor("DepthwiseConv2dNative_6:0", shape=(1, 8, 10, 256), dtype=float32)
    """

    经过尝试之后,我发现在k210 model-compiler报错:

    1
    2
    3
    4
    [layer 23]: MobilenetV1/Conv2d_12_depthwise/Relu6:0
    shape(HWC): 14x18x256 ==> 8x10x256
    scale,bias: (0.023529411764705882,0.0) ==> (0.023529411764705882,0.0)
    [5, 14, 18, 256] [5, 8, 10, 256]

    他居然把我的输入识别成了[14,18].问了群里的人,他们说space to batch nd就是为了做padding的 后面的卷积当然不需要再次padding,所以要用valid 我还是不太理解为什么维度会和Tensorflow board里面不相同.

  2. 现在尝试valid卷积 那么我给heightwidthpadding[3,2]. \[ \lceil\frac{15+3-3+1}{2}\rceil=8 \] \[ \lceil\frac{20+2-3+1}{2}\rceil=10 \] 对应代码为:

    1
    tf.space_to_batch(a, [[2, 1], [1, 1]], block_size=1)

    现在来尝试一下编译.就显示编译成功了.