我正在尝试通过使用预训练的嵌入和自定义语料库在带有Tensorflow后端的Keras 2中重新训练word2vec模型。
这是我如何使用预训练的嵌入初始化嵌入层的方法:
embedding = Embedding(vocab_size, embedding_dim,
input_length=1, name='embedding',
embeddings_initializer=lambda x: pretrained_embeddings)
其中pretrained_embeddings
是大小为vocab_size
x embedding_dim
只要pretrained_embeddings
不太大就可以使用。
不幸的是,不是我的情况-vocab_size=2270872
和embedding_dim=300
。
初始化Embeddings层时,出现错误:
Cannot create a tensor proto whose content is larger than 2GB.
错误来自于函数add_weight()
/opt/r/anaconda3/lib/python3.6/site-packages/keras/engine/base_layer.py
,更具体地说是以下行:
weight = K.variable(initializer(shape),
dtype=dtype,
name=name,
constraint=constraint)
initializer
是上面的lambda函数,它返回大矩阵。如上所述,shape
是(2270872, 300)
。
是否可以解决这个问题而不必进行低级Tensorflow编程?如果我将Theano用作后端,则代码运行良好,但是我想使用Tensorflow以获得更好的长期前景。
我发现的唯一类似的Stackoverflow问题是this,它提出了占位符变量,但是我不确定如何将它们应用于Keras级别。
非常感谢
编辑: 我非常愿意在Tensorflow后端的级别上解决此问题。只是我不知道在这种情况下如何在同一应用程序中组合Tensorflow和Keras代码。大多数示例是一个或另一个,而不是两者。
例如,当Keras中的Embeddings层的初始化不可避免地调用add_weight()函数时,Tensorflow占位符变量有什么用,这会导致问题?
解决方案:
正如@ blue-phoenox的评论所暗示的,我重新编写了如下代码:
embedding = Embedding(vocab_size, embedding_dim,
input_length=1,
name='embedding')
embedding.build(input_shape=(1,)) # the input_shape here has no effect in the build function
embedding.set_weights([pretrained_embeddings])
做到了。再次感谢@ blue-phoenox。
答案 0 :(得分:3)
您可以使用embeddings_initializer
参数为嵌入层加载预先训练的权重,而不必使用Embedding层的weights
参数,这样您就可以移交预先训练的嵌入大于2GB。
这是一个简短的示例:
from keras.layers import Embedding
embedding_layer = Embedding(vocab_size,
EMBEDDING_DIM,
weights=[embedding_matrix],
input_length=MAX_SEQUENCE_LENGTH,
trainable=False)
embedding_matrix
只是包含权重的常规numpy矩阵。
例如,您也可以在这里查看:
https://blog.keras.io/using-pre-trained-word-embeddings-in-a-keras-model.html
编辑:
正如 @PavlinMavrodiev (请参阅问题结尾)指出,weights
参数已被弃用。他改为使用 layer方法 set_weights
设置权重:
layer.set_weights(weights)
:从列表中设置图层的权重 的Numpy数组(形状与get_weights
的输出相同)。
要获得训练后的权重,可以使用get_weights
:
layer.get_weights()
:返回图层的权重作为列表 numpy数组。
这都是Keras Layer-Baseclass中的方法,可用于所有keras层,包括嵌入层。