基于和声搜索调参的CNN-LSTM模型报错:Unknown optimizer: binary_crossentropy
解决CNN-LSTM和声搜索调优中的
custom_objects错误 错误根源
你遇到的ValueError: Unknown optimizer: binary_crossentropy是因为模型编译时参数传递方式错误:在harmony_search函数里,直接把字典params传入model.compile(params),会让Keras错误地将字典整体当作optimizer参数,进而把字典里的loss值binary_crossentropy识别成了优化器名称,导致匹配失败。
关键修复步骤
修正compile调用方式
用Python字典解包语法**params传递参数,让Keras正确解析每个键值对:model.compile(**params)修复模型结构矛盾
你的CNN-LSTM结构存在维度不匹配问题:Conv1D输出是三维张量(batch_size, timesteps, filters),经过Flatten()后变成二维(batch_size, timesteps*filters),但Embedding层要求输入是整数序列(二维(batch_size, sequence_length)),这会导致后续LSTM层报错。建议调整结构,比如将Embedding移到Conv1D之前(如果输入是整数序列),或者移除Embedding层(如果输入是数值特征)。优化和声搜索逻辑
- 每次迭代重新构建模型,避免复用旧模型的权重累积影响调优结果;
- 初始化
best_params变量,防止未找到更优参数时出现未定义错误。
修正后的完整代码
import numpy as np import pandas as pd from sklearn.preprocessing import StandardScaler, MinMaxScaler from keras.layers import Input, LSTM, Dense, Conv1D, MaxPooling1D, Flatten from keras.models import Model from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error # 假设X_train、y_train、X_test、y_test已提前定义并预处理 # 示例:如果输入是数值特征,移除Embedding层,调整模型结构 def build_model(): inputs = Input(shape=(X_train.shape[1], X_train.shape[2])) x = Conv1D(filters=32, kernel_size=2, activation='relu')(inputs) x = MaxPooling1D(pool_size=1)(x) x = LSTM(units=128, dropout=0.2, recurrent_dropout=0.2)(x) outputs = Dense(1, activation='sigmoid')(x) return Model(inputs, outputs) # 初始模型训练(可选) model = build_model() model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) model.fit(X_train, y_train, epochs=10, batch_size=32) results = model.evaluate(X_test, y_test) print(results) # 修正后的和声搜索算法 def harmony_search(X_train, y_train, X_test, y_test, n_iterations=10): best_score = 0 best_params = {} for i in range(n_iterations): # 随机选择超参数 params = { 'optimizer': np.random.choice(['adam', 'rmsprop', 'sgd']), 'loss': 'binary_crossentropy', 'metrics': np.random.choice(['accuracy', 'mae']) } # 每次迭代重新构建模型 model = build_model() # 正确传递参数 model.compile(**params) model.fit(X_train, y_train, epochs=10, batch_size=32, verbose=0) score = model.evaluate(X_test, y_test, verbose=0)[1] if score > best_score: best_score = score best_params = params.copy() return best_params # 搜索最优超参数 best_params = harmony_search(X_train, y_train, X_test, y_test) print("最优超参数:", best_params)
额外说明
- 如果你的输入确实是需要Embedding处理的整数序列,应将Embedding层放在模型最前端,接收原始整数输入,再传入Conv1D和LSTM层;
verbose=0可以关闭训练过程的日志输出,让调优过程更简洁。
内容的提问来源于stack exchange,提问作者allmen
相关产品推荐
相关产品推荐

