Построение модели керас - PullRequest
0 голосов
/ 06 июля 2018

Я не понимаю, что происходит в этом коде:

def construct_model(use_imagenet=True):
    # line 1: how do we keep all layers of this model ?
    model = keras.applications.InceptionV3(include_top=False, input_shape=(IMG_SIZE, IMG_SIZE, 3),
                                          weights='imagenet' if use_imagenet else None) # line 1: how do we keep all layers of this model ?

    new_output = keras.layers.GlobalAveragePooling2D()(model.output)

    new_output = keras.layers.Dense(N_CLASSES, activation='softmax')(new_output)
    model = keras.engine.training.Model(model.inputs, new_output)
    return model

В частности, я путаюсь, когда мы вызываем последний конструктор

model = keras.engine.training.Model(model.inputs, new_output)

мы указываем входной слой и выходной слой, но откуда он знает, что мы хотим, чтобы все остальные слои остались?

Другими словами, мы добавляем слой new_output к предварительно обученной модели, которую мы загружаем в строке 1, то есть слой new_output, а затем в конечном конструкторе (последняя строка) мы просто создаем и возвращаем модель с указанные входные и выходные слои, но как он узнает, какие другие слои мы хотим между ними?

Дополнительный вопрос 1): В чем разница между keras.engine.training.Model и keras.models.Model?

Дополнительный вопрос 2): Что именно происходит, когда мы делаем new_layer = keras.layers.Dense (...) (prev_layer)? Возвращает ли операция () новый слой, что именно она делает?

Ответы [ 2 ]

0 голосов
/ 09 июля 2018

Эта модель была создана с использованием Функциональной модели API

В основном это работает так (возможно, если перед тем, как прочесть это, перейдите к «дополнительному вопросу 2» ниже, это может проясниться):

  • У вас есть входной тензор (вы также можете видеть его как "входные данные")
  • Вы создаете (или повторно используете) слой
  • Вы передаете входной тензор слою (вы «называете» слой входом)
  • Вы получите тензор вывода

Вы продолжаете работать с этими тензорами, пока не создадите весь график .

Но это еще не создало "модель". (Один вы можете тренировать и использовать другие вещи).
Все, что у вас есть, - это график, показывающий, куда идут тензоры.

Чтобы создать модель, вы определяете ее конечные конечные точки.


В примере.

  • Они берут существующую модель: model = keras.applications.InceptionV3(...)
  • Они хотят расширить эту модель, чтобы они получили выходной тензор : model.output
  • Они передают этот тензор как вход GlobalAveragePooling2D слоя
  • Они получают тензор вывода этого слоя как new_output
  • Они передают это как входные данные еще одному слою: Dense(N_CLASSES, ....)
  • И получить его вывод как new_output (этот var был заменен, поскольку они не заинтересованы в сохранении его старого значения ...)

Но поскольку он работает с функциональным API, у нас пока нет модели, только график. Для создания модели мы используем Model, определяющий входной тензор и выходной тензор:

new_model = Model(old_model.inputs, new_output)    

Теперь у вас есть модель.
Если вы используете его в другом var, как я (new_model), старая модель все еще будет существовать в model. И эти модели используют одни и те же слои, так что, когда вы тренируете одну из них, другая также обновляется.


Вопрос: откуда он знает, какие еще слои мы хотим добавить между ними?

Когда вы делаете:

outputTensor = SomeLayer(...)(inputTensor)    

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

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

Вероятно, атрибут _keras_history, который добавляется к тензорам, тесно связан с тем, как он отслеживает график.

Таким образом, выполнение Model(old_model.inputs, new_output), естественно, будет следовать единственно возможным путем: графиком.

Если вы попытаетесь сделать это с тензорами, которые не подключены, вы получите ошибку.


Дополнительный вопрос 1

Предпочитают импортировать из "keras.models". По сути, этот модуль будет импортировать из другого модуля:

Обратите внимание, что файл keras/models.py импортирует Model из keras.engine.training. Итак, это то же самое.

Дополнительный вопрос 2

Это не new_layer = keras.layers.Dense(...)(prev_layer).

Это output_tensor = keras.layers.Dense(...)(input_tensor).

Вы делаете две вещи в одной строке:

  • Создание слоя - с помощью keras.layers.Dense(...)
  • Вызов слоя с входным тензором для получения выходного тензора

Если вы хотите использовать один и тот же слой с разными входами:

denseLayer = keras.layers.Dense(...) #creating a layer

output1 = denseLayer(input1)  #calling a layer with an input and getting an output
output2 = denseLayer(input2)  #calling the same layer on another input
output3 = denseLayer(input3)  #again   

Бонус - Создание функциональной модели, равной последовательной модели

Если вы создадите эту последовательную модель:

model = Sequential()
model.add(Layer1(...., input_shape=some_shape))   
model.add(Layer2(...))
model.add(Layer3(...))

Вы делаете точно так же, как:

inputTensor = Input(some_shape)
outputTensor = Layer1(...)(inputTensor)
outputTensor = Layer2(...)(outputTensor)    
outputTensor = Layer3(...)(outputTensor)

model = Model(inputTensor,outputTensor)

В чем разница?

Что ж, функциональные модели API абсолютно бесплатны для сборки в любом случае. Вы можете создавать филиалы:

out1 = Layer1(..)(inputTensor)    
out2 = Layer2(..)(inputTensor)

Вы можете присоединиться к тензорам:

joinedOut = Concatenate()([out1,out2])   

С помощью этого вы можете создать что угодно по вашему желанию со всеми видами причудливых вещей, веток, элементов, конкатенаций, дополнений и т. Д., Что вы не можете сделать с последовательной моделью.

На самом деле модель Sequential также является Model, но создана для быстрого использования в моделях без ответвлений.

0 голосов
/ 09 июля 2018

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

См. https://keras.io/applications/#fine-tune-inceptionv3-on-a-new-set-of-classes:

base_model = InceptionV3(weights='imagenet', include_top=False)
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation='relu')(x)
predictions = Dense(200, activation='softmax')(x)
model = Model(inputs=base_model.input, outputs=predictions)
for layer in base_model.layers:
    layer.trainable = False
model.compile(optimizer='rmsprop', loss='categorical_crossentropy')

Каждый раз, когда слой добавляется операцией типа «x = Dense (...»), информация о вычислительном графе обновляется. Вы можете ввести его в интерактивном режиме, чтобы увидеть, что он содержит:

x.graph.__dict__

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

...