首页 > 解决方案 > Keras ValueError: Error when checking model target (CNN)

问题描述

The algorithm is designed to describe products. This part recognizes the colors of clothes from images (14 output values) however, it still returns the following error

Error:

ValueError: Error when checking model target: the list of Numpy arrays 
that you are passing to your model is not the size the model expected. 
Expected to see 1 array(s), but instead got the following list of 14 
arrays.

part of the code:

TRAIN_LABELS_FILE = "train/labels.txt"
VAL_LABELS_FILE = "val/labels.txt"
TEST_LABELS_FILE = "test/labels.txt"
COLOR_FILE = "names.txt"

# Specify image size
IMG_WIDTH = 128
IMG_HEIGHT = 128
CHANNELS = 3

color = pd.read_csv(COLOR_FILE)
color = color.T
color_list = list(color.iloc[0])
color_list.insert(0,'beige')
color_list.insert(0,'path')

train = pd.read_csv(TRAIN_LABELS_FILE,sep=" ",names=color_list, dtype="str")
val = pd.read_csv(VAL_LABELS_FILE,sep=" ",names=color_list, dtype="str")

from keras.preprocessing.image import ImageDataGenerator
BATCH_SIZE = 4
#directory = os.path.dirname(path)

# Add Image augmentation to our generator
train_datagen = ImageDataGenerator(rotation_range=360,
                                   horizontal_flip=True,
                                   vertical_flip=True,
                                   validation_split=0.15,
                                   #preprocessing_function=preprocess_image, 
                                   rescale=1 / 128.)

# Use the dataframe to define train and validation generators
train_generator = train_datagen.flow_from_dataframe(train, 
                                                    x_col='path', 
                                                    y_col=color_list[1:],
                                                    directory='train',
                                                    target_size=(IMG_WIDTH, IMG_HEIGHT),
                                                    batch_size=BATCH_SIZE,
                                                    class_mode="multi_output", 
                                                    subset='training')

val_generator = train_datagen.flow_from_dataframe(val, 
                                                  x_col='path', 
                                                  y_col=color_list[1:],
                                                  directory='val',
                                                  target_size=(IMG_WIDTH, IMG_HEIGHT),
                                                  batch_size=BATCH_SIZE,
                                                  class_mode="multi_output",
                                                  subset='validation')

from efficientnet import EfficientNetB5
effnet = EfficientNetB5(input_shape=(IMG_WIDTH, IMG_HEIGHT, CHANNELS),
                          weights='imagenet',
                          include_top=False)

def build_model():

    model = Sequential()
    model.add(effnet)
    model.add(GlobalAveragePooling2D())
    model.add(Dropout(0.5))
    model.add(Dense(5, activation='relu'))
    model.add(Dense(14, activation='softmax'))
    model.compile(loss='categorical_crossentropy',
                  optimizer='adam', 
                  metrics=["categorical_accuracy"])
    print(model.summary())
    return model

# Initialize model
model = build_model()

# Begin training
model.fit_generator(train_generator,
                    steps_per_epoch=train_generator.samples // BATCH_SIZE,
                    epochs=35,
                    validation_data=val_generator,
                    validation_steps = val_generator.samples // BATCH_SIZE)

input shape is defined in the first layer 'effnet' so I don't know why an error occurs.

I also tried to convert the data to a numpy array but the effect is the same.

Dataframe train: sth.

      Path    black  grey  green blue   etc....
0  12345.jpg    1      0       1  0
1  12345.jpg    0      0       1  0
2  12345.jpg    1      0       0  1
3  12345.jpg    0      1       0  1
4  12345.jpg    0      0       1  1
5  12345.jpg    0      0       1  1

标签: pythonkerasconv-neural-network

解决方案


The y_train (ground truth labels) in your model for each image should be a single array of 14 elements [0,0,1,1,0,1,0,...], but looks like you are passing 14 different arrays for each image. Change the shape of y_train (y_col) in your code. Also, you are storing it in a list, convert it to numpy array as the model expects.

I believe that your data is stored as pandas dataframe. In that case, drop the first column df.drop('Path', axis=1, inplace=True). Then you can convert to numpy array as y_train = df.to_numpy(). This will give you the target in correct shape. Give this in fit method for training.

Also, note that df.to_numpy() works only if you are using the latest pandas version. For old versions, you can use df.values to convert the dataframe to numpy array.


推荐阅读