使用TensorFlow加载Stanford Dogs数据集训练分类器遇形状不匹配错误
问题:Stanford Dogs数据集图像分类训练时输入形状不匹配错误
尝试使用Stanford Dogs数据集练习图像增强并构建图像分类器,但训练模型时持续出现输入形状不匹配错误,推测问题可能与normalize函数中调整图像尺寸的方式有关。
原始代码
import tensorflow as tf import tensorflow_datasets as tfds import tensorflow_hub as hub from tensorflow.keras import layers tfds.disable_progress_bar() import os import matplotlib.pyplot as plt import matplotlib.pylab as plt import math import numpy as np import logging logger = tf.get_logger() logger.setLevel(logging.ERROR) dataset, metadata = tfds.load('stanford_dogs', as_supervised=True, with_info=True) train_dataset, test_dataset = dataset['train'], dataset['test']
num_train_examples = metadata.splits['train'].num_examples num_test_examples = metadata.splits['test'].num_examples class_names = metadata.features['label'].names IMG_LEN = 224 N_BREEDS = 120 epochs = 50 image_size = (IMG_LEN, IMG_LEN) def normalize(image, label): normalized_image = tf.image.resize(image, image_size) normalized_image /= 255 return normalized_image, label batch_size = 32 training_batches = train_dataset.cache().shuffle(num_train_examples//4).batch(batch_size).map(normalize).prefetch(1) testing_batches = test_dataset.cache().shuffle(num_train_examples//4).batch(batch_size).map(normalize).prefetch(1) rescale = tf.keras.Sequential([ layers.Rescaling(1./255, input_shape = (IMG_LEN, IMG_LEN,3)) ]) data_augmentation = tf.keras.Sequential([ layers.RandomFlip("horizontal_and_vertical"), layers.RandomRotation(0.2), layers.RandomZoom(0.1) ]) model = tf.keras.models.Sequential([ rescale, data_augmentation, tf.keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(IMG_LEN, IMG_LEN, 3)), tf.keras.layers.MaxPooling2D(2, 2), tf.keras.layers.Flatten(), tf.keras.layers.Dense(600, activation='relu'), tf.keras.layers.Dense(len(class_names), activation=tf.nn.softmax) ]) model.compile(optimizer= "adam", loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=["accuracy"]) from tensorflow.python.distribute.cross_device_ops import validate_destinations history = model.fit( train_dataset, epochs = epochs, steps_per_epoch = 1200 )
错误信息
Epoch 1/50 --------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-12-a35416ceec02> in <module> 47 train_dataset, 48 epochs = epochs, ---> 49 steps_per_epoch = 1200 50 ) 1 frames /usr/local/lib/python3.7/dist-packages/keras/engine/training.py in tf__train_function(iterator) 13 try: 14 do_return = True ---> 15 retval_ = ag__.converted_call(ag__.ld(step_function), (ag__.ld(self), ag__.ld(iterator)), None, fscope) 16 except: 17 do_return = False ValueError: in user code: File "/usr/local/lib/python3.7/dist-packages/keras/engine/training.py", line 1051, in train_function * return step_function(self, iterator) File "/usr/local/lib/python3.7/dist-packages/keras/engine/training.py", line 1040, in step_function ** outputs = model.distribute_strategy.run(run_step, args=(data,)) File "/usr/local/lib/python3.7/dist-packages/keras/engine/training.py", line 1030, in run_step ** outputs = model.train_step(data) File "/usr/local/lib/python3.7/dist-packages/keras/engine/training.py", line 889, in train_step y_pred = self(x, training=True) File "/usr/local/lib/python3.7/dist-packages/keras/utils/traceback_utils.py", line 67, in error_handler raise e.with_traceback(filtered_tb) from None File "/usr/local/lib/python3.7/dist-packages/keras/engine/input_spec.py", line 264, in assert_input_compatibility raise ValueError(f'Input {input_index} of layer "{layer_name}" is ' ValueError: Input 0 of layer "sequential_5" is incompatible with the layer: expected shape=(None, 224, 224, 3), found shape=(None, None, 3)
问题分析与修复方案
核心问题点
- 训练数据集未处理:
model.fit传入了原始的train_dataset,而非你已经做了尺寸调整和批处理的training_batches,导致输入图像尺寸不统一。 - 重复归一化:
normalize函数中已经将图像值除以255,模型里的Rescaling层再次缩放,会导致图像值异常。 - 冗余的input_shape参数:Sequential模型中前面的层已确定输入形状,Conv2D层的
input_shape参数多余且可能引发形状冲突。 - 损失函数参数错误:最后一层用了
softmax激活,SparseCategoricalCrossentropy的from_logits应设为False(可省略)。 - steps_per_epoch设置不合理:手动指定1200步不符合实际数据量,应使用
num_train_examples // batch_size。
修改后的完整代码
import tensorflow as tf import tensorflow_datasets as tfds from tensorflow.keras import layers tfds.disable_progress_bar() import matplotlib.pyplot as plt import numpy as np import logging logger = tf.get_logger() logger.setLevel(logging.ERROR) # 加载数据集 dataset, metadata = tfds.load('stanford_dogs', as_supervised=True, with_info=True) train_dataset, test_dataset = dataset['train'], dataset['test'] num_train_examples = metadata.splits['train'].num_examples num_test_examples = metadata.splits['test'].num_examples class_names = metadata.features['label'].names IMG_LEN = 224 epochs = 50 batch_size = 32 # 数据预处理:调整尺寸+归一化 image_size = (IMG_LEN, IMG_LEN) def normalize(image, label): normalized_image = tf.image.resize(image, image_size) normalized_image /= 255.0 return normalized_image, label # 构建批处理数据集 training_batches = train_dataset.cache().shuffle(num_train_examples//4).batch(batch_size).map(normalize).prefetch(tf.data.AUTOTUNE) testing_batches = test_dataset.cache().batch(batch_size).map(normalize).prefetch(tf.data.AUTOTUNE) # 图像增强层 data_augmentation = tf.keras.Sequential([ layers.RandomFlip("horizontal"), layers.RandomRotation(0.2), layers.RandomZoom(0.1) ]) # 构建模型 model = tf.keras.models.Sequential([ data_augmentation, tf.keras.layers.Conv2D(16, (3,3), activation='relu'), tf.keras.layers.MaxPooling2D(2, 2), tf.keras.layers.Flatten(), tf.keras.layers.Dense(600, activation='relu'), tf.keras.layers.Dense(len(class_names), activation=tf.nn.softmax) ]) # 编译模型 model.compile(optimizer= "adam", loss=tf.keras.losses.SparseCategoricalCrossentropy(), metrics=["accuracy"]) # 训练模型 history = model.fit( training_batches, epochs=epochs, steps_per_epoch=num_train_examples // batch_size )
额外说明
- 图像增强中去掉了垂直翻转,因为狗的姿态垂直翻转没有实际意义,可根据需求调整。
- 测试集不需要shuffle,所以去掉了
shuffle操作。 - 使用
tf.data.AUTOTUNE代替固定的prefetch(1),让系统自动优化预取数量。
内容的提问来源于stack exchange,提问作者Jackson Roach
相关产品推荐
相关产品推荐

