我试图创建一个以单词作为输入的模型。大多数这些词都在手套词向量集(~50000)中。但是,一些常用词不是(~1000)。问题是,如何连接以下两个嵌入层以创建一个巨大的Embedding
查找表?
trained_em = Embedding(50000, 50,
weights=np.array([word2glove[w] for w in words_in_glove]),
trainable=False)
untrained_em = Embedding(1000, 50)
据我所知,这些只是两个具有相同维数的查找表。所以我希望有一种方法来堆叠这两个查找表。
编辑1:
我刚刚意识到这可能不仅仅是堆叠Embedding
层,因为输入序列将是来自0-50999
的数字。但上述untrained_em
仅预计来自0-999
的数字。所以也许需要一个不同的解决方案。
编辑2: 这是我期望在代表嵌入的numpy数组中做的事情:
np.random.seed(42) # Set seed for reproducibility
pretrained = np.random.randn(15,3)
untrained = np.random.randn(5,3)
final_embedding = np.vstack([pretrained, untrained])
word_idx = [2, 5, 19]
np.take(final_embedding, word_idx, axis=0)
我相信最后一点可以与keras.backend.gather
有关但不确定如何将它们放在一起。
答案 0 :(得分:2)
原来我需要实现自定义图层。这是通过调整orignial Embedding
类来实现的。
以下课程中显示的两个最重要的部分是self.embeddings = K.concatenate([fixed_weight, variable_weight], axis=0)
和out = K.gather(self.embeddings, inputs)
。第一个是希望自我解释,而第二个从input
表中选出相关的embeddings
行。
但是,在我正在处理的特定应用程序中,事实证明使用Embedding
层而不是修改层可以更好地解决问题。也许是因为学习率太高。在我进行了更多实验之后,我将回复此事。
from keras.engine.topology import Layer
import keras.backend as K
from keras import initializers
import numpy as np
class Embedding2(Layer):
def __init__(self, input_dim, output_dim, fixed_weights, embeddings_initializer='uniform',
input_length=None, **kwargs):
kwargs['dtype'] = 'int32'
if 'input_shape' not in kwargs:
if input_length:
kwargs['input_shape'] = (input_length,)
else:
kwargs['input_shape'] = (None,)
super(Embedding2, self).__init__(**kwargs)
self.input_dim = input_dim
self.output_dim = output_dim
self.embeddings_initializer = embeddings_initializer
self.fixed_weights = fixed_weights
self.num_trainable = input_dim - len(fixed_weights)
self.input_length = input_length
def build(self, input_shape, name='embeddings'):
initializer = initializers.get(self.embeddings_initializer)
shape1 = (self.num_trainable, self.output_dim)
variable_weight = K.variable(initializer(shape1), dtype=K.floatx(), name=name+'_var')
fixed_weight = K.variable(self.fixed_weights, name=name+'_fixed')
self._trainable_weights.append(variable_weight)
self._non_trainable_weights.append(fixed_weight)
self.embeddings = K.concatenate([fixed_weight, variable_weight], axis=0)
self.built = True
def call(self, inputs):
if K.dtype(inputs) != 'int32':
inputs = K.cast(inputs, 'int32')
out = K.gather(self.embeddings, inputs)
return out
def compute_output_shape(self, input_shape):
if not self.input_length:
input_length = input_shape[1]
else:
input_length = self.input_length
return (input_shape[0], input_length, self.output_dim)
答案 1 :(得分:1)
所以,我的建议是只使用一个嵌入层(考虑到你的索引问题),并将权重从旧层转移到新层。
所以,你在这个建议中要做的是......
使用51000字创建新模型:
inp = Input((1,))
emb = Embedding(51000,50)(inp)
out = the rest of the model.....
model = Model(inp,out)
现在进行嵌入图层并给它你的权重:
weights = np.array([word2glove[w] for w in words_in_glove])
newWeights = model.layers[1].get_weights()[0]
newWeights[:50000,:] = weights
model.layers[1].set_weights([newWeights])
这将为您提供一个比前一个更大的新嵌入,其中很大一部分权重已经过训练,剩下的随机初始化。
不幸的是,你必须让一切都受到训练。