如何在TensorFlow中动态设置动态卷积的扩张率?

时间:2018-05-04 16:29:43

标签: python tensorflow while-loop

我正在编写一个自定义的递归神经网络。网络状态在while循环体中定义,并且当某个条件发生时递归停止。我想使用迭代次数作为循环内部某些函数的参数。例如,当我使用萎缩卷曲时,我希望扩张速度取决于当前的迭代。

def body(self,..., iteration):
    dilation_rate = 2**iteration
    state = tf.nn.atrous_conv2d(..., rate = dilation_rate)
    iteration += 1

def RNN_loop(...)
    iter = tf.constant(np.array(0), dtype = tf.int32)
    ... = tf.while_loop(self.condition, self.body, [...,iter])

因为迭代被定义为张量,所以我不知道如何将它传递给期望数字的atrous_conv2d。如果我尝试使用iteration.eval来评估循环内张量的值,我得到:

ValueError: Operation u'layer/while/Identity_4' has been marked as not fetchable.

如果我将张量传递给我得到的函数:

ValueError: setting an array element with a sequence.

1 个答案:

答案 0 :(得分:0)

TL; DR :使用tf.nn.convolution()代替tf.nn.atrous_conv2d()并短路tf.nn._nn_ops._get_strides_and_dilation_rate()。 (请参阅答案底部的代码示例。)

<强> TS; WM

tf.nn.atrous_conv2d()的实施基本上只需调用tf.nn.convolution()dilation_rate设置为[rate, rate]This是源代码中的当前位置,但我在此处复制它(没有130行注释),因为它可能会更改,因此链接可能会过时:

def atrous_conv2d(value, filters, rate, padding, name=None):
    return convolution(
        input=value,
        filter=filters,
        padding=padding,
        dilation_rate=np.broadcast_to(rate, (2,)),
        name=name)

在此明确np.broadcast_to()使dilation_rate无法使用张量。tf.nn.convolution()。也许在_get_strides_and_dilation_rate()那么?

嗯,理论上,是的,直到调用dilation_rate = np.array(dilation_rate, dtype=np.int32) ,其中最无益的是

Convolution

之后,_WithSpaceToBatch.__init__()课程并不在乎,dilation_rate = ops.convert_to_tensor( dilation_rate, dtypes.int32, name="dilation_rate") 会立即明确地将其转换为张量:

tf.nn._get_strides_and_dilation_rate()

因此,如果您非常确信您的参数是正确的,那么您可以将tf.nn.convolution()短路,然后使用双暗扩张率直接调用import tensorflow as tf square_size = 5 dr = tf.placeholder( shape = ( 2, ), dtype = tf.int32 ) inp = tf.reshape( tf.constant( range( square_size * square_size ), dtype = tf.float32 ), ( 1, square_size, square_size, 1 ) ) fltr = tf.reshape( tf.ones( ( 3, 3 ) ), ( 3, 3, 1, 1 )) _original = tf.nn._nn_ops._get_strides_and_dilation_rate tf.nn._nn_ops._get_strides_and_dilation_rate = lambda a, b, c : ( b, c ) state = tf.nn.convolution( inp, fltr, "SAME", strides = [ 1, 1 ], dilation_rate = dr ) tf.nn._nn_ops._get_strides_and_dilation_rate = _original with tf.Session() as sess: print( sess.run( tf.squeeze( inp ) ) ) print print( sess.run( tf.squeeze( state ), feed_dict = { dr : [ 2, 2 ] } ) ) print print( sess.run( tf.squeeze( state ), feed_dict = { dr : [ 3, 3 ] } ) ) ,就像这段代码一样(测试):

tf.squeeze

将以动态更改的扩张率输出结果(const subarrays = array.map(pair => pair.split()); 仅用于易读性):

  

[[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.]]

     

[[24. 28. 42. 28. 32.]
   [44. 48. 72. 48. 52.]
   [66. 72. 108. 72. 78.]
   [44. 48. 72. 48. 52.]
   [64. 68. 102. 68. 72.]]

     

[[36。 40. 19. 36. 40.]
   [56。 60. 29. 56. 60.]
   [23。 25. 12. 23. 25.]
   [36。 40. 19. 36. 40.]
   [56。 60. 29. 56. 60.]]