Tensorflow 中 Flatten() 层的输入和输出形状问题
Problem with input and output shapes in Flatten() layer in Tensorflow
我正在尝试构建一个用于图像分类的基本卷积神经网络。我有一个属于 4 类 的图像数据集。我使用 ImageDataGenerator
和 flow_from_directory
:
创建了 Tensorflow 数据集
train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
rescale=1./255,
rotation_range=20,
width_shift_range=0.2,
height_shift_range=0.2,
horizontal_flip=True,
validation_split=0.2
)
val_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255, validation_split=0.2)
train_data = train_datagen.flow_from_directory(
dataset_source,
color_mode='rgb',
batch_size=batch_size,
class_mode='categorical',
shuffle=True,
subset='training'
)
val_data = val_datagen.flow_from_directory(
dataset_source,
color_mode='rgb',
batch_size=batch_size,
class_mode='categorical',
shuffle=False,
subset='validation'
)
我测试的 CNN 架构示例很简单,如下所示:
image_shape = (299, 299, 3)
model = tf.keras.Sequential()
model.add(tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=image_shape))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))
model.add(tf.keras.layers.Conv2D(64, (3, 3), activation='relu'))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))
model.add(tf.keras.layers.Conv2D(128, (3, 3), activation='relu'))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(128, activation='relu'))
model.add(tf.keras.layers.Dense(4))
model.compile(loss = "categorical_crossentropy",
optimizer = "adam",
metrics = ["accuracy"])
每当我尝试使用 model.fit(train_data, epochs=100, validation_data = val_data)
开始训练时,我都会收到以下与 Flatten()
层相关的错误:
InvalidArgumentError: Input to reshape is a tensor with 7372800 values, but the requested shape requires a multiple of 645248
[[node sequential_1/flatten_1/Reshape (defined at <ipython-input-9-d01204576b1d>:1) ]] [Op:__inference_train_function_1823]
我使用各种版本的 CNN 检查它,即使是最简单的包含单个卷积层的版本,但每次都会出现错误,只是值不同。这可能很明显,但尽管尝试了很多次我还是无法解决它,所以我将非常感谢任何指示如何处理我的问题。
使用 flow_from_directory
调用而不指定 target_size
只是自找麻烦,因为即使是单个错误大小的输入也会扰乱您的模型拟合过程。简单的解决方法是为了安全起见将 target_size=(299, 299)
添加到调用中(如评论中所示)。
此外,考虑在 flow_from_directory
调用上方添加 image_shape = (299, 299, 3)
并指定 target_size = image_shape[:-1]
以从那里提取它。这将使修改 image_shape
更容易,您可能想要尝试各种输入大小缩放。
我正在尝试构建一个用于图像分类的基本卷积神经网络。我有一个属于 4 类 的图像数据集。我使用 ImageDataGenerator
和 flow_from_directory
:
train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
rescale=1./255,
rotation_range=20,
width_shift_range=0.2,
height_shift_range=0.2,
horizontal_flip=True,
validation_split=0.2
)
val_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255, validation_split=0.2)
train_data = train_datagen.flow_from_directory(
dataset_source,
color_mode='rgb',
batch_size=batch_size,
class_mode='categorical',
shuffle=True,
subset='training'
)
val_data = val_datagen.flow_from_directory(
dataset_source,
color_mode='rgb',
batch_size=batch_size,
class_mode='categorical',
shuffle=False,
subset='validation'
)
我测试的 CNN 架构示例很简单,如下所示:
image_shape = (299, 299, 3)
model = tf.keras.Sequential()
model.add(tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=image_shape))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))
model.add(tf.keras.layers.Conv2D(64, (3, 3), activation='relu'))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))
model.add(tf.keras.layers.Conv2D(128, (3, 3), activation='relu'))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(128, activation='relu'))
model.add(tf.keras.layers.Dense(4))
model.compile(loss = "categorical_crossentropy",
optimizer = "adam",
metrics = ["accuracy"])
每当我尝试使用 model.fit(train_data, epochs=100, validation_data = val_data)
开始训练时,我都会收到以下与 Flatten()
层相关的错误:
InvalidArgumentError: Input to reshape is a tensor with 7372800 values, but the requested shape requires a multiple of 645248
[[node sequential_1/flatten_1/Reshape (defined at <ipython-input-9-d01204576b1d>:1) ]] [Op:__inference_train_function_1823]
我使用各种版本的 CNN 检查它,即使是最简单的包含单个卷积层的版本,但每次都会出现错误,只是值不同。这可能很明显,但尽管尝试了很多次我还是无法解决它,所以我将非常感谢任何指示如何处理我的问题。
使用 flow_from_directory
调用而不指定 target_size
只是自找麻烦,因为即使是单个错误大小的输入也会扰乱您的模型拟合过程。简单的解决方法是为了安全起见将 target_size=(299, 299)
添加到调用中(如评论中所示)。
此外,考虑在 flow_from_directory
调用上方添加 image_shape = (299, 299, 3)
并指定 target_size = image_shape[:-1]
以从那里提取它。这将使修改 image_shape
更容易,您可能想要尝试各种输入大小缩放。