繁体   English   中英

在功能 API keras model 中使用 datagen.flow_from_directory() 出现不兼容的形状错误

[英]incompatible shapes error using datagen.flow_from_directory() in a functional API keras model

我是一个尝试学习 TF 和 keras 的超级 n00b。 我想使用功能 API 创建一个 model 并由 ImageDataGenerator() 和 flow_from_directory() 提供。 我仅限于使用 spyder (5.1.5) 和 python 3.7、keras 2.8.0、tensorflow 2.8.0。

我已将示例补丁组织到带标签的文件夹中以支持 flow_from_directory()。 有 7 个类,每个补丁是一个 small.png 图像,大小应该是 128 x 128 x 3。

但是,当我尝试调用 model.fit() 时,我收到一个 ValueError:

Traceback (most recent call last):

  File ~\.spyder-py3\MtP_treeCounts\shape_error_code.py:129 in <module>
    history = model.fit(ds_train,

  File ~\Anaconda3\envs\tf28\lib\site-packages\keras\utils\traceback_utils.py:67 in error_handler
    raise e.with_traceback(filtered_tb) from None

  File ~\Anaconda3\envs\tf28\lib\site-packages\tensorflow\python\framework\func_graph.py:1147 in autograph_handler
    raise e.ag_error_metadata.to_exception(e)

ValueError: in user code:

    File "C:\Users\jlovitt\Anaconda3\envs\tf28\lib\site-packages\keras\engine\training.py", line 1021, in train_function  *
        return step_function(self, iterator)
    File "C:\Users\jlovitt\Anaconda3\envs\tf28\lib\site-packages\keras\engine\training.py", line 1010, in step_function  **
        outputs = model.distribute_strategy.run(run_step, args=(data,))
    File "C:\Users\jlovitt\Anaconda3\envs\tf28\lib\site-packages\keras\engine\training.py", line 1000, in run_step  **
        outputs = model.train_step(data)
    File "C:\Users\jlovitt\Anaconda3\envs\tf28\lib\site-packages\keras\engine\training.py", line 860, in train_step
        loss = self.compute_loss(x, y, y_pred, sample_weight)
    File "C:\Users\jlovitt\Anaconda3\envs\tf28\lib\site-packages\keras\engine\training.py", line 918, in compute_loss
        return self.compiled_loss(
    File "C:\Users\jlovitt\Anaconda3\envs\tf28\lib\site-packages\keras\engine\compile_utils.py", line 201, in __call__
        loss_value = loss_obj(y_t, y_p, sample_weight=sw)
    File "C:\Users\jlovitt\Anaconda3\envs\tf28\lib\site-packages\keras\losses.py", line 141, in __call__
        losses = call_fn(y_true, y_pred)
    File "C:\Users\jlovitt\Anaconda3\envs\tf28\lib\site-packages\keras\losses.py", line 245, in call  **
        return ag_fn(y_true, y_pred, **self._fn_kwargs)
    File "C:\Users\jlovitt\Anaconda3\envs\tf28\lib\site-packages\keras\losses.py", line 1789, in categorical_crossentropy
        return backend.categorical_crossentropy(
    File "C:\Users\jlovitt\Anaconda3\envs\tf28\lib\site-packages\keras\backend.py", line 5083, in categorical_crossentropy
        target.shape.assert_is_compatible_with(output.shape)

    ValueError: Shapes (None, None) and (None, 128, 128, 1) are incompatible

我认为我的发电机没有产生任何东西。 我认为这个问题与我的 model 被馈送类似 [50,7] (其中批量大小为 50,7 是类数)而不是 [50,128,128,3] 之类的东西有关,这将是从整个class 标记的文件夹。 所以它实际上并没有训练任何东西。

这是代码:

# set up
import numpy as np

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import models
from tensorflow.keras.layers import Input, Conv2D,Conv1D, UpSampling2D, concatenate,Dense, Flatten, Dropout,BatchNormalization, MaxPooling2D
from tensorflow.keras.models import Model, Sequential, load_model
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.preprocessing import image_dataset_from_directory
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from keras import backend as K

K.clear_session()
del model
#build generator & train set

datagen = ImageDataGenerator(
    rotation_range=40,
    zoom_range=(0.95,0.95),
    width_shift_range=0.2,
    height_shift_range=0.2,
    dtype = np.float32,
    rescale=1/255,
    shear_range=0.2,
    horizontal_flip=True,
    fill_mode='nearest',
    data_format = "channels_last",
    )

image_height = 128
image_width = 128
batch_size = 50


ds_train = datagen.flow_from_directory(
    directory=r"C:/Users/jlovitt/Pyworking/for_CNN_5/RGB_aerial/patches/train/rgb/organized/",
    target_size=(image_height,image_width),
    batch_size = batch_size,
    color_mode="rgb",
    class_mode = 'categorical',
    shuffle=True,
    seed =42,
    #subset='training',
    )
#set params

# STEP_SIZE_TRAIN = round(int(ds_train.n//ds_train.batch_size),-1)
STEP_SIZE_TRAIN = 180

# STEP_SIZE_VALID = round(int(ds_validation.n//ds_validation.batch_size),-1)
STEP_SIZE_VALID = 20

lr = 0.001
#define model


def U_model():
   
    in1 = Input(shape=(256,256,3))

    conv1 = Conv2D(32,(3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(in1)
    conv1 = Dropout(0.1)(conv1)
    conv1 = Conv2D(32,(3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(conv1)
    pool1 = MaxPooling2D((2,2))(conv1)

    conv2 = Conv2D(64,(3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(pool1)
    conv2 = Dropout(0.1)(conv2)
    conv2 = Conv2D(64,(3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(conv2)
    pool2 = MaxPooling2D((2,2))(conv2)

    conv3 = Conv2D(128,(3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(pool2)
    conv3 = Dropout(0.1)(conv3)
    conv3 = Conv2D(128,(3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(conv3)
    pool3 = MaxPooling2D((2,2))(conv3)
    
    conv4 = Conv2D(128, 3, activation='relu', kernel_initializer='he_normal', padding='same')(pool3)
    conv4 = Dropout(0.1)(conv4)
    conv4 = Conv2D(128, 3, activation='relu', kernel_initializer='he_normal', padding='same')(conv4)
    
    up1 = concatenate([UpSampling2D((2,2))(conv4),conv3],axis=-1)
    conv5 = Conv2D(64,(3,3), activation='relu', kernel_initializer='he_normal', padding='same')(up1)
    conv5 = Dropout(0.1)(conv5)
    conv5 = Conv2D(64,(3,3), activation='relu', kernel_initializer='he_normal', padding='same')(conv5)
    
    up2 = concatenate([UpSampling2D((2,2))(conv5), conv2], axis=-1)
    conv6 = Conv2D(64, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(up2)
    conv6 = Dropout(0.1)(conv6)
    conv6 = Conv2D(64, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(conv6)

    up3 = concatenate([UpSampling2D((2,2))(conv6), conv1], axis=-1)
    conv7 = Conv2D(32, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(up3)
    conv7 = Dropout(0.1)(conv7)
    conv7 = Conv2D(32, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(conv7)
    
    out1 = keras.layers.Dense(7)(conv7)
    
    #defining inputs and outputs of model
    model = Model(inputs=[in1], outputs=[out1])

    model.compile(loss="categorical_crossentropy", optimizer =keras.optimizers.SGD(learning_rate=lr,momentum=0.9),metrics=[tf.keras.metrics.MeanSquaredError(),tf.keras.metrics.MeanAbsoluteError()])
    
    return model

model = U_model()
model.summary()
#train model

history = model.fit(ds_train,
                    steps_per_epoch=STEP_SIZE_TRAIN,
                    validation_data=ds_validation,
                    validation_steps=STEP_SIZE_VALID,
                    epochs=10)

事实证明,我解决了以下问题:

在编译器中将优化器更改为 Adam,在我的最终密集 (7) output 之前添加了一个 flatten() 层

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM