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
是平等的
我知道这个问题被很多人问过很多次,但我仍然没有任何可行的解决方案。
我有一个 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
是平等的