我无法使用 keras 神经网络获得可重现的结果

问题描述 投票:0回答:1

正如标题所说。我目前正在使用 python (3.11) 和 keras (2.12.0) 和 tensorflow (2.12.1,仅 cpu 包) 库,并且我面临着神经网络可重复性的一些问题;目前在 jupyter 笔记本中编码。由于我在一个环境中工作,因此我使用的库数量有限。这是场景:

  1. 我用 pandas 导入一些数据。
  2. 我在数据的子集上训练模型,使用其余数据进行测试。
  3. 每次重新启动内核并拟合模型时,我都会得到不同的结果。

现在,我想我已经正确地播种了。我阅读了 keras 文档、有关如何获得可重现结果的常见问题解答部分 (https://keras.io/getting_started/faq/),以及此处提出的类似问题 (How to get reproducible results in keras, 为什么即使我设置了随机种子,我也无法在 Keras 中获得可重现的结果?),但似乎没有任何效果。

我相信我做的一切都是正确的,特别是:

  1. 我设置了提到的各种种子;
  2. 我确保使用种子初始化权重相同;
  3. 我启用了_op_确定性,即使我没有使用CPU,并设置了PYTHONHASHSEED(我在程序中完成了它,所以这可能是问题所在,因为它说我必须事先这样做)。

每次重新启动内核时,都会发生以下情况:

  1. 我(正确)加载数据
  2. 在训练测试中分割(种子,所以每次都是一样的)
  3. 创建模型:我检查并确保初始权重相同,甚至偏差相同。
  4. 我拟合模型:重新启动内核后,拟合历史记录会略有变化。

最后一点是让我困惑的一点。当我不重新启动内核并运行模型定义+估计时,我每次都会得到完全相同的拟合历史记录(正如我所说,它是种子)。当我重新启动内核时,我再次运行所有内容,并且一切正常,直到最后一个列表的第 3 点,但随后拟合历史记录发生了变化。这是如何运作的?我以为是编译器的问题,我用的是ADAM,但我不知道?为什么这会导致问题?

我目前很困惑,我希望每次运行脚本时一切都一样,因为我正在进行模拟,并且我需要结果是可重现的。

import os  #Necessario per la riproducibilità
os.environ['PYTHONHASHSEED'] = '0'

import random    #Random seed
random.seed(5014)

import numpy as np
np.random.seed(5014)

#Pacchetti generici
import sys
import feather   #Per leggere i dataset
import time

#Reti neurali
import pandas as pd
import tensorflow as tf
tf.random.set_seed(5014)
#tf.compat.v1.set_random_seed(5014)

import keras
keras.utils.set_random_seed(5014) #This should set again all of the seeds above, I know, but I'm trying everything.

from sklearn.model_selection import train_test_split
import math
print(sys.version)
#This isn't enough to get the same results.
tf.config.experimental.enable_op_determinism()

from keras import backend as K
session_conf = tf.compat.v1.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)
sess = tf.compat.v1.Session(graph=tf.compat.v1.get_default_graph(), config=session_conf)
tf.compat.v1.keras.backend.set_session(sess)
#Loading the data
data = feather.read_dataframe("dataset1.feather")  #pd.DataFrame
data.shape

#This is to get the model
def create_model(size, n_input):
    #Per rendere la stima replicabile
    seeds= [1000,1001,1002,1003]
    print("\nSemi utilizzati per l'iniz: ")
    print(seeds)

    #Struttura del modello
    model = tf.keras.models.Sequential()
    model.add(tf.keras.layers.Dense(size[0], input_shape=(n_input,), activation ="relu", name="Hidden1", kernel_initializer=tf.keras.initializers.RandomNormal(seed = seeds[0])))
    model.add(tf.keras.layers.Dense(size[1], activation='relu', name="Hidden2", kernel_initializer=tf.keras.initializers.RandomNormal(seed = seeds[1])))
    model.add(tf.keras.layers.Dense(size[2], activation='relu', name="Hidden3", kernel_initializer=tf.keras.initializers.RandomNormal(seed = seeds[2])))
    model.add(tf.keras.layers.Dense(1, activation="linear", name="Output", kernel_initializer=tf.keras.initializers.RandomNormal(seed = seeds[3])))

    #Metodo di stima da utilizzare
    model.compile(loss='mean_squared_error', optimizer='Adam', metrics = ["mean_squared_error"])
    
    return model

这些是代码中使用的函数。

vars = set(data.columns)
escluse = {"output","Days"}
X = vars.difference(escluse)

#Le posizioni di Days e output
days_pos = data.shape[1]
out_pos = data.shape[1]-1

#Specifiche della rete neurale
reps = 3 #Numero di punti di partenza per ciascuna rete.
size = [200,200,200]

i = 365
    
print("\nCurrently: ",i)
data_to_use = data.loc[(data["Days"]<=i) & (data["Days"] >= (i-364))]

#Definire i dataset da usare per stima
train, val = train_test_split(data_to_use, test_size=0.2)
x_train = train[list(X)]
y_train = train["output"]
x_val = val[list(X)]
y_val = val["output"]

model_nn = create_model(size,data_to_use.shape[1] - 2)

直到上面几行,一切都按预期工作,每次重新启动内核时模型都是相同的。 但是,到了

的时候
storia = model_nn.fit(x = x_train, y = y_train, batch_size = math.ceil(x_train.shape[0]/2), epochs = 1000, validation_data=(x_val,y_val), verbose =0, 
                callbacks = tf.keras.callbacks.EarlyStopping(monitor ="val_mean_squared_error", min_delta =0, patience =8))

storia.history["val_mean_squared_error"][0:5]

历史改变了。为什么?如果我重复模型定义+拟合,我会得到相同的精确结果。如果我重新启动内核并再次运行所有内容,结果就会改变。有谁知道如何解决它?数据在这里:https://github.com/marco-pll/data-STACKoverflow

谢谢您的帮助。我快要哭了

编辑:事实上,它是 PYTHONHASHSEED。只需将其作为环境变量即可。将帖子留在这里,因为它可能对其他人有帮助。

python tensorflow keras jupyter-notebook
1个回答
0
投票

由于 @twallow 和 @mhenning 所说的原因以及其他原因,神经网络训练的可重复性有点误导。

搜索“统计神经网络基准”会发现一篇 IEEE 文章,该文章显示神经网络根据初始化和超参数在训练中产生一系列准确度。

也许记录神经网络产生的准确度范围是一种压力较小的方法?

© www.soinside.com 2019 - 2024. All rights reserved.