GridSearchCV多次运行结果不一致的随机性来源排查
你已经做了不少固定随机性的操作,但仍出现结果不一致,以下是几个可能的遗漏点:
1. 模型权重初始化未显式绑定随机种子
你在全局设置了TensorFlow和numpy的种子,但make_model函数中创建的Dense层没有显式指定初始化器的种子。虽然全局种子理论上会控制默认初始化器的随机行为,但Keras的部分初始化逻辑可能存在全局种子覆盖或未完全生效的情况,尤其是当代码中存在多次种子设置时(你代码里先后设置了seed=1和seed=7两次TensorFlow种子,可能导致种子状态混乱)。
2. random_state参数未实际作用于模型
你在param_grid中加入了random_state,但make_model函数只是接收了这个参数,并没有将其用于控制模型的随机性(比如初始化器的种子),相当于这个参数是无效的,没有起到固定随机性的作用。
3. 优化器的隐性随机性
部分优化器(比如Adam)的内部状态初始化可能存在隐性随机性,即使权重初始化固定,优化器的动量项、自适应学习率的初始计算可能受线程调度或底层TensorFlow操作的影响,尤其是当GridSearchCV启用多线程(n_jobs>1)时,线程执行顺序的差异会导致结果不一致。
4. 重复设置种子导致状态混乱
你的代码中先后两次设置了TensorFlow种子:
# 第一次 seed(1) tf.random.set_seed(seed) # 第二次 seed = 7 tf.random.set_seed(seed)
重复设置种子会打乱随机数生成器的状态,可能导致之前的种子设置失效,反而引入随机性。
解决步骤
统一种子设置,只在代码最开始执行一次:
import numpy as np import tensorflow as tf import random # 全局固定种子,放在所有代码最前面 SEED = 42 np.random.seed(SEED) tf.random.set_seed(SEED) random.seed(SEED)将
random_state参数实际用于模型初始化:
修改make_model函数,把random_state传给Dense层的初始化器:def make_model(optimizer="adam", hidden_size1=32, hidden_size2=32, hidden_size3=32, random_state=42): model = tf.keras.Sequential() # 显式设置初始化器的种子 init = tf.keras.initializers.GlorotUniform(seed=random_state) model.add(tf.keras.layers.Dense(hidden_size1, activation=activation, input_shape=(X_train.shape[1],), kernel_initializer=init)) model.add(tf.keras.layers.Dense(hidden_size2, activation=activation, kernel_initializer=init)) model.add(tf.keras.layers.Dense(hidden_size3, activation=activation, kernel_initializer=init)) model.add(tf.keras.layers.Dense(y_train.shape[1], activation='linear')) model.compile(loss='mse', optimizer=tf.keras.optimizers.Adam(learning_rate=learning_rate), metrics=['accuracy']) return model禁用GridSearchCV的多线程:
创建GridSearchCV实例时,设置n_jobs=1,避免多线程调度带来的随机性:grid = GridSearchCV(clf, param_grid=param_grid, cv=cv, return_train_score=True, n_jobs=1)确认数据无意外修改:
确保每次运行前X_train和y_train都是完全相同的数据集,没有在其他代码块中被打乱或修改。
内容的提问来源于stack exchange,提问作者hayo

