model.fit.generator для двойного пути cnn - PullRequest
0 голосов
/ 24 апреля 2020

Я пытаюсь запустить параллельный путь CNN, который соединен с плотным слоем. Я назвал первый путь как модель1, а вторую часть как модель2, а каскадную модель, содержащую параллельные патчи как модель. Я скомпилировал модель, и резюме модели также работает. Теперь я должен тренировать модель. Для этого я дал вклад в модель CNN, представленную как model.fit.generator. Я использую версию keras 2.1.6.

    base_model1 = model.fit_generator(["train_generator","train_generator"], steps_per_epoch = 
    nb_train_samples // batch_size, epochs = epochs, validation_data = validation_generator,
    validation_steps = nb_validation_samples // batch_size) 

полученное сообщение об ошибке

WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/math_grad.py:1250: add_dispatch_support.<locals>.wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.where in 2.0, which has the same broadcast rule as np.where
Epoch 1/2
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-14-ba6c6e678605> in <module>()
      3   epochs = epochs,
      4   validation_data = validation_generator,
----> 5   validation_steps = nb_validation_samples // batch_size)

4 frames
/usr/local/lib/python3.6/dist-packages/keras/utils/data_utils.py in _data_generator_task(self)
    656                             # => Serialize calls to
    657                             # infinite iterator/generator's next() function
--> 658                             generator_output = next(self._generator)
    659                             self.queue.put((True, generator_output))
    660                         else:
TypeError: 'list' object is not an iterator

И моя модель

# Conv Layer 1
model1.add(layers.SeparableConv2D(32, (9, 9), activation='relu', input_shape=input_shape))
model1.add(layers.MaxPooling2D(2, 2))
# model.add(layers.Dropout(0.25))

# Conv Layer 2
model1.add(layers.SeparableConv2D(64, (9, 9), activation='relu'))
model1.add(layers.MaxPooling2D(2, 2))
# model.add(layers.Dropout(0.25))

# Conv Layer 3
model1.add(layers.SeparableConv2D(128, (9, 9), activation='relu'))
model1.add(layers.MaxPooling2D(2, 2))
# model.add(layers.Dropout(0.25))

# model.add(layers.SeparableConv2D(256, (9, 9), activation='relu'))
# model.add(layers.MaxPooling2D(2, 2))
# Flatten the data for upcoming dense layer
model1.add(layers.Flatten())

model1.add(layers.Dropout(0.5))
model1.add(layers.Dense(512, activation='relu'))
#model1.add(layers.Dense(output_classes,) activation='relu'))
#model1.build(input_shape = (input_shape)




model2 = Sequential()
# Conv Layer 1
model2.add(layers.SeparableConv2D(32, (9, 9), activation='relu', input_shape=input_shape))
model2.add(layers.MaxPooling2D(2, 2))
# model.add(layers.Dropout(0.25))

# Conv Layer 2
model2.add(layers.SeparableConv2D(64, (9, 9), activation='relu'))
model2.add(layers.MaxPooling2D(2, 2))
# model.add(layers.Dropout(0.25))

# Conv Layer 3
model2.add(layers.SeparableConv2D(128, (9, 9), activation='relu'))
model2.add(layers.MaxPooling2D(2, 2))
# model.add(layers.Dropout(0.25))

# model.add(layers.SeparableConv2D(256, (9, 9), activation='relu'))
# model.add(layers.MaxPooling2D(2, 2))
# Flatten the data for upcoming dense layer
model2.add(layers.Flatten())

model2.add(layers.Dropout(0.5))
model2.add(layers.Dense(512, activation='relu'))
#model2.add(layers.Dense(output_classes, activation='relu'))

from keras.layers import concatenate
model = Sequential()
model_concat = concatenate([model1.output, model2.output], axis=-1)
model_concat = Dense(128, activation='relu')(model_concat)
model_concat = Dense(7, activation='softmax')(model_concat)
model = Model(inputs=[model1.input, model2.input], outputs=model_concat)



print(model.summary()) ```

My generator code is



```train_generator = train_datagen.flow_from_directory(
    TRAIN_FOLDER,
    target_size=(img_height, img_width),
    batch_size=batch_size,
    seed = random_seed,
    shuffle = False,
    subset = 'training',
    class_mode='categorical')

validation_generator = train_datagen.flow_from_directory(
    TRAIN_FOLDER,
    target_size=(img_height, img_width),
    batch_size=batch_size,
    seed = random_seed,
    shuffle = False,
    subset = 'validation',
    class_mode='categorical')

test_datagen = ImageDataGenerator(rescale=1. / 255)
test_generator = test_datagen.flow_from_directory(
    TEST_FOLDER,
    target_size=(img_height, img_width),
    batch_size=batch_size,
    seed = random_seed,
    shuffle = False,
    class_mode='categorical')```

Ответы [ 2 ]

0 голосов
/ 25 апреля 2020

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

from keras import layers, Model
input_shape = (128,128,3) # Change this accordingly
my_input = layers.Input(shape=input_shape) # one input

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

def parallel_layers(my_input, parallel_id=1):
  x = layers.SeparableConv2D(32, (9, 9), activation='relu', name='conv_1_'+str(parallel_id))(my_input)
  x = layers.MaxPooling2D(2, 2)(x)
  x = layers.SeparableConv2D(64, (9, 9), activation='relu', name='conv_2_'+str(parallel_id))(x)
  x = layers.MaxPooling2D(2, 2)(x)
  x = layers.SeparableConv2D(128, (9, 9), activation='relu', name='conv_3_'+str(parallel_id))(x)
  x = layers.MaxPooling2D(2, 2)(x)
  x = layers.Flatten()(x)
  x = layers.Dropout(0.5)(x)
  x = layers.Dense(512, activation='relu')(x)

  return x

Давайте теперь дважды вызовем функцию параллельных слоев на нашем входе:

parallel1 = parallel_layers(my_input, 1)
parallel2 = parallel_layers(my_input, 2)

Теперь мы объединим их результаты и создадим окончательную модель:

concat = layers.Concatenate()([parallel1, parallel2])
x = layers.Dense(128, activation='relu')(concat)
x = Dense(7, activation='softmax')(x)

final_model = Model(inputs=my_input, outputs=x)
final_model.summary()

Эта модель (надеюсь) будет работать с вашим генератором данных следующим образом:

final_model.fit_generator(train_generator, steps_per_epoch = 
    nb_train_samples // batch_size, epochs = epochs, validation_data = validation_generator,
    validation_steps = nb_validation_samples // batch_size) 
0 голосов
/ 24 апреля 2020

Вы должны изменить эту строку:

base_model1 = model.fit_generator(["train_generator","train_generator"] ...

на:

base_model1 = model.fit_generator([train_generator,train_generator]...

Эта ошибка означает, что вместо данных о поездах вы используете только список. Генератор данных не может выполнить итерацию по списку.

...