Keras Tensorflow 完全重置

Keras Tensoflow full reset

我知道这个问题被很多人问过很多次,但我仍然没有任何可行的解决方案。

我有一个 Python 代码可以创建一个模型,拟合它然后预测一些东西。由于我有很多功能可以用来训练模型,因此我创建了一个包含我的功能的所有组合的列表,例如 10 个中的 2 个、10 个中的 4 个等。现在我想循环调用我的代码。

The loop looks like:

for each combination in all combinations:
    model = Sequential()
    ... add some layers...
    model.compile(...)
    model.fit()
    ...
    model.predict()

而且我看到每次我 运行 它在同一组特征上我都会得到不同的结果。当然,我已经禁用了所有随机性,所以这不是问题。如果我只是从命令行 运行 我的代码(没有循环 - 即 python 在 运行 之间完全退出)我得到一个完全重复的结果。

所以我的假设是 Keras or/and Tensorflow 不会在循环之间完全重置。

我已经尝试了很多事情,比如在我希望我的模型被丢弃之后添加以下几行:

model.reset_states()
del model
gc.collect()
tf.keras.backend.set_learning_phase(1)
keras.backend.clear_session()
K.clear_session()
tf.compat.v1.reset_default_graph()
from tensorflow.python.framework import ops
ops.reset_default_graph()

没有任何效果 - 循环之间的结果不一致。正确工作的唯一方法是 运行 我的文件来自批处理文件,其中有很多行允许 python 在下次 运行 之前退出。

有什么处理方法的建议吗?我正在 Windows 使用 TS 2.4.1 和最新的 keras。

谢谢

我正在使用此代码来防止随机性:

def reset_random_seeds():
    os.environ['PYTHONHASHSEED'] = str(1)
    tf.random.set_seed(1)
    np.random.seed(1)
    random.seed(1)

TL;DR:您需要通过调用 tf.random.set_seed.

在创建模型的循环中重置随机生成器状态

解释:

神经网络由一系列数学运算组成。神经网络中最常见的操作可以看作是以下线性方程:y=W*x+b,其中:

  • x是输入
  • y 是输出
  • W是网络节点的权重
  • b是网络节点的偏差。

(所有这些线性方程然后被非线性分开以避免网络崩溃)。

大多数时候,神经网络的权重 (W) 是随机初始化的。这意味着每次 运行 训练神经网络时,您都会得到略有不同的结果。如果您的模型足够稳健,那么这些结果将在统计上相似。

现在,如果想要重现一些准确的结果,那么权重的随机初始化可能是个问题。为了能够重现一些精确的数字,可以为随机生成器设置一个种子,这样可以保证在程序执行期间,生成的随机数将始终来自同一系列,以相同的顺序。

运行 终端中两次相同的程序

考虑以下名为 network_with_seed.py 的程序:

import tensorflow as tf
tf.random.set_seed(0)
model = tf.keras.Sequential([tf.keras.layers.Dense(1,input_shape=(1,))])
print(model.trainable_weights)

该程序是一个简单的网络,具有一个带节点(也称为感知器)的全连接层。该网络作为一个权重 W,程序将打印该网络。

如果我们第一次执行该程序,我们得到:

$ python network_with_seed.py
[<tf.Variable 'dense/kernel:0' shape=(1, 1) dtype=float32, numpy=array([[-0.7206192]], dtype=float32)>, <tf.Variable 'dense/bias:0' shape=(1,) dtype=float32, numpy=array([0.], dtype=float32)>]

现在,如果我们再次执行该代码:

python network_with_seed.py
[<tf.Variable 'dense/kernel:0' shape=(1, 1) dtype=float32, numpy=array([[-0.7206192]], dtype=float32)>, <tf.Variable 'dense/bias:0' shape=(1,) dtype=float32, numpy=array([0.], dtype=float32)>] 

由于种子,我们得到了完全相同的权重值 W-0.7206192

循环创建模型

现在,假设我们想要两次创建该网络并获得一些数字,但我们想在一个 python 脚本中完成所有事情。

考虑那个程序,loop_network_with_seed.py:

import tensorflow as tf
tf.random.set_seed(0)
for idx in range(2):
  print(f"Model {idx+1}")
  model = tf.keras.Sequential([tf.keras.layers.Dense(1,input_shape=(1,))])
  print(model.trainable_weights)

如果我们运行它

$ python loop_network_with_seed.py
Model 1
[<tf.Variable 'dense/kernel:0' shape=(1, 1) dtype=float32, numpy=array([[-0.7206192]], dtype=float32)>, <tf.Variable 'dense/bias:0' shape=(1,) dtype=float32, numpy=array([0.], dtype=float32)>]
Model 2
[<tf.Variable 'dense_1/kernel:0' shape=(1, 1) dtype=float32, numpy=array([[0.19195998]], dtype=float32)>, <tf.Variable 'dense_1/bias:0' shape=(1,) dtype=float32, numpy=array([0.], dtype=float32)>]

如果我们只看随机初始化的内核 W,我们会看到,对于同一模型,不同的值:-0.7206192, 0.19195998,并且与我们两次执行同​​一模型时的值不同连续调用我们的脚本 network_with_seed.py。如果我们训练这两个网络,我们不会得到完全相同的结果,因为它们的初始权重 W 不同。

请注意,如果您再次 运行 该程序,您将得到完全相同的结果,因为模型 1 的权重将再次设置为 -0.7206192,而权重 [由于种子,模型 2 的 =21=] 将设置为 0.19195998。种子使每个 运行.

之间的随机性可重现

这是因为随机数生成器的内部状态。欲了解更多信息,您可以阅读 documentation of tf.random.set_seed

重置随机生成器状态

如果您想要同一组参数的可重现结果,您需要在创建每个模型之前重置随机状态。通过设置种子,我们确保相同的随机值将用于我们的权重 W.

考虑最终方案network_with_seed_in_loop.py

import tensorflow as tf

for _ in range(2):
  print(f"Model {idx+1}")
  tf.random.set_seed(0)
  model = tf.keras.Sequential([tf.keras.layers.Dense(1,input_shape=(1,))])
  print(model.trainable_weights)

输出:

$ python network_with_seed_in_loop.py`
Model 1
[<tf.Variable 'dense/kernel:0' shape=(1, 1) dtype=float32, numpy=array([[-0.7206192]], dtype=float32)>, <tf.Variable 'dense/bias:0' shape=(1,) dtype=float32, numpy=array([0.], dtype=float32)>]
Model 2
[<tf.Variable 'dense_1/kernel:0' shape=(1, 1) dtype=float32, numpy=array([[-0.7206192]], dtype=float32)>, <tf.Variable 'dense_1/bias:0' shape=(1,) dtype=float32, numpy=array([0.], dtype=float32)>]

这里重置了内部状态,每个网络的内核W是平等的