Как я могу исправить ошибки измерения уровня CNN с фиксированным размером ядра и фиксированным количеством фильтров?

#python #tensorflow #keras #conv-neural-network

#python #тензорный поток #keras #conv-нейронная сеть

Вопрос:

В настоящее время я пытаюсь воссоздать модель CNN, используемую в статье

«Использование CNN для распознавания выражений лица: исследование влияния размера ядра и количества фильтров на точность» Абхинавом Агравалом и Намитой Миттал (https://doi.org/10.1007/s00371-019-01630-9 ).

Он уникален тем, что использует фиксированные размеры ядра и фиксированное количество фильтров и без выпадающих слоев или полностью подключенного слоя. Предлагаемая модель из статьи выглядит следующим образом:

 Input data (64 × 64) grayscale image
Data augmentation
CONV 8 × 8 × 32,BATCH NORM
CONV 8 × 8 × 32, RELU, STRIDE (2 × 2)
CONV 8 × 8 × 32, BATCH NORM
CONV 8 × 8 × 32, RELU, STRIDE (2 × 2)
CONV 8 × 8 × 32, BATCH NORM
CONV 8 × 8 × 32, RELU, STRIDE (2 × 2)
CONV 8 × 8 × 32, BATCH NORM
CONV 8 × 8 × 32, RELU, STRIDE (2 × 2)
CONV 8 × 8 × 32, BATCH NORM
CONV 8 × 8 × 32, RELU, STRIDE (2 × 2)
CONV 8 × 8 × 32, BATCH NORM
CONV 8 × 8 × 32, RELU, STRIDE (2 × 2)
CONV 8 × 8 × 32, BATCH NORM
CONV 8 × 8 × 32, RELU, STRIDE (2 × 2)
CONV 8 × 8 × 32, BATCH NORM
CONV 7 × 7 × 7, RELU, STRIDE (1 × 1)
SOFTMAX
 

Мой код выглядит следующим образом и пытается точно воссоздать модель из бумаги, используя тот же набор данных и изображения.

 import tensorflow as tf

from tensorflow import keras
from tensorflow.keras import datasets, layers, models
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPooling2D, BatchNormalization
from tensorflow.keras.models import Sequential
#from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt

def plot_model_acc(history):
    #model history for accuracy
    plt.plot(history.history['accuracy'], label='accuracy')
    plt.plot(history.history['val_accuracy'], label = 'val_accuracy')
    plt.title('Model Accuracy')
    plt.xlabel('Epoch')
    plt.ylabel('Accuracy')
    plt.legend(['train','test'], loc='upper left')
    plt.savefig('model_acc.png', bbox_inches='tight')
    plt.close()

def plot_model_loss(history):
    #model history for loss
    plt.plot(history.history['loss'], label='loss')
    plt.plot(history.history['val_loss'], label='val_loss')
    plt.title('Model Loss')
    plt.ylabel('Loss')
    plt.xlabel('Epoch')
    plt.legend(['train', 'test'], loc='upper left')
    plt.savefig('model_loss.png', bbox_inches='tight')
    plt.close()



#model parameters
train_directory = 'train'
test_directory = 'test'
val_directory = 'validation'
num_train = 28709
num_test = 7178
num_val = 7178
batch_size = 64
num_epoch = 10


#creating datagen class and rescaling pixel values from  0-255 to 0-1 for grayscale
train_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)
val_datagen = ImageDataGenerator(rescale=1./255)

#angry 0, disgusted 1, fearful 2, happy 3, neutral 4, sad 5, surprised 6

train_iterator = train_datagen.flow_from_directory(
    train_directory,
    target_size=(64, 64),
    class_mode='categorical',
    batch_size=batch_size,
    color_mode='grayscale')

test_iterator = test_datagen.flow_from_directory(
    test_directory,
    target_size=(64, 64),
    class_mode='categorical',
    batch_size=batch_size,
    color_mode='grayscale')

