שכבות מותאמות אישית

הצג באתר TensorFlow.org הפעל בגוגל קולאב צפה במקור ב-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 או, אפילו יותר טוב, לשלוח לנו בקשת משיכה!

דגמים: חיבור שכבות

הרבה דברים מעניינים דמויי שכבות במודלים של למידת מכונה מיושמים על ידי חיבור שכבות קיימות. לדוגמה, כל בלוק שיורי ב-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
_________________________________________________________________

הצעדים הבאים

כעת אתה יכול לחזור למחברת הקודמת ולהתאים את דוגמה הרגרסיה הליניארית לשימוש בשכבות ובמודלים כדי להיות מובנים טוב יותר.