簡體   English   中英

實現子類 model 和損失 function 作為層

[英]Implementation subclass model and loss function as a layer

我想用一些輸入實現一個子類 model。 首先你會看到我的損失層。

class CTCLayer(layers.Layer):
    '''
    Implementation of loss layer. 

    Attributes
    ----------
    name : str
    Name of the last layer.

    Methods
    -------
    
    call(y_true, y_pred)

    '''
    def __init__(self, name:str=None):
        super().__init__(name=name)
        self.loss_fn = keras.backend.ctc_batch_cost

    def call(self, y_true, y_pred):
        
        # Compute the training-time loss value and add it
        # to the layer using `self.add_loss()`.
        batch_len = tf.cast(tf.shape(y_true)[0], dtype="int64")
        input_length = tf.cast(tf.shape(y_pred)[1], dtype="int64")
        label_length = tf.cast(tf.shape(y_true)[1], dtype="int64")

        input_length = input_length * tf.ones(shape=(batch_len, 1), dtype="int64")
        label_length = label_length * tf.ones(shape=(batch_len, 1), dtype="int64")

        loss = self.loss_fn(y_true, y_pred, input_length, label_length)
        self.add_loss(loss)

        # At test time, just return the computed predictions
        return y_pred

我的損失是一層model。 我的 output 來自我的損失

class ConvBlock(layers.Layer):
    '''
    Convolution block has Cov2D and Maxpooling2D.

    Attributes
    ----------
    n_filter : int
    Number of filters of Conv2D.
    activation : str
    The activation we use in Conv2D.
    kernel_initializer : str
    Name of mathematic distribution of input weights.

    Methods
    -------
    
    call(inputs)

    '''
    def __init__(self, n_filter:int, activation:str, kernel_initializer:str):
        super(ConvBlock, self).__init__()
        self.conv2d = Conv2D(n_filter, (3, 3), activation=activation,
                             kernel_initializer=kernel_initializer,
                             padding="same")
        
        self.maxpool = MaxPooling2D()
    
    def call(self, inputs):
        x = self.conv2d(inputs)
        x = self.maxpool(x)
        return x


class RNNBlock(layers.Layer):
    '''
    RNN block has 2 LSTM layer.

    Attributes
    ----------
    unit_rnn_1 : int
    Number of units of first LSTM layer.
    drop_rnn_1 : float
    Rate of dropout hyperparameters in first LSTM.
    unit_rnn_2 : int
    Number of units of second LSTM layer.
    drop_rnn_2 : float
    Rate of dropout hyperparameters in second LSTM.

    Methods
    -------
    
    call(inputs)

    '''
    def __init__(self, unit_rnn_1:int, drop_rnn_1:float, unit_rnn_2:int, drop_rnn_2:float):
        super(RNNBlock, self).__init__()
        self.rnn_1 = Bidirectional(LSTM(unit_rnn_1, return_sequences=True, dropout=drop_rnn_1))
        self.rnn_2 = Bidirectional(LSTM(unit_rnn_2, return_sequences=True, dropout=drop_rnn_2))
    
    def call(self, inputs):
        x = self.rnn_1(inputs)
        x = self.rnn_2(x)
        return x


class OCRModel(Model):
    '''
    Implementation Model for OCR problem.
    In OCR we have 2 inputs and we have CTCLayer in last layer.

    Attributes
    ----------
    block_1 : int
    act : str
    init_kernel : str
    block_2 : int
    img_width : int
    img_height : int
    unit_1 : int 
    drop : float
    unit_rnn_1 : int
    drop_rnn_1 : float 
    unit_rnn_2 : int,
    drop_rnn_2 : float
    char_to_num : object

    Methods
    -------
    
    call(inputs)
    '''

    def __init__(self, block_1:int=32, act:str='relu', init_kernel:str='he_normal',
                 block_2:int=64, img_width:int=200, img_height:int=50, unit_1:int=64, 
                 drop:float=0.2, unit_rnn_1:int=128, drop_rnn_1:float=0.25, 
                 unit_rnn_2:int=64, drop_rnn_2:float=0.25, char_to_num:object=None):
        super(OCRModel, self).__init__()

        # CNNs
        self.convb1 = ConvBlock(n_filter=block_1, activation=act, kernel_initializer=init_kernel)
        self.convb2 = ConvBlock(n_filter=block_2, activation=act, kernel_initializer=init_kernel)

        # Factor by which the image is going to be downsampled
        # by the convolutional blocks. We will be using two
        # convolution blocks and each block will have
        # a pooling layer which downsample the features by a factor of 2.
        # Total downsampling factor would be 4.
        down_sampling = 4

        self.new_shape = ((img_width // down_sampling), (img_height // down_sampling) * block_2)
        self.reshape = Reshape(target_shape=self.new_shape)
        self.dense1 = Dense(units=unit_1, activation=act)
        self.drop = Dropout(rate=drop)
        #RNNs
        self.rnn = RNNBlock(unit_rnn_1=unit_rnn_1, drop_rnn_1=drop_rnn_1, unit_rnn_2=unit_rnn_2, drop_rnn_2=drop_rnn_2)
        # Output layer
        self.dense2 = Dense(units = len(char_to_num.get_vocabulary()) + 1, activation="softmax", name='dense2')
        # # CTC Loss
        self.ctc = CTCLayer()

    def call(self, inputs):
        x = self.convb1(inputs[0])
        x = self.convb2(x)
        x = self.reshape(x)
        x = self.dense1(x)
        x = self.drop(x)
        x = self.rnn(x)
        x = self.dense2(x)
        output = self.ctc(inputs, x)
        return output

這是我的 model,帶有一些 conv 塊、RNN 塊和像 CTC 損失這樣的損失層。

img_width = 200
img_height = 50

# inputs
img_input = Input(shape=(img_width, img_height, 1), name='image')
label_input = Input(shape=(None, ), name='label')

# hidden layers
model = OCRModel(char_to_num=char_to_num)

# output
output = model([img_input, label_input])

model = Model(inputs=[img_input, label_input], outputs = output)
model.compile(optimizer='adam')

使用亞當優化器編譯 model。

# Get the prediction model by extracting layers till the output layer
prediction_model = keras.models.Model(
    model.get_layer(name="image").input, model.get_layer(name="dense_2").output
)
prediction_model.summary()

我想在 model 中使用 dense_2 層,但我無法訪問我的 OCR model 中的“dense_2”層。 我的錯誤是:ValueError:沒有這樣的層:dense_2。 現有層有:['image', 'label', 'ocr_model']。

您不能直接訪問內部 model OCRModel 內的層。 但是,您可以為 model 命名,並從中訪問圖層:

model = OCRModel()
model._name = "my_model"
...
prediction_model = keras.models.Model(
    model.get_layer(name="image").input,
    model.get_layer(name="my_model").get_layer(name="dense_2").output
)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM