我是否以正确的方式在注意力模型中使用 tf.math.reduce_sum?
Am I using tf.math.reduce_sum in the attention model in the right way?
我试图在一个简单的双向 lstm 模型中使用 here 描述的注意力模型。但是,添加注意力模型后,我得到了这个错误:
ValueError: Unknown initializer: GlorotUniform
首先,我的代码在某些部分使用 TensorFlow 而在其他部分使用 Keras 方面没有任何不兼容问题。我还尝试了 中提到的所有解决方案。但是,其中 none 对我有用。我必须提到,在添加注意力模型之前,我的代码没有任何问题。因此,我尝试删除网络结构中注意部分的每一行,看看是哪一行导致了这个问题:
inputs = tf.keras.layers.Input(shape=(n_timesteps, n_features))
units = 50
activations = tf.keras.layers.Bidirectional(tf.compat.v1.keras.layers.CuDNNLSTM(units,
return_sequences=True),
merge_mode='concat')(inputs)
print(np.shape(activations))
# Implementation of attention
x1 = tf.keras.layers.Dense(1, activation='tanh')(activations)
print(np.shape(x1))
x1= tf.keras.layers.Flatten()(x1)
print(np.shape(x1))
x1= tf.keras.layers.Activation('softmax')(x1)
print(np.shape(x1))
x1=tf.keras.layers.RepeatVector(units*2)(x1)
print(np.shape(x1))
x1 = tf.keras.layers.Permute([2,1])(x1)
print(np.shape(x1))
sent_representation = tf.keras.layers.Multiply()([activations, x1])
print(np.shape(sent_representation))
sent_representation = tf.keras.layers.Lambda(lambda xin:tf.keras.backend.sum(xin, axis=-2),
output_shape=(units*2,))(sent_representation)
# softmax for classification
x = tf.keras.layers.Dense(n_outputs, activation='softmax')(sent_representation)
model = tf.keras.models.Model(inputs=inputs, outputs=x)
我意识到是带有 lambda 函数 和 tf.keras.backend.sum 的行导致了错误。因此,经过一番搜索后,我决定用以下内容替换该行:
sent_representation = tf.math.reduce_sum(sent_representation, axis=-2)
现在,我的代码可以工作了。但是,我不太确定这种替换是否正确。我这样做对吗?
编辑:这是代码的下几行,问题是在我尝试加载最佳模型进行测试时引起的:
optimizer = tf.keras.optimizers.SGD(lr=0.001, decay=1e-6, momentum=0.9)
model.compile(loss=lossFunction, optimizer=optimizer, metrics=['accuracy'])
print(model.summary())
# early stopping
es = tf.keras.callbacks.EarlyStopping(monitor='val_loss', mode='min',
verbose=1, patience=20)
mc = tf.keras.callbacks.ModelCheckpoint('best_model.h5',
monitor='val_accuracy', mode='max', verbose=1,
save_best_only=True)
history = model.fit(trainX, trainy, validation_data=(valX, valy),
shuffle = True, epochs=epochs, verbose=0,
callbacks=[es, mc])
saved_model = tf.keras.models.load_model('best_model.h5',
custom_objects={"GlorotUniform": tf.keras.initializers.glorot_uniform()})
# evaluate the model
_, train_acc = saved_model.evaluate(trainX, trainy, verbose=0) # saved_model
_, val_acc = saved_model.evaluate(valX, valy, verbose=0) # saved_model
_, accuracy = saved_model.evaluate(testX, testy, verbose=0) # saved_model
print('Train: %.3f, Validation: %.3f, Test: %.3f' % (train_acc, val_acc, accuracy))
y_pred = saved_model.predict(testX, batch_size=64, verbose=1)
您是否发现我的代码中有任何问题可能是我在使用 Lambda 层时出现错误的原因?
您提供的代码对 tf.keras.backend.sum
和 tf.math.reduce_sum
没有问题
答案是您的替换不会改变您的网络或您正在寻找的东西。你可以自己测试一下,验证tf.keras.backend.sum
等于tf.math.reduce_sum
X = np.random.uniform(0,1, (32,100,10)).astype('float32')
(tf.keras.backend.sum(X, axis=-2) == tf.reduce_sum(X, axis=-2)).numpy().all() # TRUE
我还建议你用 Lambda 层包装操作
EDIT:tf.reduce_sum
或 tf.keras.backend.sum
的用法,包裹在 Lambda 层中,如果使用 TF 版本 >= 则不会引发错误2.2.
在模型构建中,您只需要使用层。如果你想使用一些 tensorflow 操作(比如 tf.reduce_sum
或 tf.keras.backend.sum
),你需要将它们包装在 keras Lambda 层中。没有这个模型仍然可以工作,但是使用 Lambda 是一个很好的做法,以避免将来出现问题
我试图在一个简单的双向 lstm 模型中使用 here 描述的注意力模型。但是,添加注意力模型后,我得到了这个错误:
ValueError: Unknown initializer: GlorotUniform
首先,我的代码在某些部分使用 TensorFlow 而在其他部分使用 Keras 方面没有任何不兼容问题。我还尝试了
inputs = tf.keras.layers.Input(shape=(n_timesteps, n_features))
units = 50
activations = tf.keras.layers.Bidirectional(tf.compat.v1.keras.layers.CuDNNLSTM(units,
return_sequences=True),
merge_mode='concat')(inputs)
print(np.shape(activations))
# Implementation of attention
x1 = tf.keras.layers.Dense(1, activation='tanh')(activations)
print(np.shape(x1))
x1= tf.keras.layers.Flatten()(x1)
print(np.shape(x1))
x1= tf.keras.layers.Activation('softmax')(x1)
print(np.shape(x1))
x1=tf.keras.layers.RepeatVector(units*2)(x1)
print(np.shape(x1))
x1 = tf.keras.layers.Permute([2,1])(x1)
print(np.shape(x1))
sent_representation = tf.keras.layers.Multiply()([activations, x1])
print(np.shape(sent_representation))
sent_representation = tf.keras.layers.Lambda(lambda xin:tf.keras.backend.sum(xin, axis=-2),
output_shape=(units*2,))(sent_representation)
# softmax for classification
x = tf.keras.layers.Dense(n_outputs, activation='softmax')(sent_representation)
model = tf.keras.models.Model(inputs=inputs, outputs=x)
我意识到是带有 lambda 函数 和 tf.keras.backend.sum 的行导致了错误。因此,经过一番搜索后,我决定用以下内容替换该行:
sent_representation = tf.math.reduce_sum(sent_representation, axis=-2)
现在,我的代码可以工作了。但是,我不太确定这种替换是否正确。我这样做对吗?
编辑:这是代码的下几行,问题是在我尝试加载最佳模型进行测试时引起的:
optimizer = tf.keras.optimizers.SGD(lr=0.001, decay=1e-6, momentum=0.9)
model.compile(loss=lossFunction, optimizer=optimizer, metrics=['accuracy'])
print(model.summary())
# early stopping
es = tf.keras.callbacks.EarlyStopping(monitor='val_loss', mode='min',
verbose=1, patience=20)
mc = tf.keras.callbacks.ModelCheckpoint('best_model.h5',
monitor='val_accuracy', mode='max', verbose=1,
save_best_only=True)
history = model.fit(trainX, trainy, validation_data=(valX, valy),
shuffle = True, epochs=epochs, verbose=0,
callbacks=[es, mc])
saved_model = tf.keras.models.load_model('best_model.h5',
custom_objects={"GlorotUniform": tf.keras.initializers.glorot_uniform()})
# evaluate the model
_, train_acc = saved_model.evaluate(trainX, trainy, verbose=0) # saved_model
_, val_acc = saved_model.evaluate(valX, valy, verbose=0) # saved_model
_, accuracy = saved_model.evaluate(testX, testy, verbose=0) # saved_model
print('Train: %.3f, Validation: %.3f, Test: %.3f' % (train_acc, val_acc, accuracy))
y_pred = saved_model.predict(testX, batch_size=64, verbose=1)
您是否发现我的代码中有任何问题可能是我在使用 Lambda 层时出现错误的原因?
您提供的代码对 tf.keras.backend.sum
和 tf.math.reduce_sum
答案是您的替换不会改变您的网络或您正在寻找的东西。你可以自己测试一下,验证tf.keras.backend.sum
等于tf.math.reduce_sum
X = np.random.uniform(0,1, (32,100,10)).astype('float32')
(tf.keras.backend.sum(X, axis=-2) == tf.reduce_sum(X, axis=-2)).numpy().all() # TRUE
我还建议你用 Lambda 层包装操作
EDIT:tf.reduce_sum
或 tf.keras.backend.sum
的用法,包裹在 Lambda 层中,如果使用 TF 版本 >= 则不会引发错误2.2.
在模型构建中,您只需要使用层。如果你想使用一些 tensorflow 操作(比如 tf.reduce_sum
或 tf.keras.backend.sum
),你需要将它们包装在 keras Lambda 层中。没有这个模型仍然可以工作,但是使用 Lambda 是一个很好的做法,以避免将来出现问题