لایه های سفارشی

مشاهده در TensorFlow.org در Google Colab اجرا شود مشاهده منبع در GitHub دانلود دفترچه یادداشت

توصیه می کنیم از tf.keras به عنوان یک API سطح بالا برای ساخت شبکه های عصبی استفاده کنید. گفته می شود، بیشتر API های TensorFlow با اجرای مشتاقانه قابل استفاده هستند.

import tensorflow as tf
print(tf.config.list_physical_devices('GPU'))
[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]

لایه ها: مجموعه های رایج عملیات مفید

بیشتر اوقات هنگام نوشتن کد برای مدل های یادگیری ماشینی، می خواهید در سطح بالاتری از انتزاع عمل کنید تا عملیات فردی و دستکاری متغیرهای منفرد.

بسیاری از مدل‌های یادگیری ماشینی به صورت ترکیب و چیدمان لایه‌های نسبتاً ساده قابل بیان هستند، و TensorFlow هم مجموعه‌ای از لایه‌های رایج و هم راه‌های آسانی را برای شما فراهم می‌کند تا لایه‌های خاص برنامه خود را از ابتدا یا به‌عنوان ترکیب‌بندی بنویسید. لایه های موجود

TensorFlow شامل API کامل Keras در بسته tf.keras است و لایه‌های Keras هنگام ساخت مدل‌های خود بسیار مفید هستند.

# In the tf.keras.layers package, layers are objects. To construct a layer,
# simply construct the object. Most layers take as a first argument the number
# of output dimensions / channels.
layer = tf.keras.layers.Dense(100)
# The number of input dimensions is often unnecessary, as it can be inferred
# the first time the layer is used, but it can be provided if you want to
# specify it manually, which is useful in some complex models.
layer = tf.keras.layers.Dense(10, input_shape=(None, 5))

لیست کامل لایه های از قبل موجود را می توان در مستندات مشاهده کرد. این شامل Dense (یک لایه کاملاً متصل)، Conv2D، LSTM، BatchNormalization، Dropout و بسیاری دیگر است.

# To use a layer, simply call it.
layer(tf.zeros([10, 5]))
<tf.Tensor: shape=(10, 10), dtype=float32, numpy=
array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]], dtype=float32)>
# Layers have many useful methods. For example, you can inspect all variables
# in a layer using `layer.variables` and trainable variables using
# `layer.trainable_variables`. In this case a fully-connected layer
# will have variables for weights and biases.
layer.variables
[<tf.Variable 'dense_1/kernel:0' shape=(5, 10) dtype=float32, numpy=
 array([[-0.4370762 ,  0.6231566 , -0.44082257, -0.48535   ,  0.17860883,
         -0.521853  , -0.45774594, -0.5409817 ,  0.29194772, -0.18690601],
        [ 0.3304953 , -0.27142242, -0.48322448, -0.19328138, -0.14415592,
          0.05973059,  0.56227285,  0.5323917 , -0.4914217 ,  0.62182254],
        [-0.5313885 ,  0.54680306,  0.1632638 , -0.10741419, -0.04727739,
         -0.35414204,  0.07529551, -0.06515282, -0.19732419,  0.25217015],
        [ 0.49743277,  0.31172627,  0.04989761,  0.1200847 ,  0.42642146,
          0.5887727 ,  0.5771937 ,  0.08720696,  0.43024355, -0.17298424],
        [-0.07610255,  0.04131562,  0.3136508 , -0.6197298 ,  0.2331146 ,
          0.04888463, -0.54215366,  0.41208786,  0.27439958,  0.08524591]],
       dtype=float32)>,
 <tf.Variable 'dense_1/bias:0' shape=(10,) dtype=float32, numpy=array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)>]
