Проблема с трансферным обучением с Tensorflow и Keras - PullRequest
0 голосов
/ 03 октября 2018

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

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

import tensorflow as tf
from tensorflow.python.keras import models

## Create network based on VGG19 arch with pretrained weights
vgg = tf.keras.applications.vgg19.VGG19(include_top=False, weights='imagenet')
vgg.trainable = False

Когда мы смотрим на сводку VGG19, мы видим ожидаемую архитектуру.

vgg.summary()
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_2 (InputLayer)         (None, None, None, 3)     0         
_________________________________________________________________
block1_conv1 (Conv2D)        (None, None, None, 64)    1792      
_________________________________________________________________
block1_conv2 (Conv2D)        (None, None, None, 64)    36928     
_________________________________________________________________
block1_pool (MaxPooling2D)   (None, None, None, 64)    0         
_________________________________________________________________
block2_conv1 (Conv2D)        (None, None, None, 128)   73856     
_________________________________________________________________
block2_conv2 (Conv2D)        (None, None, None, 128)   147584    
_________________________________________________________________
block2_pool (MaxPooling2D)   (None, None, None, 128)   0         
_________________________________________________________________
block3_conv1 (Conv2D)        (None, None, None, 256)   295168    
_________________________________________________________________
block3_conv2 (Conv2D)        (None, None, None, 256)   590080    
_________________________________________________________________
block3_conv3 (Conv2D)        (None, None, None, 256)   590080    
_________________________________________________________________
block3_conv4 (Conv2D)        (None, None, None, 256)   590080    
_________________________________________________________________
block3_pool (MaxPooling2D)   (None, None, None, 256)   0         
_________________________________________________________________
block4_conv1 (Conv2D)        (None, None, None, 512)   1180160   
_________________________________________________________________
block4_conv2 (Conv2D)        (None, None, None, 512)   2359808   
_________________________________________________________________
block4_conv3 (Conv2D)        (None, None, None, 512)   2359808   
_________________________________________________________________
block4_conv4 (Conv2D)        (None, None, None, 512)   2359808   
_________________________________________________________________
block4_pool (MaxPooling2D)   (None, None, None, 512)   0         
_________________________________________________________________
block5_conv1 (Conv2D)        (None, None, None, 512)   2359808   
_________________________________________________________________
block5_conv2 (Conv2D)        (None, None, None, 512)   2359808   
_________________________________________________________________
block5_conv3 (Conv2D)        (None, None, None, 512)   2359808   
_________________________________________________________________
block5_conv4 (Conv2D)        (None, None, None, 512)   2359808   
_________________________________________________________________
block5_pool (MaxPooling2D)   (None, None, None, 512)   0         
=================================================================
Total params: 20,024,384
Trainable params: 0
Non-trainable params: 20,024,384
_________________________________________________________________

Затем мы извлекаем слои и создаемновая модель

## Layers to extract
content_layers = ['block5_conv2'] 
style_layers = ['block1_conv1','block2_conv1','block3_conv1','block4_conv1','block5_conv1']
## Get output layers corresponding to style and content layers 
style_outputs = [vgg.get_layer(name).output for name in style_layers]
content_outputs = [vgg.get_layer(name).output for name in content_layers]
model_outputs = style_outputs + content_outputs

new_model = models.Model(vgg.input, model_outputs)

Когда создается new_model, я считаю, что у нас должна быть модель намного меньшего размера.Тем не менее, сводка по модели показывает, что новая модель очень близка к исходной модели (она содержит 19 из 22 слоев из VGG19) и содержит слои, которые мы не извлекли.

