【问题标题】:How to define a Recurrent Convolutional network layer in CNTK?如何在 CNTK 中定义循环卷积网络层?
【发布时间】:2017-08-13 10:12:38
【问题描述】:

我是 CNTK 的新手,正在使用它很棒的 python API。我无法弄清楚如何定义循环卷积网络层,因为 Recurrence() 似乎只假设一个常规网络层。

更具体地说,我想在卷积层之间进行循环。

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

【问题讨论】:

    标签: python cntk rnn


    【解决方案1】:

    有两种方法可以有意义地做到这一点(即不破坏卷积所依赖的自然图像的结构)。最简单的是在最后一层有一个 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)
    

    【讨论】:

    • 谢谢尼科斯。是的,第二种情况是我正在寻找的,即仅使用卷积的循环单元,一个简单的例子会很好,非常感谢。目前,我将研究您建议的 GRU 示例。关于训练,有什么需要注意的吗?例如BPTT 详细信息和内存问题。
    • 我用一个实际的卷积 GRU 更新了答案。
    • 非常感谢 Nikos,这是一个非常清晰的步进函数示例,非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2018-06-29
    • 1970-01-01
    • 1970-01-01
    • 2019-05-06
    • 1970-01-01
    • 2015-05-07
    • 2017-07-30
    • 1970-01-01
    相关资源
    最近更新 更多