طبقات مخصصة

عرض على TensorFlow.org تشغيل في Google Colab عرض المصدر على جيثب تحميل دفتر

نوصي باستخدام tf.keras برمجة تطبيقات عالية المستوى لبناء الشبكات العصبية. ومع ذلك ، فإن معظم واجهات برمجة تطبيقات TensorFlow قابلة للاستخدام مع التنفيذ الجاد.

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

الطبقات: مجموعات شائعة من العمليات المفيدة

في معظم الأوقات ، عند كتابة التعليمات البرمجية لنماذج التعلم الآلي ، تريد العمل بمستوى أعلى من التجريد من العمليات الفردية ومعالجة المتغيرات الفردية.

يمكن التعبير عن العديد من نماذج التعلم الآلي مثل تكوين طبقات بسيطة نسبيًا وتكديسها ، ويوفر TensorFlow مجموعة من العديد من الطبقات الشائعة بالإضافة إلى طرق سهلة لكتابة الطبقات الخاصة بالتطبيق إما من البداية أو كتكوين الطبقات الموجودة.

يتضمن TensorFlow واجهة Keras API الكاملة في حزمة 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 أو إرسال طلب سحب إلينا بشكل أفضل!

النماذج: تكوين الطبقات

يتم تنفيذ العديد من الأشياء الممتعة التي تشبه الطبقة في نماذج التعلم الآلي عن طريق تكوين طبقات موجودة. على سبيل المثال ، كل كتلة متبقية في resnet عبارة عن تكوين تلافيف وتطبيع دفعي واختصار. يمكن أن تتداخل الطبقات داخل طبقات أخرى.

عادةً ما ترث من keras.Model عندما تحتاج إلى طرق النموذج مثل: Model.fit و Model.evaluate و Model.save (انظر طبقات ونماذج 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
_________________________________________________________________

الخطوات التالية

يمكنك الآن الرجوع إلى دفتر الملاحظات السابق وتكييف مثال الانحدار الخطي لاستخدام الطبقات والنماذج لتكون منظمة بشكل أفضل.