为何每次运行MLP模型得到的F1分数均存在较大差异?
问题根因
你仅在数据集拆分环节设置了随机种子,没有覆盖MLP训练流程的全部随机影响因素,因此每次运行的F1分数会出现大幅波动,具体遗漏点如下:
MLPClassifier实例未传入random_state参数:MLP的初始权重随机初始化、Adam优化器的批次采样、训练过程中的随机更新逻辑都依赖随机数生成器,未固定该参数时,每次运行的模型初始状态完全不同,收敛结果差异极大。- 未做特征标准化:MLP对特征尺度非常敏感,不同特征量纲差异过大会让损失曲面异常崎岖,模型极易收敛到差异极大的局部最优点,进一步放大结果波动。
- 未全局固定Python、Numpy的随机种子:部分底层计算逻辑的随机行为不会被数据集拆分、模型的单独种子覆盖,全局随机状态不固定也会带来结果偏差。
- 未设置足够的训练迭代次数:你当前代码使用
MLPClassifier默认的max_iter=200参数,很多场景下模型迭代200次还没收敛就终止训练,未收敛的模型结果稳定性极差。
修复后的可复现代码
import random import pandas as pd import numpy as np from sklearn.neural_network import MLPClassifier from sklearn import metrics from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler # 统一固定所有随机源的种子 seed = 42 random.seed(seed) np.random.seed(seed) # 加载数据集 df = pd.read_csv('/content/wesad-chest-combined-classification-eda.csv') # 移除非必要分类列 df = df.drop(['SSSQ class', 'condition'], axis='columns') # 删除缺失值行 df = df.dropna() # 拆分特征和标签 X = df.to_numpy() y = df['SSSQ Label'].values X = np.delete(X, 45, axis=1) # 拆分训练测试集 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.3, random_state=seed) # 特征标准化:仅在训练集上拟合缩放器,避免数据泄露 scaler = StandardScaler() X_train = scaler.fit_transform(X_train) X_test = scaler.transform(X_test) # 初始化MLP分类器,固定随机种子,增加最大迭代次数保证收敛 mlp_clf = MLPClassifier( hidden_layer_sizes=100, activation='relu', learning_rate_init=0.001, learning_rate='adaptive', momentum=0.9, solver='adam', random_state=seed, max_iter=1000 ) mlp_clf.fit(X_train, y_train) # 预测并计算指标 y_pred = mlp_clf.predict(X_test) print('RESULTS AFTER APPLYING MLP CLASSIFIER ON GIVEN DATA:') print(' Accuracy: ' + str(metrics.accuracy_score(y_test, y_pred))) print(' Recall: ' + str(metrics.recall_score(y_test, y_pred, average='weighted', labels=np.unique(y_pred)))) print(' Precision: ' + str(metrics.precision_score(y_test, y_pred, average='weighted', labels=np.unique(y_pred)))) print(' F1 Score: ' + str(metrics.f1_score(y_test, y_pred, average='weighted', labels=np.unique(y_pred)))) print('\nCROSS TAB RESULTS: [0 = Low, 1 = Medium, 2 = High]') print(pd.crosstab(y_test, y_pred, colnames=['Stress Levels'], rownames=[None]))
补充说明
- 特征标准化必须放在数据集拆分之后执行,禁止先对全量数据做缩放再拆分,否则会把测试集的统计信息泄露到训练流程中,导致指标结果虚高。
- 完成以上配置后,每次运行的F1分数差值应该稳定在1%以内,如果仍然出现大幅波动,需要检查数据集是否存在类别极度不平衡、标签错误、特征冗余度过高的问题。
- 如果出现极小幅度的结果差异,是底层线性代数库并行计算的浮点误差导致,属于正常现象。
内容的提问来源于stack exchange,提问作者hera
相关产品推荐
相关产品推荐

