Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 连接嵌入层_Python_Keras - Fatal编程技术网

Python 连接嵌入层

Python 连接嵌入层,python,keras,Python,Keras,我正在尝试创建一个以单词作为输入的模型。这些词中的大多数都在手套词向量集中(~50000)。然而,有些常用词不是(~1000)。问题是,如何连接以下两个嵌入层以创建一个巨大的嵌入查找表 trained_em = Embedding(50000, 50, weights=np.array([word2glove[w] for w in words_in_glove]), trainable=False)

我正在尝试创建一个以单词作为输入的模型。这些词中的大多数都在手套词向量集中(~50000)。然而,有些常用词不是(~1000)。问题是,如何连接以下两个嵌入层以创建一个巨大的
嵌入
查找表

trained_em = Embedding(50000, 50, 
                       weights=np.array([word2glove[w] for w in words_in_glove]), 
                       trainable=False)
untrained_em = Embedding(1000, 50)
据我所知,这只是两个具有相同维数的查找表。所以我希望有一种方法来堆叠这两个查找表

编辑1: 我刚刚意识到这可能不仅仅是堆叠
嵌入
层,因为输入序列将是
0-50999
中的一个数字。但是,上面的
未经培训的\u 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
来完成,但不确定如何将其组合在一起。

因此,我的建议是只使用一个嵌入层(考虑到索引问题),并将权重从旧层转移到新层

所以,你在这个建议中要做的是

创建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])
这将为您提供一个新的嵌入,比前一个更大,其大部分权重已经训练,其余的随机初始化


不幸的是,你必须让一切都经过训练

因此,我的建议是只使用一个嵌入层(考虑到索引问题),并将权重从旧层转移到新层

所以,你在这个建议中要做的是

创建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])
这将为您提供一个新的嵌入,比前一个更大,其大部分权重已经训练,其余的随机初始化


不幸的是,你必须让一切都经过训练

我需要实现一个自定义层。这是通过调整原始
嵌入
类实现的

下面的类中显示的两个最重要的部分是
self.embeddings=K.concatenate([fixed\u weight,variable\u weight],axis=0)
out=K.gather(self.embeddings,input)
。第一个是自解释的,而第二个则从
嵌入
表中选择相关的
输入

然而,在我正在开发的特定应用程序中,使用
嵌入层而不是修改层效果更好。也许是因为学习率太高了。在我做了更多的实验之后,我将对此进行汇报

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)

事实证明,我需要实现一个自定义层。这是通过调整原始
嵌入
类实现的

下面的类中显示的两个最重要的部分是
self.embeddings=K.concatenate([fixed\u weight,variable\u weight],axis=0)
out=K.gather(self.embeddings,input)
。第一个是自解释的,而第二个则从
嵌入
表中选择相关的
输入

然而,在我正在开发的特定应用程序中,使用
嵌入层而不是修改层效果更好。也许是因为学习率太高了。在我做了更多的实验之后,我将对此进行汇报

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)

所以,你有50000个单词来自手套,1000个单词不存在于手套中,你想学习这1000个单词的嵌入。然后,将新嵌入件与手套嵌入件合并。对吧?对。这就是为什么我在
training_em
ceoncatenate
上尝试使用
trainiable=False
的原因,但运气不太好。您遇到了什么错误?哪一行?@Daniel,我甚至没有想到要堆叠,因为我不太确定如何堆叠。然而,我添加了一些更多的信息。因此,
Sequential
层的串联可能不是一种可行的方法,除非我可以将它们堆叠为简单的矩阵,这将解决索引问题。因此,你有50000个单词来自手套,1000个单词不存在于手套中,你想学习这1000个单词的嵌入。然后,将新嵌入件与手套嵌入件合并。对吧?对。这就是为什么我在
training_em
ceoncatenate
上尝试使用
trainiable=False
的原因,但运气不太好。您遇到了什么错误?哪一行?@Daniel,我甚至没有想到要堆叠,因为我不太确定如何堆叠。然而,我添加了一些更多的信息。因此,
Sequential
层的串联可能不是一种方法,除非我可以将它们堆叠为简单的矩阵,这将解决索引问题。我明白你的意思,但我真的希望前50000行得到修复。我认为解决方案在于使用后端,并创建一个自定义层。我可能错了+我明白你的意思,但我真的希望前50000行得到修复。我认为解决方案在于使用后端,并创建一个自定义层。我可能错了+1提供解决方案。