python - 如果 Keras 结果不可重复,比较模型和选择超参数的最佳实践是什么?

标签 python tensorflow keras reproducible-research

更新:这个问题是针对 Tensorflow 1.x 的。我升级到 2.0 并且(至少在下面的简单代码中)重现性问题似乎已在 2.0 上解决。这样就解决了我的问题;但我仍然很好奇 1.x 上针对此问题使用了哪些“最佳实践”。

在 keras/tensorflow 上训练完全相同的模型/参数/数据不会给出可重复的结果,并且每次训练模型时损失都显着不同。有很多关于此的 stackoverflow 问题(例如, How to get reproducible results in keras )但推荐的解决方法似乎对我或 StackOverflow 上的许多其他人不起作用。好的,就是这样。

但是考虑到 keras 在 tensorflow 上的不可重复性的限制——比较模型和选择超参数的最佳实践是什么?我正在测试不同的架构和激活,但由于每次的损失估计都不同,我永远不确定一个模型是否比另一个更好。是否有处理此问题的最佳做法?

我认为这个问题与我的代码没有任何关系,但以防万一它有帮助;这是一个示例程序:

import os
#stackoverflow says turning off the GPU helps reproducibility, but it doesn't help for me
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"] = ""
os.environ['PYTHONHASHSEED']=str(1)

import tensorflow as tf
import tensorflow.keras as keras
import tensorflow.keras.layers 
import random
import pandas as pd
import numpy as np

#StackOverflow says this is needed for reproducibility but it doesn't help for me
from tensorflow.keras import backend as K
config = tf.ConfigProto(intra_op_parallelism_threads=1,inter_op_parallelism_threads=1)
sess = tf.Session(graph=tf.get_default_graph(), config=config)
K.set_session(sess)

#make some random data
NUM_ROWS = 1000
NUM_FEATURES = 10
random_data = np.random.normal(size=(NUM_ROWS, NUM_FEATURES))
df = pd.DataFrame(data=random_data, columns=['x_' + str(ii) for ii in range(NUM_FEATURES)])
y = df.sum(axis=1) + np.random.normal(size=(NUM_ROWS))

def run(x, y):
    #StackOverflow says you have to set the seeds but it doesn't help for me
    tf.set_random_seed(1)
    np.random.seed(1)
    random.seed(1)
    os.environ['PYTHONHASHSEED']=str(1)

    model = keras.Sequential([
            keras.layers.Dense(40, input_dim=df.shape[1], activation='relu'),
            keras.layers.Dense(20, activation='relu'),
            keras.layers.Dense(10, activation='relu'),
            keras.layers.Dense(1, activation='linear')
        ])
    NUM_EPOCHS = 500
    model.compile(optimizer='adam', loss='mean_squared_error')
    model.fit(x, y, epochs=NUM_EPOCHS, verbose=0)
    predictions = model.predict(x).flatten()
    loss = model.evaluate(x,  y) #This prints out the loss by side-effect

#Each time we run it gives a wildly different loss. :-(
run(df, y)
run(df, y)
run(df, y)

鉴于不可重复性,我如何评估超参数和架构的变化是否有帮助?

最佳答案

这是偷偷摸摸的,但实际上,您的代码确实缺少一个提高可重复性的步骤:在每次运行之前重置 Keras 和 TensorFlow 图。如果没有这个,tf.set_random_seed()将无法正常工作 - 请参阅下面的正确方法。

在将毛巾扔到不可重复性之前,我会用尽所有选项;目前我只知道 one such instance ,这很可能是一个错误。尽管如此,即使您按照所有步骤进行操作,也可能会得到明显不同的结果 - 在这种情况下,请参阅“如果没有任何效果”,但每个步骤显然都不是很有效率,因此最好专注于实现可重复性:

最终改进 :

  • 使用 reset_seeds(K)下面
  • 提高数值精度:K.set_floatx('float64')
  • 套装PYTHONHASHSEED在 Python 内核启动之前 - 例如从终端
  • 升级到 TF 2,其中包括一些可重现性错误修复,但请注意 performance
  • 在单个线程上运行 CPU(非常慢)
  • 不要从 tf.python.keras 导入- 见 here
  • 确保所有进口都是一致的(即不要做 from keras.layers import ...from tensorflow.keras.optimizers import ... )
  • 使用卓越的 CPU - 例如,Google Colab,即使使用 GPU,对于数值不精确性也更加健壮 - 参见 this SO

  • 另见 related SO关于再现性

    如果没有任何效果 :
  • 重新运行 X 次 使用完全相同的超参数和种子,平均结果
  • K 折交叉验证 使用完全相同的超参数和种子,平均结果 - 更好的选择,但涉及更多工作


  • 正确的复位方法 :

    def reset_seeds(reset_graph_with_backend=None):
        if reset_graph_with_backend is not None:
            K = reset_graph_with_backend
            K.clear_session()
            tf.compat.v1.reset_default_graph()
            print("KERAS AND TENSORFLOW GRAPHS RESET")  # optional
    
        np.random.seed(1)
        random.seed(2)
        tf.compat.v1.set_random_seed(3)
        print("RANDOM SEEDS RESET")  # optional
    

    在单 CPU 线程上运行 TF :(仅用于 TF1 的代码)

    session_conf = tf.ConfigProto(
          intra_op_parallelism_threads=1,
          inter_op_parallelism_threads=1)
    sess = tf.Session(config=session_conf)
    

    关于python - 如果 Keras 结果不可重复,比较模型和选择超参数的最佳实践是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59075244/

    相关文章:

    tensorflow - 具有附加动态参数的 Keras 损失函数

    python - 如何测试 nginx 代理超时

    python - 如何在 MapReduce Python Streaming 中对多个字段进行排序?

    python - TensorFlow 使用数组索引将 Tensor 分配给 Tensor

    python - 如何使用 TensorBoard 可视化具有自定义模型子类的 keras 模型?

    python - 为什么我在 CNN 中得到尖峰图(损失 vs 历元)

    Python端口扫描我做对了吗?

    python - python 中缺失值的统计

    python - 无法使用pip在Ubuntu 20.04 LTS上安装Tensorflow 1.x

    python - 使用 keras 进行情感分析,包括中性推文