val_iterator = val_datagen.flow_from_directory(
    val_directory,
    target_size=(64, 64),
    class_mode='categorical',
    batch_size=batch_size,
    color_mode='grayscale')
#colormode grayscale since rescale=1./255
#class_mode is categorical, returns 2D one-hot encoded label

#model creation
#output layer size after conv layer is 
#[(W−K 2P)/S] 1.
#W is the input volume - in your case 64 (for 64x64x1 image)
#K is the Kernel size - in your case 8
#P is the padding - in your case 0
#S is the stride - which you have not provided.


model = Sequential()

model.add(Conv2D(32, kernel_size=(8, 8), input_shape=(64,64,1)))
model.add(BatchNormalization())
model.add(Conv2D(32, kernel_size=(8, 8), activation='relu', strides=(2,2)))
model.add(Conv2D(32, kernel_size=(8, 8)))
model.add(BatchNormalization())

model.summary()

model.add(Conv2D(32, kernel_size=(8, 8), activation='relu', strides=(2,2)))
model.add(Conv2D(32, kernel_size=(8, 8)))
model.add(BatchNormalization())
model.add(Conv2D(32, kernel_size=(8, 8), activation='relu', strides=(2,2)))
model.add(Conv2D(32, kernel_size=(8, 8)))
model.add(BatchNormalization())

model.summary()

model.add(Conv2D(32, kernel_size=(8, 8), activation='relu', strides=(2,2)))
model.add(Conv2D(32, kernel_size=(8, 8)))
model.add(BatchNormalization())
model.add(Conv2D(32, kernel_size=(8, 8), activation='relu', strides=(2,2)))
model.add(Conv2D(32, kernel_size=(8, 8)))
model.add(BatchNormalization())

model.summary()

model.add(Conv2D(32, kernel_size=(8, 8), activation='relu', strides=(2,2)))
model.add(Conv2D(32, kernel_size=(8, 8)))
model.add(BatchNormalization())
model.add(Conv2D(32, kernel_size=(8, 8), activation='relu', strides=(2,2)))
model.add(Conv2D(32, kernel_size=(8, 8)))
model.add(BatchNormalization())

model.summary()

model.add(Conv2D(7, kernel_size=(7, 7), strides=(1,1)))
model.add(layers.Activation('softmax'))

model.summary()


#optimizer definition, learning rate, lower takes more time, but high values may cause unstable training
adam_optimizer = keras.optimizers.Adam(learning_rate=0.0001)

#CategoricalCrossentropy for one-hot encoded labels and dense layer uses softmax activation, otherwise use other loss functions
model.compile(optimizer=adam_optimizer,
              loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

history = model.fit(
    train_iterator, 
    steps_per_epoch=num_train // batch_size, 
    epochs=num_epoch,
    validation_data=test_iterator,
    validation_steps=num_val // batch_size
    )

print(history.history.keys())
plot_model_acc(history)
plot_model_loss(history)
model.save_weights('model.h5')
 

Я столкнулся с ошибкой:

«tensorflow.python.framework.errors_impl.InvalidArgumentError: отрицательный размер измерения, вызванный вычитанием 8 из 6 для ‘conv2d_4 / Conv2D’ с входными формами: [?, 6, 6, 32], [8, 8, 32, 32]».

Я понимаю, что форма вывода из последовательных слоев свертки может становиться слишком маленькой и, таким образом, выдавать мне ошибку. Как это можно исправить? Заполнение? Что меня смущает, так это то, что я не могу отредактировать размер ядра или количество фильтров, чтобы исправить ошибку.

Любая информация будет оценена.

Ответ №1:

установите для same каждого слоя свертки значение padding :

 model.add(Conv2D(32, kernel_size=(8, 8),padding='same'))
 

заполнение по умолчанию — это valid то, что оно не выполняет заполнение. same позволяет добавлять отступы, чтобы output_shape совпадал с input_shape .

Комментарии:

1. Спасибо! У меня было ощущение, что это может быть связано с заполнением, но, поскольку это явно не упоминалось в документе, я не был уверен. Это сработало отлично!