Keras:将预先训练好的嵌入作为输入,而不是在嵌入层中加载权重

时间:2017-03-28 12:48:56

标签: neural-network keras lstm recurrent-neural-network word-embedding

我使用Keras库进行序列标记。我已经在我的实验中使用预先训练好的嵌入,使用这样的方法(https://blog.keras.io/using-pre-trained-word-embeddings-in-a-keras-model.html

我的代码(内部保存):

    self._model = Sequential(name='core_sequential')
    self._model.add(Embedding(input_dim=weights.shape[0], 
                              output_dim=weights.shape[1],
                              weights=[weights],
                              name="embeddings_layer",trainable=False))
    self._model.add(Dropout(dropout_rate,name='dropout_layer_1'))
    self._model.add(Bidirectional(LSTM(output_dim=300,
                                       return_sequences=distributed,
                                       activation="tanh",
                                       name="lstm_layer"),name='birnn_layer'))
    self._model.add(Dropout(dropout_rate,name='dropout_layer_2'))
    self._model.add(TimeDistributed(Dense(output_dim=1,
                                          activation='sigmoid',
                                          name='dense_layer'), 
                    name="timesteps_layer"))
    self._model.compile(optimizer=Adam(lr=lr),
                        loss='binary_crossentropy', 
                        metrics=['accuracy'])

这非常合适,我们只需要提供一个(X,max_sequence_size)形状的nd数组,这实际上是 X 填充的序列max_sequence_size 时间步长(单词索引)。

在模型内部保存预先训练好的嵌入,完全缩小了模型的尺寸(每个型号450MB)。如果有人想在他自己的系统上使用这个架构用于多个模型,那么让他们说20个,他需要大约。 10GB保存所有型号! 在这种情况下,瓶颈是每个模型都在内部保存了嵌入权重一词,但它们总是相同。

试图找到一种减少模型大小的充分方法,我认为最好从外部加载实际的特征向量(嵌入)。 ,这意味着要加载(X,max_sequence_size,embeddings_size)形状的nd数组,这实际上是 X 填充的 max_sequence_size 时间序列 - 实际嵌入的步骤。

我找不到关于这个重要问题的任何讨论。在Keras文档中,嵌入似乎是RNN中唯一可用的选择,keras社区似乎低估了这个内存问题。我试图找出解决方案。

解决方案(外部加载):

    self._model = Sequential(name='core_sequential')
    self._model.add(InputLayer((None, 200)))
    self._model.add(Dropout(dropout_rate,name='dropout_layer_1'))
    self._model.add(Bidirectional(LSTM(output_dim=300,
                                       return_sequences=distributed,
                                       activation="tanh",
                                       name="lstm_layer"),name='birnn_layer'))
    self._model.add(Dropout(dropout_rate,name='dropout_layer_2'))
    self._model.add(TimeDistributed(Dense(output_dim=1,
                                          activation='sigmoid',
                                          name='dense_layer'), 
                    name="timesteps_layer"))
    self._model.compile(optimizer=Adam(lr=lr),
                        loss='binary_crossentropy', 
                        metrics=['accuracy'])

以上代码有效,但请考虑以下事项:

  • 您可能需要从头开始微调!
  • 您必须格外小心序列的max_length。很少的异常值(巨大的序列)可能会产生问题。

我建议采用以下解决方案。

更好的解决方案(外部加载的嵌入+掩饰):

    self._model = Sequential(name='core_sequential')
    self._model.add(Masking(mask_value=0., input_shape=(None, 200)))
    self._model.add(Dropout(dropout_rate,name='dropout_layer_1'))
    self._model.add(Bidirectional(LSTM(output_dim=300,
                                       return_sequences=distributed,
                                       activation="tanh",
                                       name="lstm_layer"),name='birnn_layer'))
    self._model.add(Dropout(dropout_rate,name='dropout_layer_2'))
    self._model.add(TimeDistributed(Dense(output_dim=1,
                                          activation='sigmoid',
                                          name='dense_layer'), 
                    name="timesteps_layer"))
    self._model.compile(optimizer=Adam(lr=lr),
                        loss='binary_crossentropy', 
                        metrics=['accuracy'])

欢迎评论和批评,非常欢迎您!

1 个答案:

答案 0 :(得分:0)

解决方案(外部加载):

    self._model = Sequential(name='core_sequential')
    self._model.add(InputLayer((None, 200)))
    self._model.add(Dropout(dropout_rate,name='dropout_layer_1'))
    self._model.add(Bidirectional(LSTM(output_dim=300,
                                       return_sequences=distributed,
                                       activation="tanh",
                                       name="lstm_layer"),name='birnn_layer'))
    self._model.add(Dropout(dropout_rate,name='dropout_layer_2'))
    self._model.add(TimeDistributed(Dense(output_dim=1,
                                          activation='sigmoid',
                                          name='dense_layer'), 
                    name="timesteps_layer"))
    self._model.compile(optimizer=Adam(lr=lr),
                        loss='binary_crossentropy', 
                        metrics=['accuracy'])

以上代码有效,但请考虑以下事项:

  • 您可能需要从头开始微调!
  • 您必须格外小心序列的max_length。很少的异常值(巨大的序列)可能会产生问题。

我建议采用以下解决方案。

更好的解决方案(外部加载的嵌入+掩饰):

    self._model = Sequential(name='core_sequential')
    self._model.add(Masking(mask_value=0., input_shape=(None, 200)))
    self._model.add(Dropout(dropout_rate,name='dropout_layer_1'))
    self._model.add(Bidirectional(LSTM(output_dim=300,
                                       return_sequences=distributed,
                                       activation="tanh",
                                       name="lstm_layer"),name='birnn_layer'))
    self._model.add(Dropout(dropout_rate,name='dropout_layer_2'))
    self._model.add(TimeDistributed(Dense(output_dim=1,
                                          activation='sigmoid',
                                          name='dense_layer'), 
                    name="timesteps_layer"))
    self._model.compile(optimizer=Adam(lr=lr),
                        loss='binary_crossentropy', 
                        metrics=['accuracy'])

欢迎评论和批评,非常欢迎您!