使用sklearn设置随机种子后神经网络结果仍不一致的技术求助
问题分析与解决方案
咱们一步步拆解你遇到的问题:设置随机种子后结果仍不一致,以及模型性能波动极大(R²在-0.1到0.6之间),这两个问题其实紧密相关,下面来逐一解决:
一、为什么np.random.seed没起作用?
你踩了Sklearn随机控制的一个常见坑:
Sklearn从0.21版本开始,默认使用自身独立的随机数生成器,不受全局np.random.seed的影响。也就是说,即使你设置了numpy的种子,MLPRegressor初始化权重、内部随机操作的随机性依然不受控制——必须显式给MLPRegressor设置random_state参数,才能固定它的随机行为。
另外,虽然你的train_test_split写在循环外,暂时不会影响当前结果,但如果后续调整代码把它放进循环,没设置random_state的话,每次划分的训练测试集都会不一样,结果自然也会波动。固定这个参数能让你的实验完全可复现。
二、模型性能波动大的核心原因:小数据集+过拟合
你的数据集只有241行、22列,属于典型的小样本场景:
- 测试集仅约48行数据,样本量太小,单次测试的结果本身就容易受随机因素干扰;
- 你用的
hidden_layer_sizes=(22,22,22)太复杂了——三层隐藏层,每层神经元数和特征数持平,参数总量远大于样本量,模型很容易过拟合训练数据,不同的权重初始化会导致模型在测试集上的表现天差地别。
三、具体解决步骤与修改后的代码
1. 固定所有随机源
把train_test_split和MLPRegressor的random_state都显式设置,确保每一次实验的随机性完全可控。
2. 简化模型+加入正则化
减少隐藏层/神经元数量,同时开启L2正则化(alpha参数)或早停(early_stopping=True),抑制过拟合。
3. 用交叉验证替代单次测试
小样本下,K折交叉验证能更稳定地评估模型性能,避免单次测试集的偶然性。
修改后的代码示例:
import matplotlib.pyplot as plt import pandas as pd import sklearn import numpy as np from sklearn.model_selection import train_test_split, cross_val_score from sklearn.preprocessing import StandardScaler from sklearn.neural_network import MLPRegressor from sklearn import metrics from math import sqrt # 加载数据 data = pd.read_csv(r"D:\PhD\1styear\machinelearning\NNforF2050\DATAnnF2050.csv") print(data.shape) print(data.dtypes) x = data.drop('EnergyConsumpManuf', axis=1) y = data['EnergyConsumpManuf'] # 固定训练测试集划分的随机种子 x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42) # 数据标准化 scaler = StandardScaler() scaler.fit(x_train) x_train = scaler.transform(x_train) x_test = scaler.transform(x_test) # 测试固定随机种子后的模型稳定性 fixed_seed = 42 np.random.seed(fixed_seed) # 简化模型结构+加入正则化+固定random_state mlp = MLPRegressor( hidden_layer_sizes=(10, 5), # 简化结构:两层隐藏层,减少神经元数量 max_iter=2000, learning_rate_init=0.001, random_state=fixed_seed, # 固定模型的随机状态 alpha=0.01, # L2正则化,抑制过拟合 early_stopping=True # 早停:当验证集性能不再提升时停止训练 ) mlp.fit(x_train, y_train) predictions = mlp.predict(x_test) print('固定种子后的结果:') print('MSE test: ', metrics.mean_squared_error(y_test, predictions)) print('RMS: ', sqrt(metrics.mean_squared_error(y_test, predictions))) print('R²: ', sklearn.metrics.r2_score(y_test, predictions)) print('MAE: ', metrics.mean_absolute_error(y_test, predictions)) # 用5折交叉验证评估模型稳定性 cv_scores = cross_val_score(mlp, scaler.transform(x), y, cv=5, scoring='r2') print('\n5折交叉验证的R²分数:', cv_scores) print('平均R²:', cv_scores.mean()) print('R²标准差:', cv_scores.std())
四、额外建议
- 如果条件允许,收集更多数据是解决小样本问题最根本的办法;
- 可以尝试调整
alpha的值(比如0.001、0.1),或者测试不同的隐藏层结构,找到最适配你数据集的模型; - 若需要对比不同种子下的模型表现,把
random_state设为循环变量i即可,但要确保其他随机源都固定不变。
内容的提问来源于stack exchange,提问作者milo204
相关产品推荐
相关产品推荐

