使用部分共享权重训练两个Keras模型

时间:2017-10-19 04:05:49

标签: python machine-learning keras

我正在使用Keras进行(字符)序列到序列的RNN应用。由于我有一组相对较少的A - >; B,以及B的更大的一组例子,我决定尝试自动编码器方法:首先训练网络以学习B上的身份功能,为B的成员产生嵌入,然后训练网络以学习A - >嵌入(B)。通过将第二个网络与第一个网络的一半解码器相结合,希望它能够推广出合理的B。

Building Autoencoders in Keras教程为模型的代码看起来像这样(为了简单起见,省略了几个层,丢失,正则化等):

class Example:
    def __init(self, ...):
        # Sets dense_size, rnn, rnn_size, embed_size, input_len, output_len, etc.

    def apply_encoder(self, input_word):
        input_masked = Masking()(input_word)
        input_dense = TimeDistributed(Dense(self.dense_size), name='input_dense')(input_masked)
        rnn = self.rnn(self.rnn_size, name='input_rnn')(input_dense)
        embedding = Dense(self.embed_size, name='embedding')(rnn)
        return embedding

    def apply_decoder(self, embedding):
        repeated = RepeatVector(self.output_len, name='repeat')(embedding)
        rnn = self.rnn(self.rnn_size, name='output_rnn')(repeated)
        output_dense = TimeDistributed(Dense(self.dense_size), name='output_dense')(rnn)
        output_word = TimeDistributed(
            Dense(self.chars, activation='softmax'),
            name='output_word'
            )(output_dense)
        return output_word

    def build_net(self):
        input_word = Input(shape=(self.input_len, self.chars), name='input_word')
        embedding = self.apply_encoder(input_word)
        output_word = self.apply_decoder(embedding)

        self.autoencoder = Model(input_word, output_word)
        self.encoder = Model(input_word, embedding)

        embed_input = Input(shape=(self.embed_size,), name='input_embedding')
        decoder_output = self.apply_decoder(embed_input)

        self.decoder = Model(embed_input, decoder_output)

    def save_models(self):
        open('models/autoencoder.json', 'w').write(self.autoencoder.to_json())
        open('models/encoder.json', 'w').write(self.encoder.to_json())
        open('models/decoder.json', 'w').write(self.decoder.to_json())

第一个脚本在B上训练autoencoder - > B;然后另一个脚本实例化encoder两次并在A - >上训练encoderA encoderB.predict(B);最后,查询脚本使用encoderAdecoderB进行预测。

这一切都很好,但性能不如我想的那么好,所以我真正想做的是同时训练两个模型。我想要的是两个自动编码器模型,单独的编码器一半,但解码器一半的共享权重。然后我在一批A - >训练模型A之间交替。 B,并且在一批B上训练模型B - > B,应该在备用批次上更新两个编码器,但在每个批次上更新共享解码器。

我的问题是,简单地说,我如何构建这两个模型,以便按照我想要的方式共享权重? Here是一个类似的问题,但它只解释了如何做我已经做过的事情。如果后端很重要(可能没有),我可以使用TF或Theano。

1 个答案:

答案 0 :(得分:1)

使用功能API创建零件模型,并将它们连接起来,就像它们是图层一样。

不同之处在于您正在创建两个解码器(通过调用两次应用解码器)

编码器A:

aInput = Input(...)
encodedA = LotsOfLayers(...)(aInput)

self.encoderA = Model(aInput,encodedA)

编码器B:

bInput = Input(...)
encodedB = LotsOfLayers(...)(bInput)

self.encoderB = Model(bInput,encodedB)

<强>解码器:

我们在这里只创建一个解码器:

encodedInput = Input(...)
decodedOutput = LotsOfLayers(...)(encodedInput)

self.decoder = Model(encodedInput, decodedOutput)

<强> AutoencoderB:

这是猫的跳跃&#34;:

autoInput = Input(sameShapeAsEncoderBInput)
encoded = self.encoderB(autoInput)
decoded = self.decoder(encoded)

self.autoencoderB = Model(autoInput,decoded)

预测员来自A:

遵循相同的逻辑:

anotherAInput = Input(sameShapeAsEncoderAInput)
encoded = self.encoderA(anotherAInput)
decoded = self.decoder(encoded)

self.predictorFromA = Model(anotherAInput,decoded)

这将使解码器与A中的AutoencoderB和Predictor相同(共享权重)。