如何在CNTK中定义循环卷积网络层?

时间:2017-08-13 10:12:39

标签: python cntk rnn

我是CNTK的新手,并使用其出色的python API。我有问题弄清楚如何定义一个递归卷积网络层,因为Recurrence()似乎只假设一个常规的网络层。

更具体地说,我想在卷积层中重复出现。

任何指针或甚至一个简单的例子都将受到高度赞赏。谢谢。

1 个答案:

答案 0 :(得分:0)

有两种方法可以以有意义的方式做到这一点(即,不会破坏卷积所依赖的自然图像的结构)。最简单的是在最后一层只有一个LSTM,即

convnet = C.layers.Sequential([Convolution(...), MaxPooling(...), Convolution(...), ...])
z = C.layers.Sequential([convnet, C.layers.Recurrence(LSTM(100)), C.layers.Dense(10)])

对于10级问题。

更复杂的方法是定义自己的循环细胞,它只使用卷积,从而尊重自然图像的结构。要定义循环单元格,您需要编写一个函数,该函数采用先前的状态和输入(即,如果您正在处理视频,则为单个帧)并输出下一个状态和输出。例如,您可以查看the implementation of the GRU in the CNTK layers module,并将其调整为在任何地方使用convolution而不是times。如果这是你想要的,我可以尝试提供这样的例子。但是,我建议您先尝试一下这个简单的方法。

更新:我写了一个准系统卷积GRU。您需要特别注意如何定义初始状态,否则它似乎工作正常。这是图层定义

def ConvolutionalGRU(kernel_shape, outputs, activation=C.tanh, init=C.glorot_uniform(), init_bias=0, name=''):
    conv_filter_shape = (outputs, C.InferredDimension) + kernel_shape
    bias_shape = (outputs,1,1)
    # parameters
    bz = C.Parameter(bias_shape, init=init_bias, name='bz')  # bias
    br = C.Parameter(bias_shape, init=init_bias, name='br')  # bias
    bh = C.Parameter(bias_shape, init=init_bias, name='bc')  # bias
    Wz = C.Parameter(conv_filter_shape, init=init, name='Wz') # input
    Wr = C.Parameter(conv_filter_shape, init=init, name='Wr') # input
    Uz = C.Parameter(conv_filter_shape, init=init, name='Uz') # hidden-to-hidden
    Ur = C.Parameter(conv_filter_shape, init=init, name='Hz') # hidden-to-hidden
    Wh = C.Parameter(conv_filter_shape, init=init, name='Wc') # input
    Uh = C.Parameter(conv_filter_shape, init=init, name='Hc') # hidden-to-hidden
    # Convolutional GRU model function
    def conv_gru(dh, x):
        zt = C.sigmoid (bz + C.convolution(Wz, x) + C.convolution(Uz, dh))        # update gate z(t)
        rt = C.sigmoid (br + C.convolution(Wr, x) + C.convolution(Ur, dh))        # reset gate r(t)
        rs = dh * rt                                                            # hidden state after reset
        ht = zt * dh + (1-zt) * activation(bh + C.convolution(Wh, x) + C.convolution(Uh, rs))
        return ht
    return conv_gru

以下是如何使用它

x = C.sequence.input_variable(3,224,224))
z = C.layers.Recurrence(ConvolutionalGRU((3,3), 32), initial_state=C.constant(0, (32,224,224)))
y = z(x)
x0 = np.random.randn(16,3,224,224).astype('f') # a single seq. with 16 random "frames"
output = y.eval({x:x0}) 
output[0].shape
(16, 32, 224, 224)