Нейронная сеть предсказывает только один класс

#machine-learning #neural-network #conv-neural-network #tf.keras #image-classification

Вопрос:

моя модель предсказывает только один класс из двоичного класса. Модель принимает видеовход с помощью генератора видеокадров Keras и получает 350 кадров для каждого видео. Модель должна принимать входные последовательности из 350 кадров и выводить двоичный класс с использованием BLSTM. Форма ввода является (350, 112, 75, 3). Размер пакета равен 2 из-за ошибки OOM. Я не знаю, может ли это быть проблемой или в коде что-то не так, но модель, похоже, ничему не научилась. Это и есть код:

 from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, BatchNormalization, MaxPool2D, GlobalMaxPool2D
def build_convnet(shape=(112, 75, 2)):
    momentum = .9
    model = Sequential()
    model.add(Conv2D(64, (3,3), input_shape=shape, padding='same', activation='relu'))
    model.add(Conv2D(64, (3,3), padding='same', activation='relu'))
    model.add(BatchNormalization(momentum=momentum))
    
    model.add(MaxPool2D())
    
    model.add(Conv2D(128, (3,3), padding='same', activation='relu'))
    model.add(Conv2D(128, (3,3), padding='same', activation='relu'))
    model.add(BatchNormalization(momentum=momentum))
    
    model.add(MaxPool2D())
    
    model.add(Conv2D(256, (3,3), padding='same', activation='relu'))
    model.add(Conv2D(256, (3,3), padding='same', activation='relu'))
    model.add(BatchNormalization(momentum=momentum))
    
    model.add(MaxPool2D())
    
    model.add(Conv2D(512, (3,3), padding='same', activation='relu'))
    model.add(Conv2D(512, (3,3), padding='same', activation='relu'))
    model.add(BatchNormalization(momentum=momentum))
    
    # flatten...
    model.add(GlobalMaxPool2D())
    
    return model
 
 from tensorflow.keras.layers import LSTM, Bidirectional
from tensorflow.keras.layers import TimeDistributed, Dense, Dropout
def action_model(shape=(350, 112, 75, 3), nbout=2):
    # Create our convnet with (112, 75, 3) input shape
    convnet = build_convnet(shape[1:])
    
    # then create our final model
    model = Sequential()
    
    # add the convnet with (350, 112, 75, 3) shape
    model.add(TimeDistributed(convnet, input_shape=shape))
    model.add(Bidirectional(LSTM(units = 512, return_sequences = True, input_shape = (NBFRAME, 112*75*3))))
    model.add(Dropout(0.5))

    # Adding a second LSTM layer and Dropout layer
    model.add(Bidirectional(LSTM(units = 512, return_sequences = True)))
    model.add(Dropout(0.5))

    # Adding a third LSTM layer and Dropout layer
    model.add(Bidirectional(LSTM(units = 512)))
    model.add(Dropout(0.5))
    model.add(Dense(nbout, activation='softmax'))
    model.summary()
    return model
 

Это краткое описание модели.

img

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

1. Вы перетасовывали свои данные на основе видео (НЕ на основе кадров)? (Предполагая, что каждое видео из 350 кадров соответствует одному из двух классов). Без перетасовки обучение будет предвзятым.

2. Я проверил и распечатал индексы видео в генераторе в случайном порядке

3. Хорошо, не могли бы вы проверить кривую обучения? Насыщается ли он очень рано (и потери вообще перестали уменьшаться)? Если это так, то ваша модель может столкнуться Dying ReLU с проблемой. Попробуйте снизить скорость обучения и/или использовать некоторые специализированные методы инициализации веса, такие как He initialization . tensorflow.org/api_docs/python/tf/keras/initializers/HeUniform . Вы также можете попробовать другие варианты ReLU подобного Leakly ReLU .

4. Я попытался использовать меньшую скорость обучения и утечку ReLU: во время обучения модель кажется лучше как в обучающем, так и в проверочном наборе (точность 70-80%), но в тестовом наборе она имеет точность 52%.

5. Рад узнать, что ваша проблема решена. Но проблема, с которой вы сталкиваетесь сейчас, отличается от проблемы вопроса. Вам лучше задать новый вопрос с кодом и, самое главное, со всеми сгенерированными вами сюжетами. Но сейчас я предлагаю вам проверить тот факт, что-если данные о поездах (по крайней мере, данные проверки) являются хорошим представителем тестовых данных или нет. Чтобы убедиться в этом, вы можете задать себе небольшой вопрос: если кто-то перепутает тестовые данные с данными о поездах, сможете ли вы их разделить? Если вы можете, то ваши данные о поездах не очень хороши. Но если вы не можете, то ваши данные о поездах в порядке.

Ответ №1:

я думаю, что вы помещаете много данных в память, вы пробовали уменьшить количество кадров для видео? Помогает ли это?

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

1. Число уже уменьшено, еще немного, и я могу потерять много информации

Ответ №2:

Ваша модель слишком большая, я уберу эту деталь:

 emodel.add(Conv2D(128, (3,3), padding='same', activation='relu'))
model.add(Conv2D(128, (3,3), padding='same', activation='relu')) 
model.add(BatchNormalization(momentum=momentum)) 
model.add(MaxPool2D())         
model.add(Conv2D(256, (3,3), padding='same', activation='relu')) 
model.add(Conv2D(256, (3,3), padding='same', activation='relu'))   
model.add(BatchNormalization(momentum=momentum))          
model.add(MaxPool2D())       
model.add(Conv2D(512, (3,3), padding='same', activation='relu'))  
model.add(Conv2D(512, (3,3), padding='same', activation='relu')) 
model.add(BatchNormalization(momentum=momentum))
 

Может быть, это вызывает ум, может быть, вам это не нужно.