当前位置: 首页 > 面试题库 >

如果Keras结果无法再现,那么比较模型和选择超参数的最佳实践是什么?

彭建业
2023-03-14
问题内容

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

在keras /tensorflow上训练完全相同的模型/参数/数据不会产生可重复的结果,并且每次训练模型时,损失都会大不相同。关于此问题,有很多问题,但是建议的解决方法似乎对我或上的许多其他人员不起作用。好,就是这样。

但是考虑到keras对张量流的不可重现性限制-
比较模型和选择超参数的最佳实践是什么?我正在测试不同的体系结构和激活,但是由于每次损失估计都不同,因此我不确定一个模型是否优于另一个模型。有什么最佳实践可以解决这个问题?

我认为该问题与我的代码无关,但以防万一。这是一个示例程序:

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)

考虑到不可重现性,我如何评估超参数和体系结构的更改是否有帮助?


问题答案:

该问题似乎在Tensorflow 2.0中得以解决(至少在简单模型上如此)!这是一个似乎可以产生可重复结果的代码段。

import os
####*IMPORANT*: Have to do this line *before* importing tensorflow
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

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

#make some random data
reset_random_seeds()
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):
    reset_random_seeds()

    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

#With Tensorflow 2.0 this is now reproducible! 
run(df, y)
run(df, y)
run(df, y)


 类似资料:
  • 问题内容: 我刚开始学习Go,并通读现有代码以学习“其他人的做法”。在这种情况下,遍历使用go“工作区”,尤其是与项目依赖关系有关的地方。 在处理各种Go项目时,使用一个或多个Go工作区(即$ GOPATH的定义)的常见(或存在)最佳实践是什么?我应该期望有一个类似于我所有项目的中央代码存储库的Go工作区,还是在我处理这些项目时都明确将其分解并设置$ GOPATH(有点像python) virtu

  • 问题内容: 在编写单元测试时,我经常遇到这样的情况,即测试中的某些对象的工作方式与实际环境中的工作方式不同。以一些接口为例。它具有和其他几个领域。逻辑上,一个配置等于s匹配时的另一个配置。但是,当谈到测试某些特定的实现时,例如,显然我想匹配 所有 字段。一种解决方案是不要在测试中使用,而只是遍历对象的属性或字段并进行比较,但这似乎不是一个好的解决方案。 因此,除了这种特定类型的情况外,我想从语义上

  • 问题内容: 我警告我。 然而,结构的嵌套是既定的编程技术,以及相当一些人在坚持它。 编辑:确实@vadian指出了Swift语言指南的规则: 要将类型嵌套在另一个类型中,请在其支持的类型的大括号内写入其定义。 类型可以嵌套到所需的多个级别 。 我知道它与泛型的使用发生冲突,并且Xcode可能会变得异常缓慢。实际上(通过测量最慢的编译点)是我开始研究此嵌套规则的原因。 实行皮棉规则的原因是什么?在这

  • 那么使用clientResponse()的最佳实践是什么?如果唯一的问题是应用程序不知道何时应该关闭连接,.exchange().block()会自动关闭连接吗?如果我应该使用.close()-我应该如何获得这个方法?也许我应该使用另一个版本的spring-webflux?或者也许还有另一种在Spring中检索响应主体和状态的最佳方法--WebFlux?

  • 问题内容: 如果您还希望获得结果总数(在进行分页之前),那么在SQL Server 2000、2005、2008、2012中对结果进行分页的最佳方法(从性能角度而言)是什么? 问题答案: 获取结果总数和分页是两个不同的操作。为了这个示例,我们假设您要处理的查询是 在这种情况下,您可以使用以下方法确定结果总数: …这看似效率低下,但假设所有索引等均已正确设置,实际上却表现不错。 接下来,要以分页的方

  • 我需要从数据库中选择一百个参数,然后在d to返回它来创建一个excel文件。 我使用的是spring数据,我认为有两种解决方案: > 使用multiselect方法,然后在DTO中定义一个包含所有参数的构造函数(参数数大于100) 使用multiselect方法并将数组(Object[])映射到DTO= 请问你还有其他的想法吗? 谢谢。