首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于Keras的ELMo嵌入层

基于Keras的ELMo嵌入层
EN

Stack Overflow用户
提问于 2019-02-12 04:23:44
回答 2查看 6K关注 0票数 1

我一直在我的架构中使用Keras默认嵌入层和word嵌入。架构看起来像这样-

代码语言:javascript
复制
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)

我想用ELMo嵌入替换嵌入层。所以我使用了一个自定义的嵌入层-可以在这个repo - https://github.com/strongio/keras-elmo/blob/master/Elmo%20Keras.ipynb中找到。嵌入层看起来像这样-

代码语言:javascript
复制
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)

我更改了新嵌入层的架构。

代码语言:javascript
复制
 # 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

我在这里做错了什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-07-17 19:15:01

我还使用该存储库作为构建CustomELMo + BiLSTM + CRF模型的指南,我需要将字典查找更改为'elmo‘而不是'default’。正如Anna Krogager所指出的,当字典查找是“默认的”时,输出是(batch_size,dim),这对于LSTM来说是不够的。然而,当字典查找是'elmo‘时,该层返回正确维度的张量,即形状(batch_size,max_length,1024)。

自定义ELMo层:

代码语言:javascript
复制
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

该模型的构建方法如下:

代码语言:javascript
复制
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

我希望我的代码对您有用,即使它不是完全相同的模型。请注意,我必须在compute_mask方法抛出

代码语言:javascript
复制
InvalidArgumentError: Incompatible shapes: [32,47] vs. [32,0]    [[{{node loss/crf_1_loss/mul_6}}]]

其中32是批处理大小,47是比我指定的max_length小1的值(大概是指pad令牌本身)。我还没有找出那个错误的原因,所以对你和你的模型来说可能没问题。然而,我注意到你正在使用GRU,并且在存储库上有一个关于添加GRU的未解决的问题,所以我很好奇你是否也得到了GRU。

票数 2
EN

Stack Overflow用户

发布于 2019-02-12 15:21:26

Elmo嵌入层为每个输入输出一个嵌入(因此输出形状为(batch_size, dim)),而您的LSTM需要一个序列(即shape (batch_size, seq_length, dim))。我不认为在Elmo嵌入层之后使用LSTM层有多大意义,因为Elmo已经使用LSTM来嵌入单词序列。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54638544

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档