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

使用Keras计算ANN模型R²分数出现异常负值,求问题排查

问题描述

需要对比随机森林与Keras构建的ANN模型的R²(决定系数)以判断预测精度,随机森林的R²已正常获取,但ANN模型计算出的R²数值异常:训练集-3170.0261、测试集-1360.6658。数据集为石油生产相关数据,共2421行、13列,当前实现代码如下:

# Initialize the constructor
model = Sequential()

# Specifying input layer
model.add(Dense(2000, input_shape=(13,)))

# Add an first hidden layer 
model.add(Dense(1500, activation='relu'))
model.add(Dropout(0.2))

# second hidden layer
model.add(Dense(1000, activation='relu'))

# third hidden layer
model.add(Dense(500, activation='relu'))


# Add an output layer with one neuron and no activation specified
model.add(Dense(1))

from keras import backend as K

def r2_score(y_test, y_pred):
    SS_res =  K.sum(K.square( y_test-y_pred )) 
    SS_tot = K.sum(K.square( y_test - K.mean(y_test) ) ) 
    return ( 1 - SS_res/(SS_tot + K.epsilon()) )

model.compile(loss='mean_squared_error',
              optimizer='adam' , metrics = ['mae', 'mse', r2_score])
                   
epochs = 50

history = model.fit(X_train, y_train, epochs=epochs, batch_size=200, validation_split=0.3)

pred_train= model.predict(X_train)
print(K.get_value(r2_score(K.constant(y_train),pred_train)))

pred= model.predict(X_test)
print(K.get_value(r2_score(K.constant(y_test),pred)))
问题原因及解决办法

核心错误点

  1. 数据未做标准化/归一化
    ANN对输入数据的尺度极度敏感,石油生产数据的特征(如产量、压力等)和目标值可能存在量级差异,未做预处理会导致模型无法有效学习特征与目标的关联,预测结果偏差极大,最终R²为负。

  2. 模型结构过于臃肿
    输入仅13个特征,却设置了2000、1500、1000、500这样超大规模的隐藏层,不仅会引发严重过拟合,还可能导致梯度消失/爆炸,模型根本无法收敛到有效权重。

  3. R²计算的维度不匹配
    model.predict()返回的是二维数组(形状为(样本数,1)),而y_train/y_test大概率是一维数组,直接代入自定义的r2_score函数会导致平方和计算逻辑错误,结果失真。

  4. 训练参数不合理
    50轮epoch可能不足以让模型收敛,且batch_size设置为200(占训练集近1/10),会降低模型的学习效率,加上无数据预处理,模型无法学到有效模式。

修正方案

1. 数据标准化处理

使用StandardScaler对特征和目标值做标准化,消除尺度差异:

from sklearn.preprocessing import StandardScaler

# 标准化特征
scaler_X = StandardScaler()
X_train_scaled = scaler_X.fit_transform(X_train)
X_test_scaled = scaler_X.transform(X_test)

# 标准化目标值(若目标值量级大)
scaler_y = StandardScaler()
y_train_scaled = scaler_y.fit_transform(y_train.values.reshape(-1, 1))
y_test_scaled = scaler_y.transform(y_test.values.reshape(-1, 1))

2. 简化模型结构

根据输入特征数量调整隐藏层规模,匹配数据复杂度:

model = Sequential()
model.add(Dense(128, input_shape=(13,), activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(64, activation='relu'))
model.add(Dense(32, activation='relu'))
model.add(Dense(1))

3. 修正R²计算逻辑

直接使用sklearn的r2_score函数,避免Keras后端的维度问题,同时注意对预测结果做反变换:

from sklearn.metrics import r2_score

# 训练集预测与R²计算
pred_train_scaled = model.predict(X_train_scaled)
pred_train = scaler_y.inverse_transform(pred_train_scaled)
print("训练集R²:", r2_score(y_train, pred_train.flatten()))

# 测试集预测与R²计算
pred_test_scaled = model.predict(X_test_scaled)
pred_test = scaler_y.inverse_transform(pred_test_scaled)
print("测试集R²:", r2_score(y_test, pred_test.flatten()))

4. 调整训练参数

适当增加epoch数,缩小batch_size,提升模型收敛效果:

model.compile(loss='mean_squared_error', optimizer='adam', metrics=['mae', 'mse'])
history = model.fit(X_train_scaled, y_train_scaled, epochs=100, batch_size=64, validation_split=0.3)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 16:15:37