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

如何调整Keras Sequential CNN训练数据张量形状并正确喂入模型

解决图像张量与边界框数据匹配及输入形状问题

咱们来拆解你遇到的两个核心问题:模型输入格式不匹配,以及灰度图数组形状不兼容。下面一步步给你修复方案:

问题1:模型输入为列表而非统一numpy数组

你最初的代码里X_train是一个包含14000个独立数组的列表,而Keras的fit方法需要的是一个4维numpy数组(形状为(样本数, 高度, 宽度, 通道数))。直接传入列表会导致模型无法识别输入维度,报出数组数量不匹配的错误。

问题2:灰度图数组维度缺失

转灰度图后,图像数组是2维的(height, width),但你定义的X_train是4维的(14000, height, width, 1),所以赋值时会出现维度不匹配的报错,需要给每个灰度图数组增加一个通道维度。


完整修复后的代码

import pandas as pd
import numpy as np
from PIL import Image
from os import listdir
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Convolution2D, Dropout, MaxPooling2D, Flatten, Dense

# 读取CSV数据,确保图像名称和边界框对应
train_csv = pd.read_csv('datasets/training.csv')
test_csv = pd.read_csv('datasets/test.csv')

y_train = train_csv[['X1', 'Y1', 'X2', 'Y2']].values  # 直接用列名更清晰,避免索引出错
x_train_names = train_csv['Image name'].values

# 加载图像并处理为统一格式的numpy数组
path = "datasets/images/images/"
# 先获取第一张图像的尺寸,假设所有图像尺寸一致
sample_img = Image.open(path + x_train_names[0]).convert('L')
img_height, img_width = sample_img.size[1], sample_img.size[0]  # 注意:PIL的size返回(width, height),要调整顺序

# 初始化4维数组:(样本数, 高度, 宽度, 通道数),通道数为1(灰度图)
X_train = np.zeros((len(x_train_names), img_height, img_width, 1), dtype=np.float32)

for i in range(len(x_train_names)):
    img_name = x_train_names[i]
    # 读取并转为灰度图
    img = Image.open(path + str(img_name)).convert('L')
    # 将2维灰度图数组直接赋值到4维数组的通道维度
    X_train[i, :, :, 0] = np.asarray(img, dtype=np.float32)

# 图像数据归一化(非常重要,能大幅提升模型训练稳定性)
X_train /= 255.0

# 构建模型,注意输入形状要和X_train完全匹配
classifier = Sequential()
classifier.add(Convolution2D(64, (3, 3), input_shape=(img_height, img_width, 1), activation='relu'))
classifier.add(Dropout(0.2))
classifier.add(MaxPooling2D((4, 4)))
classifier.add(Convolution2D(32, (2, 2), activation='relu'))
classifier.add(MaxPooling2D((2, 2)))
classifier.add(Flatten())
classifier.add(Dense(16, activation='relu'))
classifier.add(Dropout(0.5))
classifier.add(Dense(4))  # 输出4个边界框坐标

# 关键修正:边界框回归是回归任务,不是分类,损失函数要用MSE
classifier.compile(optimizer='adam', loss='mse', metrics=['mae'])  # mae是平均绝对误差,更贴合回归任务评估

# 训练模型,此时X_train是正确的4维numpy数组,和y_train一一对应
classifier.fit(x=X_train, y=y_train, batch_size=32, epochs=25)

关键改动说明

  1. 输入数组格式统一:

    • 把X_train从列表改为预分配的4维numpy数组,确保所有样本的形状一致,完全符合Keras的输入要求。
    • 对图像数据做归一化(除以255),将像素值缩放到0-1区间,这是深度学习处理图像的标准操作,能避免梯度爆炸等问题。
  2. 灰度图维度修复:

    • 通过X_train[i, :, :, 0] = np.asarray(img)直接将2维灰度图数组赋值到4维数组的通道维度,完美解决形状不匹配的问题。
  3. 损失函数修正:

    • 你做的是边界框坐标的回归任务,不是二分类任务,所以不能用binary_crossentropy,换成均方误差mse才是正确的选择,评估指标用平均绝对误差mae也更贴合任务需求。
  4. 代码可读性优化:

    • 用CSV的列名直接提取数据,比索引更清晰,避免因列顺序变化导致的错误。
    • 明确PIL图像的尺寸顺序,确保数组的高度和宽度对应正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:26:12