Python 含Keras的ELMo嵌入层

Python 含Keras的ELMo嵌入层,python,keras,deep-learning,lstm,word-embedding,Python,Keras,Deep Learning,Lstm,Word Embedding,在我的体系结构中,我一直使用Keras默认嵌入层和单词嵌入。建筑看起来像这样- left_input = Input(shape=(max_seq_length,), dtype='int32') right_input = Input(shape=(max_seq_length,), dtype='int32') embedding_layer = Embedding(len(embeddings), embedding_dim, weights=[embeddings], input_le

在我的体系结构中,我一直使用Keras默认嵌入层和单词嵌入。建筑看起来像这样-

left_input = Input(shape=(max_seq_length,), dtype='int32')
right_input = Input(shape=(max_seq_length,), dtype='int32')

embedding_layer = Embedding(len(embeddings), embedding_dim, weights=[embeddings], input_length=max_seq_length,
                            trainable=False)

# Since this is a siamese network, both sides share the same LSTM
shared_lstm = LSTM(n_hidden, name="lstm")

left_output = shared_lstm(encoded_left)
right_output = shared_lstm(encoded_right)
class ElmoEmbeddingLayer(Layer):
def __init__(self, **kwargs):
    self.dimensions = 1024
    self.trainable=True
    super(ElmoEmbeddingLayer, self).__init__(**kwargs)

def build(self, input_shape):
    self.elmo = hub.Module('https://tfhub.dev/google/elmo/2', trainable=self.trainable,
                           name="{}_module".format(self.name))

    self.trainable_weights += K.tf.trainable_variables(scope="^{}_module/.*".format(self.name))
    super(ElmoEmbeddingLayer, self).build(input_shape)

def call(self, x, mask=None):
    result = self.elmo(K.squeeze(K.cast(x, tf.string), axis=1),
                  as_dict=True,
                  signature='default',
                  )['default']
    return result

def compute_mask(self, inputs, mask=None):
    return K.not_equal(inputs, '--PAD--')

def compute_output_shape(self, input_shape):
    return (input_shape[0], self.dimensions)
我想用ELMo嵌入替换嵌入层。所以我使用了一个定制的嵌入层——可以在这个repo中找到。嵌入层如下所示-

left_input = Input(shape=(max_seq_length,), dtype='int32')
right_input = Input(shape=(max_seq_length,), dtype='int32')

embedding_layer = Embedding(len(embeddings), embedding_dim, weights=[embeddings], input_length=max_seq_length,
                            trainable=False)

# Since this is a siamese network, both sides share the same LSTM
shared_lstm = LSTM(n_hidden, name="lstm")

left_output = shared_lstm(encoded_left)
right_output = shared_lstm(encoded_right)
class ElmoEmbeddingLayer(Layer):
def __init__(self, **kwargs):
    self.dimensions = 1024
    self.trainable=True
    super(ElmoEmbeddingLayer, self).__init__(**kwargs)

def build(self, input_shape):
    self.elmo = hub.Module('https://tfhub.dev/google/elmo/2', trainable=self.trainable,
                           name="{}_module".format(self.name))

    self.trainable_weights += K.tf.trainable_variables(scope="^{}_module/.*".format(self.name))
    super(ElmoEmbeddingLayer, self).build(input_shape)

def call(self, x, mask=None):
    result = self.elmo(K.squeeze(K.cast(x, tf.string), axis=1),
                  as_dict=True,
                  signature='default',
                  )['default']
    return result

def compute_mask(self, inputs, mask=None):
    return K.not_equal(inputs, '--PAD--')

def compute_output_shape(self, input_shape):
    return (input_shape[0], self.dimensions)
我改变了新嵌入层的架构

 # The visible layer
left_input = Input(shape=(1,), dtype="string")
right_input = Input(shape=(1,), dtype="string")

embedding_layer = ElmoEmbeddingLayer()

# Embedded version of the inputs
encoded_left = embedding_layer(left_input)
encoded_right = embedding_layer(right_input)

# Since this is a siamese network, both sides share the same LSTM
shared_lstm = LSTM(n_hidden, name="lstm")

left_output = shared_gru(encoded_left)
right_output = shared_gru(encoded_right)
但我得到了一个错误-

ValueError:输入0与层lstm不兼容:预期ndim=3,发现ndim=2


我做错了什么

Elmo嵌入层为每个输入输出一个嵌入(因此输出形状为
(批量大小,dim)
),而LSTM需要一个序列(即形状
(批量大小,序列长度,dim)
)。我认为在Elmo嵌入层之后再加一个LSTM层没有多大意义,因为Elmo已经使用了一个LSTM来嵌入一个单词序列。

Elmo嵌入层每个输入输出一个嵌入(因此输出形状是
(batch\u size,dim)
),而您的LSTM需要一个序列(即形状
(批次大小、序列长度、尺寸)
)。我认为在Elmo嵌入层之后再添加一个LSTM层没有多大意义,因为Elmo已经使用了一个LSTM来嵌入一系列单词。

我还将该存储库用作构建CustomELMo+BiLSTM+CRF模型的指南,我需要将dict查找更改为“Elmo”,而不是“default”。正如Anna Krogager所指出的,当dict查找为“默认值”,输出为(批次大小,dim),这对于LSTM来说不够尺寸。但是,当dict查找为['elmo']时,层返回一个正确尺寸的张量,即形状张量(批次大小,最大长度,1024)

自定义ELMo层:

class ElmoEmbeddingLayer(Layer):
def __init__(self, **kwargs):
    self.dimensions = 1024
    self.trainable = True
    super(ElmoEmbeddingLayer, self).__init__(**kwargs)

def build(self, input_shape):
    self.elmo = hub.Module('https://tfhub.dev/google/elmo/2', trainable=self.trainable,
                           name="{}_module".format(self.name))

    self.trainable_weights += K.tf.trainable_variables(scope="^{}_module/.*".format(self.name))
    super(ElmoEmbeddingLayer, self).build(input_shape)

def call(self, x, mask=None):
    result = self.elmo(K.squeeze(K.cast(x, tf.string), axis=1),
                       as_dict=True,
                       signature='default',
                       )['elmo']
    print(result)
    return result

# def compute_mask(self, inputs, mask=None):
#   return K.not_equal(inputs, '__PAD__')

def compute_output_shape(self, input_shape):
    return input_shape[0], 48, self.dimensions
模型构建如下:

def build_model(): # uses crf from keras_contrib
    input = layers.Input(shape=(1,), dtype=tf.string)
    model = ElmoEmbeddingLayer(name='ElmoEmbeddingLayer')(input)
    model = Bidirectional(LSTM(units=512, return_sequences=True))(model)
    crf = CRF(num_tags)
    out = crf(model)
    model = Model(input, out)
    model.compile(optimizer="rmsprop", loss=crf_loss, metrics=[crf_accuracy, categorical_accuracy, mean_squared_error])
    model.summary()
    return model
我希望我的代码对您有用,即使它不是完全相同的模型

InvalidArgumentError: Incompatible shapes: [32,47] vs. [32,0]    [[{{node loss/crf_1_loss/mul_6}}]]

其中32是批量大小,47是比我指定的最大长度小一个(可能意味着它是对pad令牌本身的解释)。我还没有找出错误的原因,所以对您和您的模型来说可能没问题。但是,我注意到您正在使用GRU,并且在存储库中有一个关于添加GRU的未解决问题。因此我很好奇您是否也明白了这一点。

我还将该存储库用作构建CustomELMo+BiLSTM+CRF模型的指南,我需要d将dict查找更改为“elmo”而不是“default”。正如Anna Krogager指出的,当dict查找为“default”时,输出为(batch_size,dim),这对于LSTM来说不够尺寸。但是,当dict查找为['elmo']时,层返回一个正确尺寸的张量,即形状张量(batch_size,max_length,1024)

自定义ELMo层:

class ElmoEmbeddingLayer(Layer):
def __init__(self, **kwargs):
    self.dimensions = 1024
    self.trainable = True
    super(ElmoEmbeddingLayer, self).__init__(**kwargs)

def build(self, input_shape):
    self.elmo = hub.Module('https://tfhub.dev/google/elmo/2', trainable=self.trainable,
                           name="{}_module".format(self.name))

    self.trainable_weights += K.tf.trainable_variables(scope="^{}_module/.*".format(self.name))
    super(ElmoEmbeddingLayer, self).build(input_shape)

def call(self, x, mask=None):
    result = self.elmo(K.squeeze(K.cast(x, tf.string), axis=1),
                       as_dict=True,
                       signature='default',
                       )['elmo']
    print(result)
    return result

# def compute_mask(self, inputs, mask=None):
#   return K.not_equal(inputs, '__PAD__')

def compute_output_shape(self, input_shape):
    return input_shape[0], 48, self.dimensions
模型构建如下:

def build_model(): # uses crf from keras_contrib
    input = layers.Input(shape=(1,), dtype=tf.string)
    model = ElmoEmbeddingLayer(name='ElmoEmbeddingLayer')(input)
    model = Bidirectional(LSTM(units=512, return_sequences=True))(model)
    crf = CRF(num_tags)
    out = crf(model)
    model = Model(input, out)
    model.compile(optimizer="rmsprop", loss=crf_loss, metrics=[crf_accuracy, categorical_accuracy, mean_squared_error])
    model.summary()
    return model
我希望我的代码对您有用,即使它不是完全相同的模型

InvalidArgumentError: Incompatible shapes: [32,47] vs. [32,0]    [[{{node loss/crf_1_loss/mul_6}}]]

其中32是批量大小,47是比我指定的最大长度小一个(可能意味着它是对pad令牌本身的解释)。我还没有找出错误的原因,所以对您和您的模型来说可能没问题。但是我注意到您正在使用GRU,并且在存储库中有一个关于添加GRU的未解决问题。所以我很好奇您是否也得到了这个结果。

为了获得LSTM预期的序列,我应该在ELMo嵌入层中更改什么o您想通过LSTM层获得什么?您的输入只是一个字符串,而不是一个序列,因此我不明白LSTM层的目的是什么。但是,如果您想以某种方式将一系列字符串作为输入,那么您可以将ELMo层应用于序列的每个元素(通过将ELMo包装在时间分布层中)然后将生成的嵌入序列输入到LSTMYeah,实际上我的输入是一个句子为了得到LSTM期望的序列,我应该在ELMo嵌入层中修改什么?你想从LSTM层中得到什么?你的输入只是一个字符串,不是序列,所以我不明白LSTM层的目的是什么。But如果您以某种方式将字符串序列作为输入,那么您可以将ELMo层应用于序列的每个元素(通过将ELMo包装在时间分布层中)然后将生成的嵌入序列输入到lstmeyeah,实际上我的输入是一个句子你有没有发现k.tf.trainable_变量的错误?我得到了ame error@ElSheikh,你能找到一个解决方案吗?是的,这里是
self.\u trainable_weights+=tf.trainable_变量(scope=f“^{self.name}\u module/*”)
它对您有帮助吗?@Ivanlibedinsky感谢您的帮助,我正在处理tensorflow和trainable_变量,您能指定在运行此程序时使用的tensorflow和keras版本吗?k.tf.trainable_变量有任何错误吗?我收到ame错误@ElSheikh,您能找到解决方案吗?是的,给您
self.\u trainable\u weights+=tf.trainable\u variables(scope=f“^{self.name}\u module/*”
对您有帮助吗?@Ivanlibedinsky感谢您的帮助,我正在处理tensorflow和trainable\u变量,您能否指定在运行此操作时使用的tensforflow和keras版本?为什么输入大小是
(1,)
?这是怎么回事?
input=layers.input(shape=(1,),dtype=tf.string)
为什么输入大小是
(1,)
?这是怎么回事?
input=layers.input(shape=(1,),dtype=tf.string)