种子:修复了具有激活函数的 TensorFlow 代码,不可重现

Seed Fixed TensorFlow code with activation function not reproducible

提问人:sunacho 提问时间:10/22/2023 最后编辑:sunacho 更新时间:10/22/2023 访问量:41

问:

我是一个完全的深度学习初学者,一个月前开始学习深度学习。在研究 LSTM 模型时,我正在尝试在修复随机种子后提高模型性能。但是,我意识到即使我修复了随机种子(我自己在互联网上尝试了很多方法和 stackoverflow),当我重新启动运行时时,我也无法重现相同的结果。我使用的是 Google Colab CPU 和 Tensorflow 2.13.0 版。然后我意识到,只有当激活函数添加到LSTM模型中时,结果才会重现。

我制作了这段代码来修复随机种子,并将其用于我的 LSTM 模型。(我已经尝试了各种方法来修复随机种子,如果有奇怪的代码组合,请提前道歉)当我在 Google Colab 上重新启动 Runtime 时,此代码不会重现相同的结果。

import os
os.environ["PYTHONHASHSEED"] = '0'
os.environ['TF_DETERMINISTIC_OPS'] = '1'
os.environ['TF_CUDNN_DETERMINISTIC'] = '1'
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"] = ""

import numpy as np
import random as rn
import tensorflow as tf
import tensorflow.keras as keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout, Activation
from tensorflow.keras.callbacks import EarlyStopping
from tensorflow.keras.optimizers import Adam


def seed_everything(seed=42):
    np.random.seed(seed)
    tf.random.set_seed(seed)
    rn.seed(seed)
    tf.keras.utils.set_random_seed(seed)

    tf.config.experimental.enable_op_determinism()
    config = tf.compat.v1.ConfigProto(
        intra_op_parallelism_threads=1,
        inter_op_parallelism_threads=1
    )
    session = tf.compat.v1.Session(config=config)
    tf.compat.v1.keras.backend.set_session(session)


def create_lstm_model():
    seed_everything()

    model = tf.keras.Sequential([
        tf.keras.layers.LSTM(63, input_shape=(3, 1),
                            kernel_initializer='glorot_uniform', recurrent_initializer='glorot_uniform',
                             dropout=0.11, activation='relu', return_sequences=True),
        tf.keras.layers.LSTM(63, input_shape=(3, 1), kernel_initializer='glorot_uniform', recurrent_initializer='glorot_uniform',
                             dropout=0.11,  activation='relu'),
        tf.keras.layers.Dense(1, kernel_initializer='glorot_uniform')
    ])

    return model


seed_everything()

input_data = np.random.rand(100, 3, 1)
target_data = np.random.rand(100, 1)

for i in range(4):
    print(f"Case {i + 1}:")

    model = create_lstm_model()

    indices = np.arange(len(input_data))
    np.random.shuffle(indices)
    input_data_shuffled = input_data[indices]
    target_data_shuffled = target_data[indices]

    optimizer = tf.keras.optimizers.Adam(learning_rate=0.002)
    model.compile(optimizer=optimizer, loss='mse')

    early_stopping = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True)

    model.fit(input_data_shuffled, target_data_shuffled, epochs=100, batch_size=32, verbose=0, validation_split=0.2, callbacks=[early_stopping])

    loss = model.evaluate(input_data, target_data, verbose=0)
    print(f"Loss: {loss}")

另一方面,如果如下所示从模型中删除激活函数,则每次重新启动运行时都会重现相同的结果。不使用激活函数来创建可重现的 LSTM 模型似乎是不合理的。有没有办法使用我的模型重现结果?谢谢。

def create_lstm_model():
    seed_everything()

    model = tf.keras.Sequential([
        tf.keras.layers.LSTM(63, input_shape=(3, 1),
                            kernel_initializer='glorot_uniform', recurrent_initializer='glorot_uniform',
                             dropout=0.11, return_sequences=True),
        tf.keras.layers.LSTM(63, input_shape=(3, 1), kernel_initializer='glorot_uniform', recurrent_initializer='glorot_uniform',
                             dropout=0.11),
        tf.keras.layers.Dense(1, kernel_initializer='glorot_uniform')
    ])

    return model

(+)我从@Nicolas的评论中尝试了这种方法,它很好地再现了结果,但是模型的预测性能发生了显着变化,所以我想知道我编写的代码是否正确。

seed_everything()

model = tf.keras.Sequential([
    tf.keras.layers.LSTM(63, input_shape=(3, 1),
                        kernel_initializer='glorot_uniform', recurrent_initializer='glorot_uniform',
                         dropout=0.11, return_sequences=True),
    tf.keras.layers.ReLU(),
    tf.keras.layers.LSTM(63, input_shape=(3, 1), kernel_initializer=GlorotUniform(seed=42), recurrent_initializer=GlorotUniform(seed=42),
                         dropout=0.11),
    tf.keras.layers.ReLU(),
    tf.keras.layers.Dense(1, kernel_initializer=GlorotUniform(seed=42))
])

return model
python tensorflow keras lstm 随机种子

评论

0赞 Nicolas Gervais 10/22/2023
如果这是真的,这似乎是您应该向 Tensorflow 报告的错误。如果不在 LSTM 层中使用激活函数,而是在 LSTM 层之间这样添加它,它是否有效? ?tf.keras.layers.ReLU()
0赞 sunacho 10/22/2023
您好@Nicolas,感谢您的友好评论。当在 LSTM 层之间添加激活函数时,结果似乎被重现。但是预测性能发生了重大变化,所以我想知道我写的代码是否正确。我修改了文本。

答: 暂无答案