ELMo 嵌入层与 Keras
ELMo Embedding layer with Keras
我一直在我的架构中使用 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)
我想用 ELMo 嵌入替换嵌入层。所以我使用了一个自定义嵌入层——在这个 repo 中找到——https://github.com/strongio/keras-elmo/blob/master/Elmo%20Keras.ipynb。嵌入层看起来像这样 -
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 嵌入层为每个输入输出一个嵌入(因此输出形状为 (batch_size, dim)
),而您的 LSTM 需要一个序列(即形状 (batch_size, seq_length, dim)
)。我认为在 Elmo 嵌入层之后有一个 LSTM 层没有多大意义,因为 Elmo 已经使用 LSTM 来嵌入一系列单词。
我还使用该存储库作为构建 CustomELMo + BiLSTM + CRF 模型的指南,我需要将字典查找更改为 'elmo' 而不是 'default'。正如 Anna Krogager 指出的那样,当字典查找为 'default' 时,输出为 (batch_size, dim),这对于 LSTM 来说维度不够。然而,当 dict 查找是 ['elmo'] 层 returns 一个正确维度的张量,即形状 (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
我希望我的代码对您有用,即使它不是完全相同的模型。请注意,我必须注释掉 compute_mask 方法,因为它抛出
InvalidArgumentError: Incompatible shapes: [32,47] vs. [32,0] [[{{node loss/crf_1_loss/mul_6}}]]
其中 32 是批量大小,47 比我指定的 max_length 少一个(可能意味着它本身就是一个 pad 令牌)。我还没有找出导致该错误的原因,所以这对您和您的模型来说可能没问题。但是我注意到您正在使用 GRU,并且存储库中有一个关于添加 GRU 的未解决问题。所以我很好奇你是否也遇到了这个问题。
我一直在我的架构中使用 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)
我想用 ELMo 嵌入替换嵌入层。所以我使用了一个自定义嵌入层——在这个 repo 中找到——https://github.com/strongio/keras-elmo/blob/master/Elmo%20Keras.ipynb。嵌入层看起来像这样 -
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 嵌入层为每个输入输出一个嵌入(因此输出形状为 (batch_size, dim)
),而您的 LSTM 需要一个序列(即形状 (batch_size, seq_length, dim)
)。我认为在 Elmo 嵌入层之后有一个 LSTM 层没有多大意义,因为 Elmo 已经使用 LSTM 来嵌入一系列单词。
我还使用该存储库作为构建 CustomELMo + BiLSTM + CRF 模型的指南,我需要将字典查找更改为 'elmo' 而不是 'default'。正如 Anna Krogager 指出的那样,当字典查找为 'default' 时,输出为 (batch_size, dim),这对于 LSTM 来说维度不够。然而,当 dict 查找是 ['elmo'] 层 returns 一个正确维度的张量,即形状 (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
我希望我的代码对您有用,即使它不是完全相同的模型。请注意,我必须注释掉 compute_mask 方法,因为它抛出
InvalidArgumentError: Incompatible shapes: [32,47] vs. [32,0] [[{{node loss/crf_1_loss/mul_6}}]]
其中 32 是批量大小,47 比我指定的 max_length 少一个(可能意味着它本身就是一个 pad 令牌)。我还没有找出导致该错误的原因,所以这对您和您的模型来说可能没问题。但是我注意到您正在使用 GRU,并且存储库中有一个关于添加 GRU 的未解决问题。所以我很好奇你是否也遇到了这个问题。