Ошибка Keras ValueError: Ошибка при проверке цели модели (CNN) - PullRequest
0 голосов
/ 09 октября 2019

Алгоритм предназначен для описания товаров. Эта часть распознает цвета одежды по изображениям (14 выходных значений), однако все равно возвращает следующую ошибку

Ошибка:

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.

часть кода:

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)

форма ввода определена в первом слое effnet, поэтому я не знаю, почему происходит ошибка.

Я также пытался преобразовать данные в массив Numpy, но эффект тот же.

Поезд данных: 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

Ответы [ 2 ]

1 голос
/ 10 октября 2019

Вы должны использовать class_mode="other" вместо class_mode="multi_output" в train_generator и val_generator. [Ref: multi-label-классификация-с-keras-imagedatagenerator ]

Кроме того, поскольку это проблема классификации по нескольким меткам, вы должны использовать функцию активации sigmoid в выходном слоевашей модели. Вы также должны использовать binary_crossentropy убыток при компиляции вашей модели, поскольку для каждого целевого класса вам необходимо определить, принадлежит ли вход к этому классу.

model.add(Dense(14, activation='sigmoid'))
model.compile(loss='binary_crossentropy',
              optimizer='adam', 
              metrics=["accuracy"])

Надеюсь, это поможет.

1 голос
/ 10 октября 2019

y_train (метки истинности земли) в вашей модели для каждого изображения должен быть одним массивом из 14 элементов [0,0,1,1,0,1,0, ...], но похоже, что вы передаете14 различных массивов для каждого изображения. Измените форму y_train (y_col) в вашем коде. Кроме того, вы сохраняете его в виде списка, конвертируете его в массив numpy, как ожидает модель.

Я считаю, что ваши данные хранятся в виде pandas dataframe. В этом случае опустите первый столбец df.drop('Path', axis=1, inplace=True). Затем вы можете преобразовать в массив NumPy как y_train = df.to_numpy(). Это даст вам цель в правильной форме. Дайте это в подходящем методе для обучения.

Также обратите внимание, что df.to_numpy() работает, только если вы используете последнюю версию pandas. Для старых версий вы можете использовать df.values для преобразования кадра данных в массив numpy.

...