CNN气球检测模型调用fit()报错:输入形状不兼容求助
气球检测CNN模型训练时的输入形状不兼容问题
训练模型调用fit()时触发错误:
ValueError: Input 0 of layer "sequential" is incompatible with the layer: expected shape=(None, 224, 224, 3), found shape=(None, None, None, 224, 224, 3)
尝试过小修改但未解决,寻求问题原因及修复方案。
原代码
import numpy as np import pandas as pd import tensorflow as tf import tensorflow_datasets as tfds tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR) model = tf.keras.Sequential([ tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(224, 224, 3)), tf.keras.layers.MaxPooling2D(2, 2), tf.keras.layers.Conv2D(64, (3, 3), activation='relu'), tf.keras.layers.MaxPooling2D(2, 2), tf.keras.layers.Conv2D(128, (3, 3), activation='relu'), tf.keras.layers.MaxPooling2D(2, 2), tf.keras.layers.Flatten(), tf.keras.layers.Dense(128, activation='relu'), tf.keras.layers.Dense(1, activation='sigmoid') ]) model.compile(loss='binary_crossentropy', optimizer=tf.keras.optimizers.Adam(learning_rate=0.001), metrics=['accuracy']) annotations_file = '/content/balloon-data.csv' annotations = pd.read_csv(annotations_file) image_paths = [] labels = [] for i, row in annotations.iterrows(): if row['num_balloons'] > 0: image_path = 'path/to/image/{}'.format(row['fname']) image_paths.append(image_path) labels.append(1) else: image_path = 'path/to/image/{}'.format(row['fname']) image_paths.append(image_path) labels.append(0) dataset = tf.data.Dataset.from_tensor_slices((image_paths, labels)) def preprocess_image(image_path, label): image = tf.io.read_file(image_path) image = tf.image.decode_jpeg(image, channels=3) image = tf.image.resize(image, (224, 224)) image = image / 255.0 return image, label dataset = dataset.map(lambda x, y: preprocess_image(x, y)).batch(64) train_size = int(0.8 * len(image_paths)) test_size = len(image_paths) - train_size train_dataset = dataset.take(train_size) test_dataset = dataset.skip(train_size) train_dataset = train_dataset.shuffle(1024).batch(32) test_dataset = test_dataset.batch(32) train_dataset = train_dataset.shuffle(1024).batch(64) test_dataset = test_dataset.batch(64) model.fit(train_dataset, epochs=10, validation_data=test_dataset)
已尝试的修改
# 原代码中这一行 dataset = dataset.map(lambda x, y: preprocess_image(x, y)).batch(64) # 修改为 dataset = dataset.map(preprocess_image) # 删除了以下重复batch的代码 train_dataset = train_dataset.shuffle(1024).batch(64) test_dataset = test_dataset.batch(64)
问题原因及最终修复方案
错误核心是重复调用batch()导致数据集维度嵌套:
- 原代码先对整个
dataset执行.batch(64),此时每个元素是包含64个样本的batch - 后续又对
train_dataset和test_dataset多次调用.batch(),相当于把已有的batch再次打包,形成嵌套的batch结构,输入形状变成(None, None, None, 224, 224, 3),和模型期望的(None, 224, 224, 3)不匹配
修正步骤:
- 预处理阶段只做映射,不提前batch,保持数据集每个元素是单样本
- 划分训练测试集后,仅执行一次
shuffle和batch操作
修正后的完整代码:
import numpy as np import pandas as pd import tensorflow as tf import tensorflow_datasets as tfds tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR) model = tf.keras.Sequential([ tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(224, 224, 3)), tf.keras.layers.MaxPooling2D(2, 2), tf.keras.layers.Conv2D(64, (3, 3), activation='relu'), tf.keras.layers.MaxPooling2D(2, 2), tf.keras.layers.Conv2D(128, (3, 3), activation='relu'), tf.keras.layers.MaxPooling2D(2, 2), tf.keras.layers.Flatten(), tf.keras.layers.Dense(128, activation='relu'), tf.keras.layers.Dense(1, activation='sigmoid') ]) model.compile(loss='binary_crossentropy', optimizer=tf.keras.optimizers.Adam(learning_rate=0.001), metrics=['accuracy']) annotations_file = '/content/balloon-data.csv' annotations = pd.read_csv(annotations_file) image_paths = [] labels = [] for i, row in annotations.iterrows(): if row['num_balloons'] > 0: image_path = 'path/to/image/{}'.format(row['fname']) image_paths.append(image_path) labels.append(1) else: image_path = 'path/to/image/{}'.format(row['fname']) image_paths.append(image_path) labels.append(0) dataset = tf.data.Dataset.from_tensor_slices((image_paths, labels)) def preprocess_image(image_path, label): image = tf.io.read_file(image_path) image = tf.image.decode_jpeg(image, channels=3) image = tf.image.resize(image, (224, 224)) image = image / 255.0 return image, label # 仅做预处理映射,不提前batch dataset = dataset.map(preprocess_image) train_size = int(0.8 * len(image_paths)) test_size = len(image_paths) - train_size train_dataset = dataset.take(train_size) test_dataset = dataset.skip(train_size) # 对划分后的数据集执行一次shuffle和batch train_dataset = train_dataset.shuffle(1024).batch(64) test_dataset = test_dataset.batch(64) model.fit(train_dataset, epochs=10, validation_data=test_dataset)
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

