为什么使用SavedModel进行训练要比使用子类Transformer的检查点进行训练慢呢?

时间:2020-07-24 02:39:31

标签: python tensorflow machine-learning keras

我正在尝试使用savedModel格式,因为我想使用Tensorflow JS部署模型,但是当我使用saveModel生成预测时,它比将检查点加载到预先存在的模型中大约慢20倍(这就是我的意思)。在测试期间进行。) 在此处加载检查点:

model = Transformer(num_layers=settings.num_layers,
                    d_model=settings.embed_dim,
                    num_heads=settings.num_heads,
                    dff=settings.dense_layer_units,
                    vocab_size=settings.vocab_size,
                    pe_input=settings.seq_len)
learning_rate = CustomSchedule(settings.embed_dim)
optimizer = tf.keras.optimizers.Adam(learning_rate, beta_1=0.9, beta_2=0.98, epsilon=1e-9)
ckpt = tf.train.Checkpoint(transformer=model, optimizer=optimizer)
ckpt_manager = tf.train.CheckpointManager(ckpt, settings.checkpoint_dir, max_to_keep=5)

if ckpt_manager.latest_checkpoint:
    ckpt.restore(ckpt_manager.latest_checkpoint)  # since we'll load the optimizer as well
    print('Latest checkpoint restored.')

并将输入传递给模型:

predictions, weights = model([data, False, look_ahead_mask])

vs。 savedModel:

model = tf.keras.models.load_model('Models/All/test', compile=False)

并传递输入:

@tf.function(input_signature=[tf.TensorSpec([1, None], tf.int32),
                                      tf.TensorSpec([], dtype=tf.bool),
                                      tf.TensorSpec([None, None], tf.float32)])
def model_predict(d, train, mask):
    return model([d, train, mask])  # , dec_mask])

predictions, weights = model_predict([data, False, look_ahead_mask])

我都在GPU上运行,并且我确实尝试了以第一种方式将输入的数据传递给saveModel,但是由于重新跟踪,这使得速度甚至变慢了。

这是模型的完整代码(其中许多内容摘自代码注释中提到的TensorFlow教程。)

import numpy as np
import tensorflow as tf


