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

Keras Resizing层无法处理不同尺寸图像输入的问题与解决

Keras Resizing层使用问题与解决方案

我原本以为Keras的Resizing层支持输入不同尺寸的图像,但实际使用时遇到了问题,以下代码可复现报错情况:

import tensorflow as tf
import tensorflow_datasets as tfds
from tensorflow.keras import layers
dsTrain = tfds.load('CatsVsDogs', split='train[:10%]', as_supervised=True).batch(128).prefetch(tf.data.AUTOTUNE)

model = tf.keras.models.Sequential()
model.add(layers.InputLayer(input_shape=(None, None, 3)))
model.add(layers.Resizing(200, 200, crop_to_aspect_ratio=True)) # 问题出在这里
model.add(layers.Rescaling(1./255))
model.add(layers.Conv2D(8, (3, 3), activation='relu', kernel_initializer='random_normal', padding='same'))
model.add(layers.MaxPooling2D((3,3)))
model.add(layers.Dense(2))

model.compile(optimizer='rmsprop',loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),metrics=['accuracy'])
model.fit(dsTrain,epochs=10,batch_size=128) 

# 报错信息:
# 无法对组件0中形状不同的张量进行批处理。第一个元素形状为[262,350,3],第二个元素形状为[409,336,3]

我想掌握该层的正确用法,虽然可以提前调整图像尺寸,但还是希望了解Resizing层的规范使用方式。

编辑1

我尝试将预处理逻辑集成到模型中,代码如下:

import tensorflow as tf
import tensorflow_datasets as tfds
from tensorflow import keras
from tensorflow.keras import layers
dsTrain = tfds.load('CatsVsDogs', split='train[:10%]', as_supervised=True).batch(128).prefetch(tf.data.AUTOTUNE)
IMAGE_SIZE = 100

preprocessing_model = tf.keras.models.Sequential()
preprocessing_model.add(layers.InputLayer(input_shape=(None, None, 3)))
preprocessing_model.add(layers.Resizing(IMAGE_SIZE, IMAGE_SIZE, crop_to_aspect_ratio=True))
preprocessing_model.add(layers.Rescaling(1./255))

training_model = tf.keras.models.Sequential()
training_model.add(layers.InputLayer(input_shape=(IMAGE_SIZE, IMAGE_SIZE, 3)))
training_model.add(layers.Conv2D(8, (3, 3), activation='relu', kernel_initializer='random_normal', padding='same'))
training_model.add(layers.MaxPooling2D((5,5)))
training_model.add(layers.Flatten())
training_model.add(layers.Dense(2))

inputs = keras.Input(shape=preprocessing_model.input_shape)
outputs = training_model(preprocessing_model(inputs))
model = tf.keras.Model(inputs, outputs)

model.summary()
model.compile(optimizer='rmsprop',loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),metrics=['accuracy'])
model.fit(dsTrain,epochs=3,batch_size=128) 

但出现维度不兼容报错:

WARNING:tensorflow:构建模型时输入形状为(None, None, None, 3),但实际调用时输入形状为(None, None, None, None, 3),维度不兼容。
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-82-6e99f023839a> in <module>
     22 
     23 inputs = keras.Input(shape=preprocessing_model.input_shape)
---> 24 outputs = training_model(preprocessing_model(inputs))
     25 model = tf.keras.Model(inputs, outputs)
     26 

1 frames
/usr/local/lib/python3.7/dist-packages/keras/preprocessing/image.py in smart_resize(x, size, interpolation)
    110     if img.shape.rank < 3 or img.shape.rank > 4:
    111       raise ValueError(
---> 112           '期望图像数组形状为`(高度, 宽度, 通道数)`或`(批大小, 高度, 宽度, 通道数)`,但实际输入维度不符合要求,形状为{img.shape}。')

ValueError: 调用Resizing层时遇到异常:
期望图像数组形状为`(高度, 宽度, 通道数)`或`(批大小, 高度, 宽度, 通道数)`,但实际输入形状为(None, None, None, None, 3)。

编辑2

调整输入维度后,预处理层集成成功,但仍无法接收不同尺寸图像,报错如下:

