使用KerasRegressor预测训练数据结果极差,求技术解决方案
问题:KerasRegressor拟合训练数据时输出全为极小值,无法得到准确预测
我在一个非随机的模拟数据集上使用KerasRegressor,尝试直接预测训练数据本身,但输出结果完全不符合预期。以下是我的实现代码:
from keras.models import Sequential from keras.layers import Dense from keras.wrappers.scikit_learn import KerasRegressor import numpy as ny X = ny.array([[1,2], [3,4], [5,6], [7,8], [9,10]]) Y = ny.array([3, 4, 5, 6, 7]) N = 5 def brain(): #Create the brain br_model=Sequential() br_model.add(Dense(3, input_dim=2, kernel_initializer='normal',activation='relu')) br_model.add(Dense(2, kernel_initializer='normal',activation='relu')) br_model.add(Dense(1,kernel_initializer='normal')) #Compile the brain br_model.compile(loss='mean_squared_error',optimizer='adam') return br_model estimator = KerasRegressor(build_fn=brain, nb_epoch=1000000, batch_size=5,verbose=1) print "Done" estimator.fit(X,Y) prediction = estimator.predict(X) print Y print prediction
真实输出应为[3 4 5 6 7],但我的预测结果全是[0.001 0.001 0.001 0.001 0.001]。我试过调整多种网络配置,但问题依旧,请问该怎么调整才能得到准确的预测结果?
解决方案
我帮你梳理几个核心问题点,以及对应的调整方案:
1. 数据未归一化是核心问题
你的输入数据X范围是1-10,输出Y是3-7,但模型使用了relu激活函数,搭配默认的normal初始化(均值0,标准差0.05)。初始权重极小,导致relu直接把大量神经元输出压制到0,模型根本无法有效学习数据规律。
- 调整方法:对输入和输出做归一化处理,把数据缩放到模型更容易处理的范围(比如0-1):
from sklearn.preprocessing import MinMaxScaler import numpy as np # 修正代码里ny的笔误为np X = np.array([[1,2], [3,4], [5,6], [7,8], [9,10]]) Y = np.array([3, 4, 5, 6, 7]).reshape(-1, 1) # 转成二维数组适配缩放器 # 初始化缩放器 scaler_x = MinMaxScaler() X_scaled = scaler_x.fit_transform(X) scaler_y = MinMaxScaler() Y_scaled = scaler_y.fit_transform(Y) # 用缩放后的数据训练 estimator.fit(X_scaled, Y_scaled) # 预测后反缩放得到真实值 prediction_scaled = estimator.predict(X_scaled).reshape(-1, 1) prediction = scaler_y.inverse_transform(prediction_scaled).flatten()
2. 训练轮数严重超标
你设置了nb_epoch=1000000,这完全没必要。Adam优化器在训练后期会因为梯度趋近于0而停止更新,甚至可能出现数值不稳定的情况。
- 调整方法:把轮数降到合理范围(比如1000-5000),同时加入早停机制避免无效训练:
from keras.callbacks import EarlyStopping # 新版本Keras中nb_epoch已更名为epochs,建议使用新参数名 estimator = KerasRegressor( build_fn=brain, epochs=5000, batch_size=5, verbose=1, callbacks=[EarlyStopping(monitor='loss', patience=50, restore_best_weights=True)] )
早停会在损失连续不再下降时停止训练,并恢复到最优的权重状态。
3. 网络结构与初始化不匹配
你的数据集只有5个样本,两层隐藏层(3+2神经元)反而可能让模型难以收敛;同时normal初始化对relu激活函数不够友好,容易引发“死亡神经元”问题。
- 调整方向:
- 简化网络:比如只用一层隐藏层(甚至不用隐藏层,因为你的数据明显存在线性规律);
- 更换初始化方式:用
he_normal(专门针对relu的初始化策略):
def brain(): br_model=Sequential() br_model.add(Dense(3, input_dim=2, kernel_initializer='he_normal', activation='relu')) br_model.add(Dense(2, kernel_initializer='he_normal', activation='relu')) br_model.add(Dense(1, kernel_initializer='normal')) br_model.compile(loss='mean_squared_error', optimizer='adam') return br_model
4. 学习率可能过低
Adam默认学习率0.001对于未归一化的数据来说太小,导致权重更新缓慢,无法移动到有效拟合区域。可以尝试调大学习率:
from keras.optimizers import Adam def brain(): br_model=Sequential() br_model.add(Dense(3, input_dim=2, kernel_initializer='he_normal', activation='relu')) br_model.add(Dense(2, kernel_initializer='he_normal', activation='relu')) br_model.add(Dense(1, kernel_initializer='normal')) # 调整学习率为0.01 opt = Adam(learning_rate=0.01) br_model.compile(loss='mean_squared_error', optimizer=opt) return br_model
5. 批量大小可灵活调整
你的数据集只有5个样本,batch_size=5意味着每次训练用全量数据。可以尝试改成1或2,让优化器有更多更新步骤,可能更容易收敛。
内容的提问来源于stack exchange,提问作者Thanatos
相关产品推荐
相关产品推荐

