Keras Преобразование функциональной модели в подкласс модели - PullRequest
1 голос
/ 01 июля 2019

Я пытаюсь использовать Keras Подклассы моделей для перезаписи Функциональной модели , но в подклассе новой модели генерация сводных данных не работает.

Для справки приведем функциональную модель и ее вывод.

filters = 32

# placeholder for inputs
inputs = Input(shape=[16, 16, 16, 12])  

# L-hand side of UNet
conv1 = DoubleConv3D(filters*1)(inputs)
pool1 = MaxPooling3D()(conv1)
...

# middle bottleneck
conv5 = DoubleConv3D(filters*5)(pool4)

# R-hand side of UNet
rsdc6 = ConcatConv3D(filters*4)(conv5, conv4)
conv6 = DoubleConv3D(filters*4)(rsdc6)
...

# sigmoid activation
outputs = Conv3D(1, (1, 1, 1), activation='sigmoid')(conv9)

model = Model(inputs=[inputs], outputs=[outputs])
model.summary()
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_29 (InputLayer)           (None, 16, 16, 16, 1 0                                            
__________________________________________________________________________________________________
conv3d_111 (Conv3D)             (None, 16, 16, 16, 3 10400       input_29[0][0]                   
__________________________________________________________________________________________________
...

И подкласс Model выглядит так:

class UNet3D(Model):
    def __init__(self, **kwargs):
        super(UNet3D, self).__init__(name="UNet3D", **kwargs)        
        self.filters = 32

    def __call__(self, inputs):

        # L-hand side of UNet
        conv1 = DoubleConv3D(self.filters*1)(inputs)
        pool1 = MaxPooling3D()(conv1)
        ...

        # middle bottleneck
        conv5 = DoubleConv3D(self.filters*5)(pool4)

        # R-hand side of UNet
        rsdc6 = ConcatConv3D(self.filters*4)(conv5, conv4)
        conv6 = DoubleConv3D(self.filters*4)(rsdc6)
        ...

        # sigmoid activation
        outputs = Conv3D(1, (1, 1, 1), activation='sigmoid')(conv9)
        return outputs

unet3d = UNet3D()
unet3d.build(Input(shape=[None, None, None, 1]))
unet3d.summary()

Однако вместо вывода слоев и количества параметров, сводка дает

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
Total params: 0
Trainable params: 0
Non-trainable params: 0
_________________________________________________________________

Изначально я полагал, что это была ошибка, из-за которой не вызывался build до вызова итогов, и пытался как явно вызвать функцию, так и добавить InputLayer перед первым слоем свертки, как отмечено в этом ответе, связанном с . Однако ни одно из решений не помогает исправить генерацию сводки на подклассе модели.

1 Ответ

0 голосов
/ 03 июля 2019

Я нашел решение этой проблемы подклассов Модели, посмотрев на следующий пример .Автор должен отдать должное этому репо.

Один из способов конвертировать функционал Keras в подкласс Model - создать и вызвать функцию, которая реплицирует инициализацию модели, например, Model(inputs=[inputs], outputs=[outputs]).Здесь мы делаем это с помощью функции _build.

class UNet3D(Model):
    def __init__(self, **kwargs):

        # Initialize model parameters.
        self.filters = 32
        ...

        # Initialize model.
        self._build(**kwargs)

    def __call__(self, inputs):

        # L-hand side of UNet
        conv1 = DoubleConv3D(self.filters*1)(inputs)
        pool1 = MaxPooling3D()(conv1)
        ...

        # middle bottleneck
        conv5 = DoubleConv3D(self.filters*5)(pool4)

        # R-hand side of UNet
        rsdc6 = ConcatConv3D(self.filters*4)(conv5, conv4)
        conv6 = DoubleConv3D(self.filters*4)(rsdc6)
        ...

        # sigmoid activation
        outputs = Conv3D(1, (1, 1, 1), activation='sigmoid')(conv9)
        return outputs

    def _build(self, **kwargs):
        """
        Replicates Model(inputs=[inputs], outputs=[outputs]) of functional model.
        """
        # Replace with shape=[None, None, None, 1] if input_shape is unknown.
        inputs  = Input(shape=[16, 16, 16, 12])
        outputs = self.__call__(inputs)
        super(UNet3D, self).__init__(name="UNet3D", inputs=inputs, outputs=outputs, **kwargs) 

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