Создание пользовательского data_generator в Keras для fit_generate ()

Я пытаюсь обучить CNN-LSTM читать последовательность из 6 кадров за раз в CNN (VGG16 без верхнего уровня) и передавать извлеченные функции LSTM в Keras.

Проблема в том, что, поскольку мне нужно отправлять 6 кадров за раз, мне нужно изменять форму каждые 6 кадров и добавлять измерение. Кроме того, поскольку метки предназначены для каждого кадра, мне нужно создать еще одну переменную, чтобы получить метку первого кадра для каждой последовательности и поместить ее в новый массив, а затем скормить обе для загрузки модели (код ниже).

Проблема в том, что данные становятся слишком большими для использования model.fit (), и даже при попытке использовать его с небольшой частью данных я получаю странные ужасные результаты, поэтому я пытаюсь использовать model.fit_generator для итерации ввода в модель. Но поскольку я не могу напрямую загружать данные, которые загружаю из набора данных (потому что мне нужно изменить форму и сделать то, что я объяснил в первом абзаце), я пытаюсь создать свой собственный генератор. Однако дела идут не очень хорошо, и я продолжаю получать ошибки о том, что кортеж не является итератором. Кто-нибудь знает, как я могу исправить код, чтобы он работал?

train_batches = ImageDataGenerator().flow_from_directory(train_path, target_size=(224, 224),
                                                         classes=['Bark', 'Bitting', 'Engage', 'Hidden', 'Jump',
                                                                  'Stand', 'Walk'], batch_size=18156, shuffle=False)
valid_batches = ImageDataGenerator().flow_from_directory(valid_path, target_size=(224, 224),
                                                         classes=['Bark', 'Bitting', 'Engage', 'Hidden', 'Jump',
                                                                  'Stand', 'Walk'], batch_size=6, shuffle=False)
test_batches = ImageDataGenerator().flow_from_directory(test_path, target_size=(224, 224),
                                                        classes=['Bark', 'Bitting', 'Engage', 'Hidden', 'Jump',
                                                                 'Stand','Walk'], batch_size=6, shuffle=False)

def train_gen():

    n_frames=6    
    n_samples=6 #to decide
    H=W=224
    C = 3

    imgs, labels = next(train_batches)

    y = np.empty((n_samples, 7))
    j = 0
    for i in range(n_samples):       
        y[i] = labels[j]        
        j +=6
    frame_sequence = imgs.reshape(n_samples,n_frames, H,W,C)

    return frame_sequence,y



def valid_gen():

    v_frames=6
    v_samples=1
    H=W=224
    C = 3

    vimgs,vlabels = next(valid_batches)
    y2 = np.empty((v_samples, 7))

    k = 0
    for l in range(v_samples):       
        y2[l] = vlabels[k]        
        k +=6
    valid_sequence = vimgs.reshape(v_samples,v_frames, H,W,C)

    return valid_sequence,y2

def main():

    cnn = VGG16(weights='imagenet',
                include_top='False', pooling='avg')

    cnn.layers.pop()
    print(cnn.summary())
    cnn.trainable = False

    video_input= Input(shape=(None,224,224,3), name='video_input')   
    print(video_input.shape)

    encoded_frame_sequence = TimeDistributed(cnn)(video_input) # the output will be a sequence of vectors
    encoded_video = LSTM(256)(encoded_frame_sequence)  # the output will be a vector
    output = Dense(7, activation='relu')(encoded_video)
    video_model = Model(inputs=[video_input], outputs=output)

    tr_data = train_gen()
    vd_data= valid_gen()
    print(video_model.summary())

    imgs, labels = next(train_batches)    
    vimgs,vlabels = next(valid_batches)

    print("Training ...")
    video_model.compile(Adam(lr=.001), loss='categorical_crossentropy', metrics=['accuracy'])
    video_model.fit_generator(tr_data, 
                              steps_per_epoch=1513, 
                             validation_data=vd_data, 
                              validation_steps=431, 
                              epochs=1, 
                              verbose=2)

Есть ли ошибка в том, как я определяю генератор?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
2 338
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Похоже, я неправильно определил генераторы. Как объяснил мне администратор Keras, у этого определения есть две проблемы.

  1. Вместо return нам нужно использовать yield
  2. Нам нужен цикл while True, чтобы убедиться, что он продолжает читать

Обратите внимание, что в остальной части кода, с которым я имел дело, есть несколько ошибок, но поскольку этот вопрос касается генератора, я отправляю ответ только по этой части (есть два генератора, но они похожи, за исключением ввода):

def train_gen():

    n_frames=6    
    n_samples=5 #to decide
    H=W=224
    C = 3

    while True:

        imgs, labels = next(train_batches)
        #frame_sequence = imgs.reshape(n_samples,n_frames, H,W,C)

        y = np.empty((n_samples, 7))
        j = 0
        #print("labels")
        #print(labels)
        #print("y")
        #print(y.shape)

        if len(labels) == n_frames*n_samples:
            frame_sequence = imgs.reshape(n_samples,n_frames, H,W,C)
            for i in range(n_samples):

                y[i] = labels[j]
               # print("inside: ")
                #print(y[i])
               # print(labels[j])
                j +=6                


        yield frame_sequence,y 

не могли бы вы объяснить мне, в чем разница между n_samples ia и n_frame. Это n_samples = number_videos, n_frames = #frames_in_a_video. Следовательно, это может означать папку со 100 кадрами, которую я делаю на 4 партии по 25 кадров?

KDX2 05.01.2019 11:08

n_samples относится к количеству последовательностей. n_frames - количество кадров в 1 последовательности. Допустим, мы рассматриваем 1 последовательность из 8 кадров. Это означает, что если я прочитал 16 кадров за одну итерацию, мне нужно было бы установить n_samples равным 2 и n_frames = 8. Итак, если вы установите длину последовательности на 25 и вы прочитаете 100 кадров за итерацию, у вас действительно будет n_samples = 4. Это может быть слишком сложно для вашего процессора / графического процессора, хотя

Wazaki 08.01.2019 06:49

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

Спасибо за ссылку. Я поискал его, когда пытался решить проблему, но метод слишком сложен для моей цели. Я думаю, что опубликованное мной решение отлично справляется со своей задачей.

Wazaki 09.06.2018 16:59

Другие вопросы по теме