# The variables are also accessible through nice accessors
layer.kernel, layer.bias
(<tf.Variable 'dense_1/kernel:0' shape=(5, 10) dtype=float32, numpy=
 array([[-0.4370762 ,  0.6231566 , -0.44082257, -0.48535   ,  0.17860883,
         -0.521853  , -0.45774594, -0.5409817 ,  0.29194772, -0.18690601],
        [ 0.3304953 , -0.27142242, -0.48322448, -0.19328138, -0.14415592,
          0.05973059,  0.56227285,  0.5323917 , -0.4914217 ,  0.62182254],
        [-0.5313885 ,  0.54680306,  0.1632638 , -0.10741419, -0.04727739,
         -0.35414204,  0.07529551, -0.06515282, -0.19732419,  0.25217015],
        [ 0.49743277,  0.31172627,  0.04989761,  0.1200847 ,  0.42642146,
          0.5887727 ,  0.5771937 ,  0.08720696,  0.43024355, -0.17298424],
        [-0.07610255,  0.04131562,  0.3136508 , -0.6197298 ,  0.2331146 ,
          0.04888463, -0.54215366,  0.41208786,  0.27439958,  0.08524591]],
       dtype=float32)>,
 <tf.Variable 'dense_1/bias:0' shape=(10,) dtype=float32, numpy=array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)>)

پیاده سازی لایه های سفارشی

بهترین راه برای پیاده سازی لایه خود، گسترش کلاس tf.keras.Layer و پیاده سازی:

  1. __init__ ، که در آن می توانید تمام مقداردهی اولیه مستقل از ورودی را انجام دهید
  2. build ، که در آن شما شکل تانسورهای ورودی را می شناسید و می توانید بقیه مقداردهی اولیه را انجام دهید
  3. call ، جایی که شما محاسبات رو به جلو را انجام می دهید

توجه داشته باشید که برای ایجاد متغیرهای خود لازم نیست تا فراخوانی build صبر کنید، همچنین می توانید آنها را در __init__ ایجاد کنید. با این حال، مزیت ایجاد آنها در build این است که ایجاد متغیر دیرهنگام را بر اساس شکل ورودی هایی که لایه روی آنها کار می کند، امکان پذیر می کند. از طرف دیگر، ایجاد متغیرها در __init__ به این معنی است که اشکال مورد نیاز برای ایجاد متغیرها باید به صراحت مشخص شوند.

class MyDenseLayer(tf.keras.layers.Layer):
  def __init__(self, num_outputs):
    super(MyDenseLayer, self).__init__()
    self.num_outputs = num_outputs

  def build(self, input_shape):
    self.kernel = self.add_weight("kernel",
                                  shape=[int(input_shape[-1]),
                                         self.num_outputs])

  def call(self, inputs):
    return tf.matmul(inputs, self.kernel)

layer = MyDenseLayer(10)
_ = layer(tf.zeros([10, 5])) # Calling the layer `.builds` it.
print([var.name for var in layer.trainable_variables])
['my_dense_layer/kernel:0']

در صورت استفاده از لایه‌های استاندارد در صورت امکان، خواندن و نگهداری کد کلی آسان‌تر است، زیرا سایر خوانندگان با رفتار لایه‌های استاندارد آشنا خواهند بود. اگر می‌خواهید از لایه‌ای استفاده کنید که در tf.keras.layers وجود ندارد، یک مشکل github را در نظر بگیرید یا حتی بهتر از آن، یک درخواست pull برای ما ارسال کنید!

مدل ها: ترکیب لایه ها

بسیاری از چیزهای لایه مانند جالب در مدل های یادگیری ماشین با ترکیب لایه های موجود پیاده سازی می شوند. به عنوان مثال، هر بلوک باقیمانده در یک resnet ترکیبی از کانولوشن ها، نرمال سازی های دسته ای و یک میانبر است. لایه ها را می توان در داخل لایه های دیگر تو در تو قرار داد.

معمولاً زمانی که به روش‌های مدل مانند Model.fit ، Model.evaluate و Model.save نیاز دارید، از keras.Model ارث می‌برید (برای جزئیات به لایه‌ها و مدل‌های سفارشی Keras مراجعه کنید).

یکی دیگر از ویژگی های ارائه شده توسط keras.Model (به جای keras.layers.Layer ) این است که یک keras.Model علاوه بر ردیابی متغیرها، لایه های داخلی خود را نیز ردیابی می کند و بازرسی آنها را آسان تر می کند.

به عنوان مثال در اینجا یک بلوک ResNet وجود دارد:

