KerasRegressor报__call__属性缺失:ANN回归模型调参问题
KerasRegressor结合GridSearchCV调参报错的解决方法
问题背景
构建数值预测用的ANN回归模型,使用GridSearchCV做超参数调优时触发错误:AttributeError: 'KerasRegressor' object has no attribute '__call__'。代码定义了含三层隐藏层的ANN,通过KerasRegressor封装后传入GridSearchCV,调用fit方法时出错。
原代码示例
def create_model(optimizer = 'rmsprop', units = 16, learning_rate = 0.001): ann = Sequential() # Initialising ANN ann.add(tf.keras.layers.Dense(units = units, activation = "relu")) # Adding First Hidden Layer ann.add(tf.keras.layers.Dense(units = units, activation = "relu")) # Adding Second Hidden Layer ann.add(tf.keras.layers.Dense(units = units, activation = "relu")) # Adding Third Hidden Layer ann.add(tf.keras.layers.Dense(units = 1)) # Adding Output Layer ann.compile(optimizer = optimizer, loss = 'mean_absolute_error') # Compiling ANN return ann ann = KerasRegressor(model = create_model, verbose = 0, learning_rate = 0.001, units = 16 ) optimizers = ['rmsprop', 'adam', 'SGD'] epoch_values = [10, 25, 50, 100, 150, 200] batches = [10, 20, 30, 40, 50, 100, 1000] units = [16, 32, 64, 128, 256] lr_values = [0.001, 0.01, 0.1, 0.2, 0.3] hyperparameters = dict(optimizer = optimizers, epochs = epoch_values, batch_size = batches, units = units, learning_rate = lr_values ) grid = GridSearchCV(estimator = ann, cv = 5, param_grid = hyperparameters) history = grid.fit(X_train, Y_train, batch_size = 32, validation_data = (X_test, Y_test), epochs = 100 ) # Fitting ANN
报错详情
... 92 elif (not isinstance(self.build_fn, types.FunctionType) and 93 not isinstance(self.build_fn, types.MethodType)): 94 legal_params_fns.append(self.build_fn.__call__) AttributeError: 'KerasRegressor' object has no attribute '__call__'
数据集维度
- X.shape -> (10, 2066)
- Y.shape -> (10, 4)
- X_train.shape -> (8, 2066)
- X_test.shape -> (2, 2066)
- Y_train.shape -> (8, 4)
- Y_test.shape -> (2, 4)
报错原因与修复方案
核心错误原因
KerasRegressor的参数传递错误:原代码用了model=create_model,但scikit-learn封装Keras模型的正确参数名是build_fn=create_model,旧版Keras wrapper通过该参数指定模型构建函数,传错参数导致内部识别异常。
另外还有两个隐性问题:
- 模型输出层维度不匹配:Y数据是4维输出,但原代码输出层定义为
Dense(units=1),后续训练会触发维度不匹配错误。 - GridSearchCV的fit方法重复传入
batch_size和epochs,这些参数应该交给GridSearchCV通过param_grid遍历调优,重复传入会导致逻辑冲突。
修复后的完整代码
from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense from tensorflow.keras.wrappers.scikit_learn import KerasRegressor from sklearn.model_selection import GridSearchCV import tensorflow as tf def create_model(optimizer='rmsprop', units=16, learning_rate=0.001): ann = Sequential() # 三层隐藏层 ann.add(Dense(units=units, activation="relu")) ann.add(Dense(units=units, activation="relu")) ann.add(Dense(units=units, activation="relu")) # 输出层改为4维,匹配Y数据的维度 ann.add(Dense(units=4)) # 实例化带学习率的优化器,避免字符串传参无法生效 if optimizer == 'SGD': optimizer = tf.keras.optimizers.SGD(learning_rate=learning_rate) elif optimizer == 'adam': optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate) elif optimizer == 'rmsprop': optimizer = tf.keras.optimizers.RMSprop(learning_rate=learning_rate) ann.compile(optimizer=optimizer, loss='mean_absolute_error') return ann # 正确初始化KerasRegressor:使用build_fn参数指定模型构建函数 ann = KerasRegressor(build_fn=create_model, verbose=0) # 超参数网格(可根据需求调整规模) optimizers = ['rmsprop', 'adam', 'SGD'] epoch_values = [10, 25, 50] batches = [10, 20, 30] units = [16, 32, 64] lr_values = [0.001, 0.01] hyperparameters = dict( optimizer=optimizers, epochs=epoch_values, batch_size=batches, units=units, learning_rate=lr_values ) grid = GridSearchCV(estimator=ann, cv=5, param_grid=hyperparameters) # GridSearchCV的fit无需传入batch_size和epochs,由param_grid控制调优 history = grid.fit(X_train, Y_train, validation_data=(X_test, Y_test))
关键修复点说明
- KerasRegressor参数修正:将
model=create_model改为build_fn=create_model,符合scikit-learn封装Keras模型的参数规范。 - 输出层维度匹配:把输出层
Dense(units=1)改为Dense(units=4),与Y数据的4维输出对应。 - 优化器与学习率兼容:实例化优化器并传入learning_rate参数,避免直接传字符串导致学习率参数无法生效。
- 清理fit冗余参数:移除fit中的
batch_size和epochs,让GridSearchCV通过param_grid完成参数遍历。
内容的提问来源于stack exchange,提问作者leskovecg98
相关产品推荐
相关产品推荐

