Tensorflow 神经网络中的形状不正确 - 形状的批量大小

Incorrect Shape in Tensorflow Neural Network - Batch size in shape

我正在学习这个关于在 Keras 上实现 EfficientNet 的教程。:

Tensorflow

我正在使用自己的数据集,因此必须手动加载它。由于某种原因,批量大小被包含在张量形状中并且它抛出错误。

from tensorflow.keras.models import Sequential
from tensorflow.keras import layers
from tensorflow.keras.layers import Dense, Dropout, GlobalMaxPooling2D, Input
from tensorflow.keras import optimizers
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.callbacks import EarlyStopping
from tensorflow.keras.applications import EfficientNetB0
import tensorflow as tf
import os, os.path
import glob
import shutil
import sys
import matplotlib.pyplot as plt

sys.path.insert(1, './efficientnet_keras_transfer_learning')


# Options: EfficientNetB0, EfficientNetB1, EfficientNetB2, EfficientNetB3 to B7
# Higher the number, the more complex the model is.
# EfficientNetB0, EfficientNetB1, EfficientNetB2, EfficientNetB3
# loading pretrained conv base model
# define input height and width

### This changes model weights name ###
model_type = 'B0'

if model_type == 'B0':
    height, width = 224, 224
elif model_type == 'B1':
    height, width = 240, 240
elif model_type == 'B2':
    height, width = 260, 260
elif model_type == 'B3':
    height, width = 300, 300
elif model_type == 'B4':
    height, width = 380, 380
elif model_type == 'B5':
    height, width = 456, 456
elif model_type == 'B6':
    height, width = 528, 528
elif model_type == 'B7':
    height, width = 600, 600

# input_shape = (height, width, 3)

# ### Change Model Type ###
# conv_base = EfficientNetB0(
#     include_top=True,
#     weights=None,
#     classes=3
#     # input_shape=input_shape,
# )

filepath = (os.path.expanduser(
    '~') + '\dataset')

# Prepare Data
train_dir = filepath + '\Train'
test_dir = filepath + '\Test'
val_dir = filepath + '\Val'

batch_size = 32

train_ds = tf.keras.utils.image_dataset_from_directory(
    train_dir,
    labels='inferred',
    seed=42,
    image_size=(height, width),
    batch_size=batch_size
    )

val_ds = tf.keras.utils.image_dataset_from_directory(
    val_dir,
    labels='inferred',
    seed=42,
    image_size=(height, width),
    batch_size=batch_size
    )

class_names = train_ds.class_names
num_classes = len(class_names)
print('There are ' + str(num_classes) + ' classes:\n' + str(class_names))


train_ds = train_ds.map(lambda image, label: (tf.image.resize(image, (height, width)), label))
val_ds = val_ds.map(lambda image, label: (tf.image.resize(image, (height, width)), label))

# plt.figure(figsize=(10, 10))
# for images, labels in train_ds.take(1):
#   for i in range(9):
#     ax = plt.subplot(3, 3, i + 1)
#     plt.imshow(images[i].numpy().astype("uint8"))
#     plt.title(class_names[labels[i]])
#     plt.axis("off")


img_augmentation = Sequential(
    # [
        # layers.RandomRotation(factor=0.15),
        # layers.RandomTranslation(height_factor=0.1, width_factor=0.1),
        # layers.RandomFlip(),
        # layers.RandomContrast(factor=0.1),
    # ],
    name="img_augmentation",
)


# One-hot / categorical encoding
def input_preprocess(image, label):
    label = tf.one_hot(label, num_classes)
    return image, label

train_ds = train_ds.map(
    input_preprocess, num_parallel_calls=tf.data.AUTOTUNE)
train_ds = train_ds.batch(batch_size=batch_size, drop_remainder=True)
train_ds = train_ds.prefetch(tf.data.AUTOTUNE)

val_ds = val_ds.map(input_preprocess)
val_ds = val_ds.batch(batch_size=batch_size, drop_remainder=True)

inputs = Input(shape=(height, width, 3))
x = img_augmentation(inputs)
outputs = EfficientNetB0(include_top=True, weights=None, classes=num_classes)(x)


model = tf.keras.Model(inputs, outputs)
model.compile(
    optimizer="adam", loss="categorical_crossentropy", metrics=["accuracy"]
)

model.summary()

epochs = 50
hist = model.fit(train_ds, epochs=epochs, validation_data=val_ds, verbose=2)

我一直收到错误消息:

    ValueError: Input 0 is incompatible with layer model_4: expected shape=(None, 224, 224, 3), found shape=(32, None, 224, 224, 3)

前面的32显然是batch size。但我不知道为什么会这样,无法弄清楚如何匹配。

正如@Frightera 评论的那样,tf.keras.utils.image_dataset_from_directory returns 4Dimension 的图像形状。

示例代码

import pathlib
data_dir = pathlib.Path('/content/images/images')

import tensorflow as tf
batch_size = 16
img_height = 180
img_width = 180
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
  data_dir,
  validation_split=0.2,
  subset="training",
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size)

for image_batch, labels_batch in train_ds:
  print(image_batch.shape)
  print(labels_batch.shape)

输出

(7, 180, 180, 3)
(7,)