Невозможно преобразовать модель Re snet, обученную с Keras, в модель CoreML - PullRequest
0 голосов
/ 05 февраля 2020

Мне нужно преобразовать модель resnet50 в модель CoreML. Обученная модель Keras работает правильно. Я пытался преобразовать его в Coreml, но вот ошибка, которую я получаю, используя coremltools:

ValueError: Keras layer '<class 'keras.layers.core.Lambda'>' not supported.

Кажется, у меня есть лямбда-функции в моей модели, и Coreml не поддерживает это ... но что я не делаю понять, откуда берутся эти лямбда-функции, поскольку я только что использовал стандартную сеть resnet50 для обучения передаче Я изменил только последний слой с 1000 плотностями на слой с 4 плотностями, вот мой код:

from keras.applications.resnet50 import ResNet50, preprocess_input

full_imagenet_model = ResNet50(weights='imagenet')

output = full_imagenet_model.layers[-2].output
base_model = Model(full_imagenet_model.input, output)

top_model = Sequential()
top_model.add(Dense(4, input_dim=2048, activation='softmax'))
top_model.compile(optimizer=Adam(lr=1e-4),
                  loss='categorical_crossentropy', metrics=['accuracy'])

model = Model(base_model.input, top_model(base_model.output))

Вот начало и конец описания модели:

__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_1 (InputLayer)            (None, 224, 224, 3)  0                                            
__________________________________________________________________________________________________
conv1_pad (ZeroPadding2D)       (None, 230, 230, 3)  0           input_1[0][0]                    
__________________________________________________________________________________________________
conv1 (Conv2D)                  (None, 112, 112, 64) 9472        conv1_pad[0][0]                  
__________________________________________________________________________________________________
bn_conv1 (BatchNormalization)   (None, 112, 112, 64) 256         conv1[0][0]                      
__________________________________________________________________________________________________
activation_1 (Activation)       (None, 112, 112, 64) 0           bn_conv1[0][0]                   
__________________________________________________________________________________________________
pool1_pad (ZeroPadding2D)       (None, 114, 114, 64) 0           activation_1[0][0]               
__________________________________________________________________________________________________
max_pooling2d_1 (MaxPooling2D)  (None, 56, 56, 64)   0           pool1_pad[0][0]                  
__________________________________________________________________________________________________
res2a_branch2a (Conv2D)         (None, 56, 56, 64)   4160        max_pooling2d_1[0][0]            
________________________________________________________________________________________________

(...)           
__________________________________________________________________________________
add_16 (Add)                    (None, 7, 7, 2048)   0           bn5c_branch2c[0][0]              
                                                                 activation_46[0][0]              
__________________________________________________________________________________________________
activation_49 (Activation)      (None, 7, 7, 2048)   0           add_16[0][0]                     
__________________________________________________________________________________________________
avg_pool (GlobalAveragePooling2 (None, 2048)         0           activation_49[0][0]              
__________________________________________________________________________________________________
sequential_1 (Sequential)       (None, 4)            8196        avg_pool[0][0]                   
==================================================================================================
Total params: 23,595,908
Trainable params: 23,542,788
Non-trainable params: 53,120

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

__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_3 (InputLayer)            (None, 224, 224, 3)  0                                            
__________________________________________________________________________________________________
lambda_3 (Lambda)               (None, 224, 224, 3)  0           input_3[0][0]                    
__________________________________________________________________________________________________
lambda_4 (Lambda)               (None, 224, 224, 3)  0           input_3[0][0]                    
__________________________________________________________________________________________________
model_5 (Model)                 (None, 4)            23595908    lambda_3[0][0]                   
                                                                 lambda_4[0][0]                   
__________________________________________________________________________________________________
sequential_2 (Concatenate)      (None, 4)            0           model_5[1][0]                    
                                                                 model_5[2][0]                    
==================================================================================================
Total params: 23,595,908
Trainable params: 23,542,788
Non-trainable params: 53,120

Я понятия не имею, откуда берутся лямбда-слои ... Есть идеи?

Для информации вот как проходит обучение:

opt = Adam(lr=1e-3)

parallel_model = multi_gpu_model(model, gpus=2)

parallel_model.compile(optimizer=opt, loss='categorical_crossentropy',
              metrics=['accuracy'])

history = parallel_model.fit_generator(train_flow, train_flow.n // train_flow.batch_size,
                              epochs=200,
                              validation_data=val_flow,
                              validation_steps=val_flow.n,
                              callbacks=[clr, tensorboard, cb_checkpointer, cb_early_stopper])

Спасибо за помощь

Edit1

А вот как я сохраняю модель:

from tensorflow.python.keras.callbacks import EarlyStopping, ModelCheckpoint
from pyimagesearch.clr_callback import CyclicLR

cb_early_stopper = EarlyStopping(monitor = 'val_acc', patience = 30)
cb_checkpointer = ModelCheckpoint(filepath = 'SAVED_MODELS/EPOCH:50_DataAug:Yes_Monitor:val-acc_DB2.hdf5', monitor = 'val_acc', save_best_only = True, mode = 'auto')
tensorboard = TensorBoard(log_dir="logs/{}".format('model_EPOCH:50_DataAug:Yes_Monitor:val-acc_DB2'))
clr = CyclicLR(
        mode=CLR_METHOD,
        base_lr=MIN_LR,
        max_lr=MAX_LR,
        step_size= STEP_SIZE * (train_flow.n // train_flow.batch_size))

1 Ответ

0 голосов
/ 13 февраля 2020

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

Проблема в том, что использование multi_gpu создает функции lambdas в сводке для загрузки данных в parralel.

Я сейчас ищу возможность реализовать лямбда-функции в coremltools.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...