You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keras与TensorFlow中CNN分类实验结果无法复现的咨询

CNN实验无法复现结果的问题排查与最新解决方案

你的代码里的明显问题

  • 重复多次初始化随机种子和TensorFlow会话,逻辑混乱,且部分设置顺序错误(比如导入库后才设置环境变量,效果大打折扣)
  • random.seed(seed)中的seed未定义,应该写成random.seed(random_seed),导致Python全局随机状态未被正确固定
  • 沿用TensorFlow 1.x的会话API(tf.compat.v1.Session),在TF 2.x环境下完全没必要,反而会干扰默认执行流程

适用于TensorFlow 2.x + Keras的最新复现手段

要完全复现结果,需从全局随机状态锁定、禁用TF非确定性操作、训练流程固定三个层面入手,以下是标准步骤:

1. 全局随机种子初始化(必须放在所有导入最开头)

环境变量和各模块的种子必须在导入任何ML库之前设置,否则部分库会提前生成随机数:

import os
import random
import numpy as np
import tensorflow as tf

# 固定全局随机种子
random_seed = 0
os.environ['PYTHONHASHSEED'] = str(random_seed)
random.seed(random_seed)
np.random.seed(random_seed)
tf.random.set_seed(random_seed)

2. 禁用TensorFlow的非确定性操作

TF 2.x中部分GPU操作(如卷积、池化)默认使用非确定性算法提升速度,必须强制关闭:

# 禁用非确定性操作
os.environ['TF_DETERMINISTIC_OPS'] = '1'
os.environ['TF_CUDNN_DETERMINISTIC'] = '1'

# TF 2.10+版本可额外开启全局确定性
tf.config.experimental.enable_op_determinism()

3. 训练流程中的额外固定项

  • 数据加载时,shuffle=True必须搭配固定的seed参数,比如tf.data.Dataset.shuffle(buffer_size=..., seed=random_seed)
  • 模型初始化时,所有带随机初始化的层(如Dense、Conv2D)可显式设置seed参数,确保权重初始化完全一致
  • 调用model.fit时,若开启shuffle,需固定random_state参数(TF 2.x会继承全局种子,但显式指定更稳妥)

修正后的完整示例代码

# 第一步:全局种子与环境变量设置(必须最开头)
import os
import random
import numpy as np
import tensorflow as tf

random_seed = 0
os.environ['PYTHONHASHSEED'] = str(random_seed)
os.environ['TF_DETERMINISTIC_OPS'] = '1'
os.environ['TF_CUDNN_DETERMINISTIC'] = '1'

random.seed(random_seed)
np.random.seed(random_seed)
tf.random.set_seed(random_seed)
tf.config.experimental.enable_op_determinism()

# 第二步:导入其他库和定义模型
from keras.layers import *
from keras.models import *
from keras.utils import *
from sklearn.utils import shuffle
import matplotlib.pyplot as plt

# 示例CNN模型(显式设置层的初始化种子)
def build_model(input_shape, num_classes):
    model = Sequential([
        Conv2D(32, (3,3), activation='relu', input_shape=input_shape, 
               kernel_initializer=tf.keras.initializers.GlorotUniform(seed=random_seed)),
        MaxPooling2D((2,2)),
        Conv2D(64, (3,3), activation='relu', 
               kernel_initializer=tf.keras.initializers.GlorotUniform(seed=random_seed)),
        MaxPooling2D((2,2)),
        Flatten(),
        Dense(64, activation='relu', 
              kernel_initializer=tf.keras.initializers.GlorotUniform(seed=random_seed)),
        Dense(num_classes, activation='softmax', 
              kernel_initializer=tf.keras.initializers.GlorotUniform(seed=random_seed))
    ])
    model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
    return model

# 第三步:数据加载与训练(固定shuffle种子)
# 假设你的数据是x_train, y_train
x_train, y_train = shuffle(x_train, y_train, random_state=random_seed)

model = build_model((28,28,1), 10)
history = model.fit(x_train, y_train, epochs=10, batch_size=32, shuffle=True, random_state=random_seed)

额外注意事项

  • 使用GPU时,确保CUDA/CUDNN版本支持确定性操作(建议CUDA 11.x+、CUDNN 8.x+)
  • 彻底弃用tf.compat.v1旧API,完全切换到TF 2.x原生Keras接口
  • 训练过程中若用到动态数据增强,需固定所有随机参数的种子

内容的提问来源于stack exchange,提问作者David98

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 17:24:17