我是否以正确的方式在注意力模型中使用 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.sumtf.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 层包装操作

EDITtf.reduce_sumtf.keras.backend.sum 的用法,包裹在 Lambda 层中,如果使用 TF 版本 >= 则不会引发错误2.2.

在模型构建中,您只需要使用层。如果你想使用一些 tensorflow 操作(比如 tf.reduce_sumtf.keras.backend.sum),你需要将它们包装在 keras Lambda 层中。没有这个模型仍然可以工作,但是使用 Lambda 是一个很好的做法,以避免将来出现问题