Преобразование Caffe в Keras сгруппированной свертки - PullRequest
0 голосов
/ 09 февраля 2019

Я пытаюсь взять вес из очень простой модели Caffe и интерпретировать ее как полностью функциональную модель Keras.

Это оригинальное определение модели в Caffe, назовем его simple.prototxt:

input: "im_data"
input_shape {
  dim: 1
  dim: 3
  dim: 1280
  dim: 1280
}
layer {
  name: "conv1"
  type: "Convolution"
  bottom: "im_data"
  top: "conv1"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  convolution_param {
    num_output: 96
    kernel_size: 11
    pad: 5
    stride: 4
  }
}
layer {
  name: "relu1"
  type: "ReLU"
  bottom: "conv1"
  top: "conv1"
}
layer {
  name: "pool1"
  type: "Pooling"
  bottom: "conv1"
  top: "pool1"
  pooling_param {
    pool: MAX
    kernel_size: 3
    pad: 0
    stride: 2
  }
}
layer {
  name: "norm1"
  type: "LRN"
  bottom: "pool1"
  top: "norm1"
  lrn_param {
    local_size: 5
    alpha: 0.0001
    beta: 0.75
  }
}
layer {
  name: "conv2"
  type: "Convolution"
  bottom: "norm1"
  top: "conv2"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  convolution_param {
    num_output: 256
    kernel_size: 5
    pad: 2
    group: 2
  }
}
layer {
  name: "relu2"
  type: "ReLU"
  bottom: "conv2"
  top: "conv2"
}

Определение слоя в Caffe может выглядеть сложным, но оно просто берет изображение измерений 1280x1280x3, передает его в сверточный слой, затем максимально объединяет его и передает в последний сверточный слой.

Вот его реализация в Keras , которая намного проще:

from keras.models import Model
from keras.layers import Input, BatchNormalization, 
from keras.activations import relu, softmax

im_data = Input(shape=(1280, 1280, 3),
                   dtype='float32',
                   name='im_data')
conv1 = Conv2D(filters=96,
               kernel_size=11,
               strides=(4, 4),
               activation=relu,
               padding='same',
               name='conv1')(im_data)

pooling1 = MaxPooling2D(pool_size=(3, 3),
                        strides=(2, 2),
                        padding='same',
                        name='pooling1')(conv1)
normalized1 = BatchNormalization()(pooling1)  # https://stats.stackexchange.com/questions/145768/importance-of-local-response-normalization-in-cnn

conv2 = Conv2D(filters=256,
               kernel_size=5,
               activation=relu,
               padding='same',
               name='conv2')(normalized1)
model = Model(inputs=[im_data], outputs=conv2)  

Проблема:

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

Проблема в том, что последний слой свертки Keras имеет другое значение в 3-м измерении по сравнению с последним слоем свертки в Caffe.См. Ниже.


Весовые формы для Кафе :

>>> net = caffe.net('simple.prototxt', 'premade_weights.caffemodel', caffe.TEST)
>>> for i in range(len(net.layers)):
...     if len(net.layers[i].blobs) != 0:  # if layer has no weights
...         print(("name", net._layer_names[i]))
...         print("weight_shapes", [v.data.shape for v in net.layers[i].blobs])
('name', 'conv1')
('weight_shapes', [(96, 3, 11, 11), (96,)])
('name', 'conv2')
('weight_shapes', [(256, 48, 5, 5), (256,)])

Весовые формы для Керас :

>>> for layer in model.layers:
...     if len(layer.get_weights()) != 0:
...         print(("name", layer.name))
...         print(("weight_shapes", [w.shape for w in layer.get_weights()]))  
('name', 'conv1')
('weight_shapes', [(11, 11, 3, 96), (96,)])
('name', 'conv2')
('weight_shapes', [(5, 5, 96, 256), (256,)])

Это кажется странным поведением.Как видите, форма conv1 в Caffe и Keras одинакова (игнорируя порядок).Но в Caffe conv2 форма равна [(256, 48, 5, 5), (256,)]), тогда как в Keras 'conv2' форма равна [(5, 5, 96, 256), (256,)], , обратите внимание , что 48*2=96.

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


Вопрос:

Правильно ли я интерпретировал определение модели от Caffe до Keras?Особенно максимальный уровень пула и его параметры?

Большое спасибо!

1 Ответ

0 голосов
/ 10 февраля 2019

Обратите внимание на поле group: 2 в вашем определении conv2.Это означает, что у вас есть сгруппированная свертка ( Caffe: Что означает групповой параметр? ).Технически это означает, что у вас есть два фильтра, каждый из которых имеет форму (128, 48, 5, 5).Первый сворачивается с первыми 48 каналами и производит первые 128 выходов, второй - для остальных.Однако Caffe хранит эти два веса в одном двоичном объекте, поэтому его форма равна (128x2, 48, 5, 5)

. В слое Keras Conv2D такого параметра нет, но широко распространенный обходной прием - разделить карту входных объектов.со слоями Lambda обработайте их двумя различными сверточными слоями и затем объедините обратно в одну карту объектов.

from keras.layers import Concatenate

normalized1_1 = Lambda(lambda x: x[:, :, :, :48])(normalized1)
normalized1_2 = Lambda(lambda x: x[:, :, :, 48:])(normalized1)

conv2_1 = Conv2D(filters=128,
                 kernel_size=5,
                 activation=relu,
                 padding='same',
                 name='conv2_1')(normalized1_1)

conv2_2 = Conv2D(filters=128,
                 kernel_size=5,
                 activation=relu,
                 padding='same',
                 name='conv2_2')(normalized1_2)

conv2 = Concatenate(name='conv_2_merge')([conv2_1, conv2_2])

Я не проверял код на правильность, но идея должна быть примерно такой.

Относительно вашей задачи: преобразование сетей из Caffe в Keras может быть сложным.Чтобы получить абсолютно тот же результат, вы должны столкнуться с множеством тонких вещей, таких как асимметричное заполнение в свертках или другое поведение максимального пула .Вот почему, если вы импортируете веса из Caffe, вы, вероятно, не сможете заменить слой LRN на batchnorm.К счастью, в Керасе есть реализации LRN, например здесь .

...