class ResnetIdentityBlock(tf.keras.Model):
  def __init__(self, kernel_size, filters):
    super(ResnetIdentityBlock, self).__init__(name='')
    filters1, filters2, filters3 = filters

    self.conv2a = tf.keras.layers.Conv2D(filters1, (1, 1))
    self.bn2a = tf.keras.layers.BatchNormalization()

    self.conv2b = tf.keras.layers.Conv2D(filters2, kernel_size, padding='same')
    self.bn2b = tf.keras.layers.BatchNormalization()

    self.conv2c = tf.keras.layers.Conv2D(filters3, (1, 1))
    self.bn2c = tf.keras.layers.BatchNormalization()

  def call(self, input_tensor, training=False):
    x = self.conv2a(input_tensor)
    x = self.bn2a(x, training=training)
    x = tf.nn.relu(x)

    x = self.conv2b(x)
    x = self.bn2b(x, training=training)
    x = tf.nn.relu(x)

    x = self.conv2c(x)
    x = self.bn2c(x, training=training)

    x += input_tensor
    return tf.nn.relu(x)


block = ResnetIdentityBlock(1, [1, 2, 3])
_ = block(tf.zeros([1, 2, 3, 3]))
block.layers
[<keras.layers.convolutional.Conv2D at 0x7fc7e439bf90>,
 <keras.layers.normalization.batch_normalization.BatchNormalization at 0x7fc7dc1e5dd0>,
 <keras.layers.convolutional.Conv2D at 0x7fc7dc1a1cd0>,
 <keras.layers.normalization.batch_normalization.BatchNormalization at 0x7fc7dc12c490>,
 <keras.layers.convolutional.Conv2D at 0x7fc7dc12c8d0>,
 <keras.layers.normalization.batch_normalization.BatchNormalization at 0x7fc7dc12cf50>]
len(block.variables)
18
block.summary()
Model: ""
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d (Conv2D)             multiple                  4         
                                                                 
 batch_normalization (BatchN  multiple                 4         
 ormalization)                                                   
                                                                 
 conv2d_1 (Conv2D)           multiple                  4         
                                                                 
 batch_normalization_1 (Batc  multiple                 8         
 hNormalization)                                                 
                                                                 
 conv2d_2 (Conv2D)           multiple                  9         
                                                                 
 batch_normalization_2 (Batc  multiple                 12        
 hNormalization)                                                 
                                                                 
=================================================================
Total params: 41
Trainable params: 29
Non-trainable params: 12
_________________________________________________________________

با این حال، اغلب اوقات، مدل هایی که لایه های زیادی را تشکیل می دهند، به سادگی یک لایه را پس از دیگری فراخوانی می کنند. این را می توان با کد بسیار کمی با استفاده از tf.keras.Sequential :

my_seq = tf.keras.Sequential([tf.keras.layers.Conv2D(1, (1, 1),
                                                    input_shape=(
                                                        None, None, 3)),
                             tf.keras.layers.BatchNormalization(),
                             tf.keras.layers.Conv2D(2, 1,
                                                    padding='same'),
                             tf.keras.layers.BatchNormalization(),
                             tf.keras.layers.Conv2D(3, (1, 1)),
                             tf.keras.layers.BatchNormalization()])
my_seq(tf.zeros([1, 2, 3, 3]))
<tf.Tensor: shape=(1, 2, 3, 3), dtype=float32, numpy=
array([[[[0., 0., 0.],
         [0., 0., 0.],
         [0., 0., 0.]],

        [[0., 0., 0.],
         [0., 0., 0.],
         [0., 0., 0.]]]], dtype=float32)>
my_seq.summary()
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d_3 (Conv2D)           (None, None, None, 1)     4         
                                                                 
 batch_normalization_3 (Batc  (None, None, None, 1)    4         
 hNormalization)                                                 
                                                                 
 conv2d_4 (Conv2D)           (None, None, None, 2)     4         
                                                                 
 batch_normalization_4 (Batc  (None, None, None, 2)    8         
 hNormalization)                                                 
                                                                 
 conv2d_5 (Conv2D)           (None, None, None, 3)     9         
                                                                 
 batch_normalization_5 (Batc  (None, None, None, 3)    12        
 hNormalization)                                                 
                                                                 
=================================================================
Total params: 41
Trainable params: 29
Non-trainable params: 12
_________________________________________________________________

مراحل بعدی

اکنون می توانید به دفترچه یادداشت قبلی برگردید و مثال رگرسیون خطی را با استفاده از لایه ها و مدل ها برای ساختار بهتر تطبیق دهید.