# from 'Transformer model for language understanding' https://www.tensorflow.org/tutorials/text/transformer
def get_angles(pos, i, d_model):
    angle_rates = 1 / np.power(10000, (2 * (i//2)) / np.float32(d_model))
    return pos * angle_rates


def positional_encoding(position, d_model):
    angle_rads = get_angles(np.arange(position)[:, np.newaxis],
                            np.arange(d_model)[np.newaxis, :],
                            d_model)

    # apply sin to even indices in the array; 2i
    angle_rads[:, 0::2] = np.sin(angle_rads[:, 0::2])

    # apply cos to odd indices in the array; 2i+1
    angle_rads[:, 1::2] = np.cos(angle_rads[:, 1::2])

    pos_encoding = angle_rads[np.newaxis, ...]

    return tf.cast(pos_encoding, dtype=tf.float32)


def create_padding_mask(seq):
    seq = tf.cast(tf.math.equal(seq, 0), tf.float32)

    # add extra dimensions to add the padding
    # to the attention logits.
    return seq[:, tf.newaxis, tf.newaxis, :]  # (batch_size, 1, 1, seq_len)


def create_look_ahead_mask(size):
    mask = 1 - tf.linalg.band_part(tf.ones((size, size)), -1, 0)
    return mask  # (seq_len, seq_len)


def scaled_dot_product_attention(q, k, v, mask):
    """Calculate the attention weights.
    q, k, v must have matching leading dimensions.
    k, v must have matching penultimate dimension, i.e.: seq_len_k = seq_len_v.
    The mask has different shapes depending on its type(padding or look ahead)
    but it must be broadcastable for addition.

    Args:
      q: query shape == (..., seq_len_q, depth)
      k: key shape == (..., seq_len_k, depth)
      v: value shape == (..., seq_len_v, depth_v)
      mask: Float tensor with shape broadcastable
            to (..., seq_len_q, seq_len_k). Defaults to None.

    Returns:
      output, attention_weights
    """

    matmul_qk = tf.matmul(q, k, transpose_b=True)  # (..., seq_len_q, seq_len_k)

    # scale matmul_qk
    dk = tf.cast(tf.shape(k)[-1], tf.float32)
    scaled_attention_logits = matmul_qk / tf.math.sqrt(dk)

    # add the mask to the scaled tensor.
    if mask is not None:
        scaled_attention_logits += (mask * -1e9)

    # softmax is normalized on the last axis (seq_len_k) so that the scores
    # add up to 1.
    attention_weights = tf.nn.softmax(scaled_attention_logits, axis=-1)  # (..., seq_len_q, seq_len_k)

    output = tf.matmul(attention_weights, v)  # (..., seq_len_q, depth_v)

    return output, attention_weights


def print_out(q, k, v):
    temp_out, temp_attn = scaled_dot_product_attention(
        q, k, v, None)
    print('Attention weights are:')
    print(temp_attn)
    print('Output is:')
    print(temp_out)


class MultiHeadAttention(tf.keras.layers.Layer):
    def __init__(self, d_model, num_heads):
        super(MultiHeadAttention, self).__init__()
        self.num_heads = num_heads
        self.d_model = d_model

        assert d_model % self.num_heads == 0

        self.depth = d_model // self.num_heads

        self.wq = tf.keras.layers.Dense(d_model)
        self.wk = tf.keras.layers.Dense(d_model)
        self.wv = tf.keras.layers.Dense(d_model)

        self.dense = tf.keras.layers.Dense(d_model)

    def split_heads(self, x, batch_size):
        """Split the last dimension into (num_heads, depth).
        Transpose the result such that the shape is (batch_size, num_heads, seq_len, depth)
        """
        x = tf.reshape(x, (batch_size, -1, self.num_heads, self.depth))
        return tf.transpose(x, perm=[0, 2, 1, 3])

    def call(self, v, k, q, mask):
        batch_size = tf.shape(q)[0]

        q = self.wq(q)  # (batch_size, seq_len, d_model)
        k = self.wk(k)  # (batch_size, seq_len, d_model)
        v = self.wv(v)  # (batch_size, seq_len, d_model)

        q = self.split_heads(q, batch_size)  # (batch_size, num_heads, seq_len_q, depth)
        k = self.split_heads(k, batch_size)  # (batch_size, num_heads, seq_len_k, depth)
        v = self.split_heads(v, batch_size)  # (batch_size, num_heads, seq_len_v, depth)

        # scaled_attention.shape == (batch_size, num_heads, seq_len_q, depth)
        # attention_weights.shape == (batch_size, num_heads, seq_len_q, seq_len_k)
        scaled_attention, attention_weights = scaled_dot_product_attention(
            q, k, v, mask)

        scaled_attention = tf.transpose(scaled_attention,
                                        perm=[0, 2, 1, 3])  # (batch_size, seq_len_q, num_heads, depth)

        concat_attention = tf.reshape(scaled_attention,
                                      (batch_size, -1, self.d_model))  # (batch_size, seq_len_q, d_model)

        output = self.dense(concat_attention)  # (batch_size, seq_len_q, d_model)

        return output, attention_weights


def point_wise_feed_forward_network(d_model, dff):
    return tf.keras.Sequential([
        tf.keras.layers.Dense(dff, activation='relu'),  # (batch_size, seq_len, dff)
        tf.keras.layers.Dense(d_model)  # (batch_size, seq_len, d_model)
    ])


class DecoderLayer(tf.keras.layers.Layer):
    def __init__(self, d_model, num_heads, dff, rate=0.3):
        super(DecoderLayer, self).__init__()

        self.mha1 = MultiHeadAttention(d_model, num_heads)
        self.mha2 = MultiHeadAttention(d_model, num_heads)

        self.ffn = point_wise_feed_forward_network(d_model, dff)

        self.layernorm1 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
        self.layernorm2 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
        self.layernorm3 = tf.keras.layers.LayerNormalization(epsilon=1e-6)

        self.dropout1 = tf.keras.layers.Dropout(rate)
        self.dropout2 = tf.keras.layers.Dropout(rate)
        self.dropout3 = tf.keras.layers.Dropout(rate)

    def call(self, x, training, look_ahead_mask):  # , padding_mask):
        # enc_output.shape == (batch_size, input_seq_len, d_model)

        attn1, attn_weights_block1 = self.mha1(x, x, x, look_ahead_mask)  # (batch_size, target_seq_len, d_model)
        attn1 = self.dropout1(attn1, training=training)
        out1 = self.layernorm1(attn1 + x)

        # why two MHAs? Later models (e.g. GPT-2) only use one.
        # attn2, attn_weights_block2 = self.mha2(
        #     enc_output, enc_output, out1, padding_mask)  # (batch_size, target_seq_len, d_model)
        # attn2 = self.dropout2(attn2, training=training)
        # out2 = self.layernorm2(attn2 + out1)  # (batch_size, target_seq_len, d_model)

        # maybe size down and then up again with multiple ffn layers
        ffn_output = self.ffn(out1)  # (batch_size, target_seq_len, d_model) # was out2
        ffn_output = self.dropout3(ffn_output, training=training)
        out3 = self.layernorm3(ffn_output + out1)  # (batch_size, target_seq_len, d_model)

        return out3, attn_weights_block1  # , attn_weights_block2


class Decoder(tf.keras.layers.Layer):
    def __init__(self, num_layers, d_model, num_heads, dff, target_vocab_size,
                 maximum_position_encoding, rate=0.3):
        super(Decoder, self).__init__()

        self.d_model = d_model
        self.num_layers = num_layers

        self.embedding = tf.keras.layers.Embedding(target_vocab_size, d_model)
        self.pos_encoding = positional_encoding(maximum_position_encoding, d_model)

        self.dec_layers = [DecoderLayer(d_model, num_heads, dff, rate)
                           for _ in range(num_layers)]
        self.dropout = tf.keras.layers.Dropout(rate)

    def call(self, x, training, look_ahead_mask):  # , padding_mask):
        seq_len = tf.shape(x)[1]
        attention_weights = {}

        x = self.embedding(x)  # (batch_size, target_seq_len, d_model)
        x *= tf.math.sqrt(tf.cast(self.d_model, tf.float32))
        x += self.pos_encoding[:, :seq_len, :]

        x = self.dropout(x, training=training)

        for i in range(self.num_layers):
            x, block1 = self.dec_layers[i](x, training, look_ahead_mask)  # , padding_mask)

            attention_weights['decoder_layer{}_block1'.format(i + 1)] = block1

        # x.shape == (batch_size, target_seq_len, d_model)
        return x, attention_weights


class Transformer(tf.keras.Model):
    def __init__(self, num_layers, d_model, num_heads, dff, vocab_size, pe_input, rate=0.1):
        super(Transformer, self).__init__()

        self.decoder = Decoder(num_layers, d_model, num_heads, dff, vocab_size, pe_input, rate)

        self.final_layer = tf.keras.layers.Dense(vocab_size)

    def call(self, inputs):
        inp, training, look_ahead_mask = inputs  # , dec_padding_mask = inputs
        # dec_output.shape == (batch_size, tar_seq_len, d_model)
        dec_output, attention_weights = self.decoder(inp, training, look_ahead_mask)  # , dec_padding_mask)

        final_output = self.final_layer(dec_output)  # (batch_size, tar_seq_len, target_vocab_size)

        return final_output, attention_weights


def create_masks(inp):

    # Used in the 2nd attention block in the decoder.
    # This padding mask is used to mask the encoder outputs.
    dec_padding_mask = create_padding_mask(inp)

    # Used in the 1st attention block in the decoder.
    # It is used to pad and mask future tokens in the input received by
    # the decoder.
    look_ahead_mask = create_look_ahead_mask(tf.shape(inp)[1])

    return look_ahead_mask, dec_padding_mask

非常感谢,祝您有愉快的一天!

如果有任何相关性,尝试保存模型时会收到警告:

WARNING: Logging before flag parsing goes to stderr.
W0723 19:37:52.691118 19792 save_impl.py:76] Skipping full serialization of Keras layer <self_attention.MultiHeadAttention object at 0x0000021D137D24C8>, because it is not built.
W0723 19:37:52.764919 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.normalization.LayerNormalization object at 0x0000021D13AAC848>, because it is not built.
W0723 19:37:52.766914 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dropout object at 0x0000021D13AB7A08>, because it is not built.
W0723 19:37:52.774865 19792 save_impl.py:76] Skipping full serialization of Keras layer <self_attention.MultiHeadAttention object at 0x0000021D13AC1A48>, because it is not built.
W0723 19:37:52.846703 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.normalization.LayerNormalization object at 0x0000021D13BE1688>, because it is not built.
W0723 19:37:52.848691 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dropout object at 0x0000021D13BE78C8>, because it is not built.
W0723 19:37:52.855677 19792 save_impl.py:76] Skipping full serialization of Keras layer <self_attention.MultiHeadAttention object at 0x0000021D13BF3948>, because it is not built.
W0723 19:37:52.928455 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.normalization.LayerNormalization object at 0x0000021D13C034C8>, because it is not built.
W0723 19:37:52.929453 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dropout object at 0x0000021D13C086C8>, because it is not built.
W0723 19:37:52.936461 19792 save_impl.py:76] Skipping full serialization of Keras layer <self_attention.MultiHeadAttention object at 0x0000021D13C13788>, because it is not built.
W0723 19:37:53.075063 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.normalization.LayerNormalization object at 0x0000021D13C64288>, because it is not built.
W0723 19:37:53.076060 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dropout object at 0x0000021D13C694C8>, because it is not built.
W0723 19:37:53.084039 19792 save_impl.py:76] Skipping full serialization of Keras layer <self_attention.MultiHeadAttention object at 0x0000021D13C76548>, because it is not built.
W0723 19:37:53.169809 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.normalization.LayerNormalization object at 0x0000021D13C86148>, because it is not built.
W0723 19:37:53.171804 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dropout object at 0x0000021D13C8B388>, because it is not built.
W0723 19:37:53.179784 19792 save_impl.py:76] Skipping full serialization of Keras layer <self_attention.MultiHeadAttention object at 0x0000021D13C964C8>, because it is not built.
W0723 19:37:53.273533 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.normalization.LayerNormalization object at 0x0000021D13CAA148>, because it is not built.
W0723 19:37:53.274530 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dropout object at 0x0000021D13CAD388>, because it is not built.
2020-07-23 19:37:55.664396: W tensorflow/python/util/util.cc:329] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
W0723 19:37:55.827702 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D137D3248>, because it is not built.
W0723 19:37:55.827702 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D137D67C8>, because it is not built.
W0723 19:37:55.827702 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D137D6E08>, because it is not built.
W0723 19:37:55.827702 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13AA3508>, because it is not built.
W0723 19:37:55.828699 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13AC1EC8>, because it is not built.
W0723 19:37:55.828699 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13AC66C8>, because it is not built.
W0723 19:37:55.828699 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13AC6D48>, because it is not built.
W0723 19:37:55.828699 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13ACB448>, because it is not built.
W0723 19:37:55.829697 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13BF3E48>, because it is not built.
W0723 19:37:55.829697 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13BF7648>, because it is not built.
W0723 19:37:55.829697 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13BF7CC8>, because it is not built.
W0723 19:37:55.829697 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13BFB3C8>, because it is not built.
W0723 19:37:55.830694 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13C13C48>, because it is not built.
W0723 19:37:55.830694 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13C18408>, because it is not built.
W0723 19:37:55.830694 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13C18AC8>, because it is not built.
W0723 19:37:55.831692 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13C1B188>, because it is not built.
W0723 19:37:55.831692 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13C76A08>, because it is not built.
W0723 19:37:55.832690 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13C79208>, because it is not built.
W0723 19:37:55.832690 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13C79888>, because it is not built.
W0723 19:37:55.832690 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13C79F48>, because it is not built.
W0723 19:37:55.833687 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13C96988>, because it is not built.
W0723 19:37:55.833687 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13C9B188>, because it is not built.
W0723 19:37:55.833687 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13C9B848>, because it is not built.
W0723 19:37:55.833687 19792 save_impl.py:76] Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000021D13C9BEC8>, because it is not built.
W0723 19:38:00.007525 19792 deprecation.py:506] From C:\Python37\lib\site-packages\tensorflow\python\ops\resource_variable_ops.py:1817: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.

关于节省资产,我在其他人的日志中也没有看到。不知道这是怎么回事。

0 个答案:

没有答案