import tensorflow as tf
import tensorflow_datasets as tfds
from tensorflow import keras
from tensorflow.keras import layers
IMAGE_SIZE = 100
dsTrain = tfds.load('CatsVsDogs', split='train[:10%]', as_supervised=True).batch(128).prefetch(tf.data.AUTOTUNE)

preprocessing_model = tf.keras.models.Sequential()
preprocessing_model.add(layers.InputLayer(input_shape=(None, None, 3)))
preprocessing_model.add(layers.Resizing(IMAGE_SIZE, IMAGE_SIZE, crop_to_aspect_ratio=True))
preprocessing_model.add(layers.Rescaling(1./255))

training_model = tf.keras.models.Sequential()
training_model.add(layers.InputLayer(input_shape=(IMAGE_SIZE, IMAGE_SIZE, 3)))
training_model.add(layers.Conv2D(8, (3, 3), activation='relu', kernel_initializer='random_normal', padding='same'))
training_model.add(layers.MaxPooling2D((5,5)))
training_model.add(layers.Flatten())
training_model.add(layers.Dense(2))

inputs = keras.Input(shape=preprocessing_model.input_shape[1:]) # [1:] 为批处理添加维度
outputs = training_model(preprocessing_model(inputs))
model = tf.keras.Model(inputs, outputs)

model.summary()
model.compile(optimizer='rmsprop',loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),metrics=['accuracy'])
model.fit(dsTrain,epochs=3,batch_size=128) 

# model.fit报错:无法对组件0中形状不同的张量进行批处理。第一个元素形状为[262,350,3],第二个元素形状为[409,336,3]

最终结论与解决方案

我终于搞懂了问题核心:训练阶段的数据必须统一尺寸(因为批处理要求张量形状一致),但训练好的包含Resizing层的模型,在推理阶段可以接收不同尺寸的图像。解决方案代码如下:

import tensorflow as tf
import tensorflow_datasets as tfds
from tensorflow import keras
from tensorflow.keras import layers
import numpy as np
import matplotlib.pyplot as plt
import random

IMAGE_SIZE = 100
dsTrain = tfds.load('CatsVsDogs', split='train[:10%]', as_supervised=True)
dsPredict = dsTrain.take(77)

# 训练前统一图像尺寸,满足批处理要求
def preprocess(image, label):
    image = tf.image.resize(image, (100,100))
    return image, label
dsTrain = dsTrain.map(preprocess).shuffle(1024).batch(128).prefetch(tf.data.AUTOTUNE)

# 预处理模型(包含Resizing层,推理时可处理任意尺寸图像)
preprocessing_model = tf.keras.models.Sequential()
preprocessing_model.add(layers.Resizing(IMAGE_SIZE, IMAGE_SIZE, crop_to_aspect_ratio=True, input_shape=(None, None, 3))) # 训练时此层冗余,但推理时有用
preprocessing_model.add(layers.Rescaling(1./255))

# 核心训练模型
training_model = tf.keras.models.Sequential()
training_model.add(layers.Conv2D(8, (3, 3), activation='relu', kernel_initializer='random_normal', padding='same'))
training_model.add(layers.MaxPooling2D((5,5)))
training_model.add(layers.Flatten())
training_model.add(layers.Dense(2))

# 组合模型
inputs = keras.Input(shape=preprocessing_model.input_shape[1:])
outputs = training_model(preprocessing_model(inputs))
model = tf.keras.Model(inputs, outputs)

model.summary()
model.compile(optimizer='rmsprop',loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),metrics=['accuracy'])
model.fit(dsTrain,epochs=1,batch_size=128) 

# 测试:用任意尺寸的图像推理
for image, labelId in dsPredict.skip(random.randint(0, 50)).take(1):
    dsImage = tf.keras.preprocessing.image.img_to_array(image)
    dsImage = np.expand_dims(dsImage, axis = 0) # 添加批维度
    prediction = model.predict(dsImage)
    plt.imshow(image)
    plt.title(f"预测值:{prediction[0][0]}, {prediction[0][1]}")
    plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 20:09:30