new_model.summary()

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_2 (InputLayer)         (None, None, None, 3)     0         
_________________________________________________________________
block1_conv1 (Conv2D)        (None, None, None, 64)    1792      
_________________________________________________________________
block1_conv2 (Conv2D)        (None, None, None, 64)    36928     
_________________________________________________________________
block1_pool (MaxPooling2D)   (None, None, None, 64)    0         
_________________________________________________________________
block2_conv1 (Conv2D)        (None, None, None, 128)   73856     
_________________________________________________________________
block2_conv2 (Conv2D)        (None, None, None, 128)   147584    
_________________________________________________________________
block2_pool (MaxPooling2D)   (None, None, None, 128)   0         
_________________________________________________________________
block3_conv1 (Conv2D)        (None, None, None, 256)   295168    
_________________________________________________________________
block3_conv2 (Conv2D)        (None, None, None, 256)   590080    
_________________________________________________________________
block3_conv3 (Conv2D)        (None, None, None, 256)   590080    
_________________________________________________________________
block3_conv4 (Conv2D)        (None, None, None, 256)   590080    
_________________________________________________________________
block3_pool (MaxPooling2D)   (None, None, None, 256)   0         
_________________________________________________________________
block4_conv1 (Conv2D)        (None, None, None, 512)   1180160   
_________________________________________________________________
block4_conv2 (Conv2D)        (None, None, None, 512)   2359808   
_________________________________________________________________
block4_conv3 (Conv2D)        (None, None, None, 512)   2359808   
_________________________________________________________________
block4_conv4 (Conv2D)        (None, None, None, 512)   2359808   
_________________________________________________________________
block4_pool (MaxPooling2D)   (None, None, None, 512)   0         
_________________________________________________________________
block5_conv1 (Conv2D)        (None, None, None, 512)   2359808   
_________________________________________________________________
block5_conv2 (Conv2D)        (None, None, None, 512)   2359808   
=================================================================
Total params: 15,304,768
Trainable params: 15,304,768
Non-trainable params: 0
_________________________________________________________________

Поэтому мои вопросы ...

  1. Почему слои, которые я не извлек, отображаются в new_model.Находятся ли они в процессе создания модели в соответствии с документами ?Кажется, это слишком близко к архитектуре VGG19.
  2. Из того, как я понимаю модель (функциональный API) Keras , прохождение нескольких выходных слоев должно создать модель с несколькими выходами, однакоКажется, что новая модель является последовательной и имеет только один выходной слой.Это тот случай?

1 Ответ

0 голосов
/ 03 октября 2018
  1. Почему слои, которые я не извлек, отображаются в new_model.

Это потому, что при создании модели с models.Model(vgg.input, model_outputs) the "промежуточные "слои между vgg.input и выходными слоями также включены.Это намеченный способ, поскольку VGG построен таким образом.

Например, если вы хотите создать модель следующим образом: models.Model(vgg.input, vgg.get_layer('block2_pool') будет включен каждый промежуточный слой между input_1 и block2_pool, поскольку вход должен проходить через нихдо достижения block2_pool.Ниже приведен частичный график VGG, который может помочь с этим.

enter image description here

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

from keras.layers import Conv2D, Input

x_input = Input(shape=(28, 28, 1,))
block1_conv1 = Conv2D(64, (3, 3), padding='same')(x_input)
block2_conv2 = Conv2D(128, (3, 3), padding='same')(x_input)
...

new_model = models.Model(x_input, [block1_conv1, block2_conv2, ...])
... однако, похоже, что новая модель является последовательной и имеет только один выходной слой.Это так?

Нет, ваша модель имеет несколько выходов, как вы и предполагали.model.summary() должен отображать, какие слои связаны с чем (что поможет понять структуру), но я считаю, что есть небольшая ошибка с некоторыми версиями, которая предотвращает это.В любом случае вы можете увидеть, что ваша модель имеет несколько выходов, проверив new_model.output, что должно дать вам:

[<tf.Tensor 'block1_conv1/Relu:0' shape=(?, ?, ?, 64) dtype=float32>,
 <tf.Tensor 'block2_conv1/Relu:0' shape=(?, ?, ?, 128) dtype=float32>,
 <tf.Tensor 'block3_conv1/Relu:0' shape=(?, ?, ?, 256) dtype=float32>,
 <tf.Tensor 'block4_conv1/Relu:0' shape=(?, ?, ?, 512) dtype=float32>,
 <tf.Tensor 'block5_conv1/Relu:0' shape=(?, ?, ?, 512) dtype=float32>,
 <tf.Tensor 'block5_conv2/Relu:0' shape=(?, ?, ?, 512) dtype=float32>]

Последовательная печать в new_model.summary() - это просто выбор дизайна, так как это может привести к волосатостисо сложными моделями.

...