我正在使用 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 个模型,他需要大约 20 个模型。10GB 可保存所有型号!在这种情况下,瓶颈是每个模型都在内部保存了词嵌入权重,而它们总是相同的。
试图找到一种足够的方法来减小模型的大小,我认为最好在外部加载实际的特征向量(嵌入)。,这意味着加载一个(X,max_sequence_size, embeddings_size)形状的 nd 数组,它实际上是 实际嵌入的max_sequence_size时间步长的X个填充序列。
我找不到任何关于这个重要问题的讨论。在 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'])
随意评论和批评,非常欢迎您!