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

使用Scikeras KerasRegressor构建CNN的输入维度错误解决

解决Scikeras KerasRegressor构建CNN回归模型的维度错误

第一个错误:输入维度不匹配(Expected min_ndim=4, found ndim=2)

你的输入X[i]初始形状是(600,99),属于2D张量(样本数,特征数),但Conv2D要求输入是4D张量(样本数,高度,宽度,通道数)。你在Input层指定了shape=(None,99,1),但实际输入未达到4维要求。

解决方法:

将输入扩展为4D张量,根据数据结构调整维度:

for i in range(len(X)):
    # 从(600,99) → (600, 1, 99, 1),对应(样本数, 高度, 宽度, 通道)
    X[i] = np.expand_dims(np.expand_dims(X[i], axis=1), axis=-1)
    X_test[i] = np.expand_dims(np.expand_dims(X_test[i], axis=1), axis=-1)

如果你的可变长度维度是宽度(比如每个样本宽度可变、高度固定为99),则调整Input层的shape为(99, None, 1),同时对应调整输入扩展方式。

第二个错误:MaxPooling2D导致负维度

当输入变成(?,99,1,4)时,默认的MaxPooling2D(pool_size=(2,2), padding="valid")会在宽度维度(大小为1)上尝试池化,计算后维度变为负数,引发报错。

解决方法(选其一即可):

  1. 调整池化窗口,仅在有效维度池化:
    将所有MaxPooling2D的pool_size设为(2,1),仅在高度维度(99)做池化:
    model.add(keras.layers.MaxPooling2D(pool_size=(2,1)))
    
  2. 设置padding为same,保持维度不变:
    给MaxPooling2D添加padding="same"参数,避免维度缩小为负:
    model.add(keras.layers.MaxPooling2D(padding="same"))
    
  3. 调换输入维度顺序:
    将输入调整为(?,1,99,1),让宽度维度为99、高度为1,池化(2,2)时高度维度用padding="same"保持为1,避免出错。

模型代码的其他问题修正

除维度问题外,你的模型还有几个关键错误需要修复:

  • 移除Conv2D和MaxPooling2D语句末尾的逗号(会导致添加元组而非层);
  • 删除Conv2D中的input_shape参数(Input层已指定,重复定义会冲突);
  • 回归任务需在模型末尾添加Flatten()和Dense(1)层,将卷积特征映射为单个回归值;

修正后的完整模型代码

from typing import Dict, Any
import numpy as np
import keras
from scikeras.wrappers import KerasRegressor
from sklearn.datasets import make_regression

class CNNRegressor(KerasRegressor):

    def __init__(
        self,
        optimizer="adam",
        optimizer__learning_rate=0.001,
        epochs=200,
        verbose=0,
        **kwargs,
    ):
        super().__init__(**kwargs)
        self.optimizer = optimizer
        self.epochs = epochs
        self.verbose = verbose

    def _keras_build_fn(self, compile_kwargs: Dict[str, Any]):
        model = keras.Sequential()
        # 输入形状对应(高度, 宽度, 通道),样本数自动添加
        model.add(keras.layers.Input(shape=(1, 99, 1)))
        model.add(keras.layers.Conv2D(activation='relu', filters=4, kernel_size=(3,3), padding='same'))
        model.add(keras.layers.MaxPooling2D(pool_size=(2,1)))  # 只在高度维度池化
        model.add(keras.layers.Conv2D(activation='relu', filters=4, kernel_size=(3,3), padding='same'))
        model.add(keras.layers.MaxPooling2D(pool_size=(2,1)))
        model.add(keras.layers.Conv2D(activation='relu', filters=4, kernel_size=(3,3), padding='same'))
        model.add(keras.layers.MaxPooling2D(pool_size=(2,1)))
        model.add(keras.layers.Conv2D(activation='relu', filters=4, kernel_size=(3,3), padding='same'))
        model.add(keras.layers.MaxPooling2D(pool_size=(2,1)))
        model.add(keras.layers.Conv2D(activation='relu', filters=4, kernel_size=(3,3), padding='same'))
        # 展平特征图,添加全连接层输出回归值
        model.add(keras.layers.Flatten())
        model.add(keras.layers.Dense(1))
        model.compile(loss="mse", optimizer=compile_kwargs["optimizer"])
        return model

# 示例数据生成(替换为你的真实数据)
X, y = make_regression(n_samples=5, n_features=99, random_state=42)
X = [x.reshape(600,99) for x in np.split(X,5)]  # 模拟你的X结构
y = [y_i.reshape(-1,1) for y_i in np.split(y,5)]
X_test, y_test = make_regression(n_samples=2, n_features=99, random_state=42)
X_test = [x.reshape(600,99) for x in np.split(X_test,2)]

# 扩展输入维度
for i in range(len(X)):
    X[i] = np.expand_dims(np.expand_dims(X[i], axis=1), axis=-1)
for i in range(len(X_test)):
    X_test[i] = np.expand_dims(np.expand_dims(X_test[i], axis=1), axis=-1)

# 训练与预测
reg = CNNRegressor(epochs=20, verbose=1)
for i in range(len(X)):
    result_cnn = reg.fit(X[i], y[i])
    print(result_cnn.model.summary())

for i in range(len(X_test)):
    pred_cnn = result_cnn.predict(X_test[i])
    print(pred_cnn)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 07:25:11