вопрос теории resnet50 — выходная форма и единицы измерения плотных слоев?

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

Вопрос:

я изучаю tensorflow/keras для классификации изображений, и мне кажется, что я упускаю важную часть теории.

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

набор данных составляет 1600 150 х 150 цветных фотографий фруктов, которые делятся на 12 классов. я использую генератор для изображений:

 datagen = ImageDataGenerator(
        validation_split=0.25, 
        rescale=1/255,
        horizontal_flip=True,
        vertical_flip=True,
        width_shift_range=0.2,
        height_shift_range=0.2,
        rotation_range=90)
 
    train_datagen_flow = datagen.flow_from_directory(
        '/datasets/fruits_small/',
        target_size=(150, 150),
        batch_size=32,
        class_mode='sparse',
        subset='training',
        seed=12345)
 
    val_datagen_flow = datagen.flow_from_directory(
        '/datasets/fruits_small/',
        target_size=(150, 150),
        batch_size=32,
        class_mode='sparse',
        subset='validation',
        seed=12345)
 
    features, target = next(train_datagen_flow)
 

вот слои, которые я использую:

магистраль = ResNet50(input_shape=(150, 150, 3),веса=’imagenet’, include_top=False) магистраль.обучаемый = False

 model = Sequential()
    optimizer = Adam(lr=0.001)
    model.add(backbone)
    model.add(GlobalMaxPooling2D())
    model.add(Dense(2048,activation='relu'))
    model.add(BatchNormalization())
    model.add(Dense(512,activation = 'relu'))
    model.add(BatchNormalization())
    model.add(Dense(12, activation='softmax'))
    model.compile(optimizer = optimizer, loss='sparse_categorical_crossentropy',metrics=['acc'])
 

Теперь это моя первая попытка использовать globalmax и resnet50, и я испытываю ОГРОМНОЕ переоснащение, потому что, я полагаю, небольшой набор данных.

я немного почитал на эту тему и предпринял несколько попыток нормализации с ограниченным успехом.

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

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

вот как выглядит мое текущее резюме слоя:

 Model: "sequential_3"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
resnet50 (Model)             (None, 5, 5, 2048)        23587712  
_________________________________________________________________
global_max_pooling2d_3 (Glob (None, 2048)              0         
_________________________________________________________________
dense_7 (Dense)              (None, 2048)              4196352   
_________________________________________________________________
batch_normalization_2 (Batch (None, 2048)              8192      
_________________________________________________________________
dense_8 (Dense)              (None, 512)               1049088   
_________________________________________________________________
batch_normalization_3 (Batch (None, 512)               2048      
_________________________________________________________________
dense_9 (Dense)              (None, 12)                6156      
=================================================================
Total params: 28,849,548
Trainable params: 5,256,716
Non-trainable params: 23,592,832
 

вот как выглядит мой текущий результат:

     Epoch 1/3
40/40 [==============================] - 363s 9s/step - loss: 0.5553 - acc: 0.8373 - val_loss: 3.8422 - val_acc: 0.1295
Epoch 2/3
40/40 [==============================] - 354s 9s/step - loss: 0.1621 - acc: 0.9423 - val_loss: 6.3961 - val_acc: 0.1295
Epoch 3/3
40/40 [==============================] - 357s 9s/step - loss: 0.1028 - acc: 0.9716 - val_loss: 4.8895 - val_acc: 0.1295
 

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

Любой вклад будет оценен по достоинству!

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

1. Может быть, это имеет какое-то отношение к class_mode='sparse', переданному datagen.flow_from_directory . Выход модели-это softmax, верно? Мне кажется, что это соответствует лучше class_mode='"categorical" .

2. Хорошее наблюдение, я могу это попробовать! 🙂

3. Оказывается, категоричность делает OHE, и это очень быстро выходит из-под контроля ресурсов и убивает ядро (похоже, так или иначе)

4. Да, в документах действительно написано «По умолчанию: «категорично». Определяет тип возвращаемых массивов меток: — «категориальными» будут 2D однократно закодированные метки». Поправьте меня, если я ошибаюсь, но softmax-это приближение OHE, верно? Не уверен, что вы имеете в виду, говоря о выходе из-под контроля ресурсов, но, возможно, вам захочется уменьшить свои плотные слои. Я думаю, что 5 м обучаемых параметров-это довольно много для начала. Что произойдет, если вы разрежете оба слоя пополам?

5. @GillesOttervanger ядро умирает-это то, что я имел в виду под ресурсами. для этого я использую онлайн-платформу (это курс, который я прохожу). Тем не менее, ваши предложения о разделении слоев пополам были великолепны — я неправильно понял и подумал, что мне нужно иметь нейрон для каждого вывода из сети resnet, но, перейдя с 256, затем с 64 на последний слой из 12, производительность значительно улучшилась

Ответ №1:

Итак, я обнаружил, что у меня было неправильное представление о форме вывода из слоя resnet/global average — он имел форму 2048, и я думал, что это означает, что мне нужно, чтобы мой первый плотный слой имел 2048 фильтров, что вызывало значительные проблемы с подгонкой.

в конечном счете я изменил свои плотные слои на 256, затем на 64 и, наконец, на 12 (потому что у меня есть 12 классов для классификации), и это значительно повысило производительность.