לולאות אימון בסיסיות

הצג באתר TensorFlow.org הפעל בגוגל קולאב צפה במקור ב-GitHub הורד מחברת

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

TensorFlow כולל גם את tf.Keras API , ממשק API לרשת עצבית ברמה גבוהה המספק הפשטות שימושיות להפחתת ה-boilerplate. עם זאת, במדריך זה תשתמש בשיעורים בסיסיים.

להכין

import tensorflow as tf

import matplotlib.pyplot as plt

colors = plt.rcParams['axes.prop_cycle'].by_key()['color']

פתרון בעיות למידת מכונה

פתרון בעיית למידת מכונה מורכב בדרך כלל מהשלבים הבאים:

  • השג נתוני אימון.
  • הגדירו את הדגם.
  • הגדר פונקציית אובדן.
  • רוץ על נתוני האימון, חישוב הפסד מהערך האידיאלי
  • חשב שיפועים עבור אובדן זה והשתמש באופטימיזציה כדי להתאים את המשתנים כך שיתאימו לנתונים.
  • העריכו את התוצאות שלכם.

למטרות המחשה, במדריך זה תפתחו מודל ליניארי פשוט, \(f(x) = x * W + b\), שיש לו שני משתנים: \(W\) (משקלים) ו- \(b\) (הטיה).

זוהי הבעיות הבסיסיות ביותר של למידת מכונה: בהינתן \(x\) ו- \(y\), נסה למצוא את השיפוע וההיסט של קו באמצעות רגרסיה ליניארית פשוטה .

נתונים

למידה מפוקחת משתמשת בקלט (מסומן בדרך כלל כ- x ) ובפלטים (מסומנים y , הנקראים לעתים קרובות תוויות ). המטרה היא ללמוד מכניסות ויציאות מזווגות כדי שתוכל לחזות את הערך של פלט מקלט.

כל קלט של הנתונים שלך, ב-TensorFlow, מיוצג כמעט תמיד על ידי טנזור, ולעתים קרובות הוא וקטור. באימון מפוקח, התפוקה (או הערך שתרצה לחזות) הוא גם טנסור.

הנה כמה נתונים מסונתזים על ידי הוספת רעש גאוסי (רגיל) לנקודות לאורך קו.

# The actual line
TRUE_W = 3.0
TRUE_B = 2.0

NUM_EXAMPLES = 201

# A vector of random x values
x = tf.linspace(-2,2, NUM_EXAMPLES)
x = tf.cast(x, tf.float32)

def f(x):
  return x * TRUE_W + TRUE_B

# Generate some noise
noise = tf.random.normal(shape=[NUM_EXAMPLES])

# Calculate y
y = f(x) + noise
# Plot all the data
plt.plot(x, y, '.')
plt.show()

png

טנסורים נאספים בדרך כלל בקבוצות , או קבוצות של תשומות ויציאות מוערמות יחד. אצווה יכולה להעניק כמה יתרונות אימון ועובדת היטב עם מאיצים וחישוב וקטורי. בהתחשב בכמה קטן מערך הנתונים הזה, אתה יכול להתייחס לכל מערך הנתונים כאל אצווה אחת.

הגדירו את הדגם

השתמש tf.Variable כדי לייצג את כל המשקלים במודל. tf.Variable מאחסן ערך ומספק אותו בצורת טנזור לפי הצורך. עיין במדריך המשתנים לפרטים נוספים.

השתמש tf.Module כדי לכלול את המשתנים ואת החישוב. אתה יכול להשתמש בכל אובייקט Python, אבל בדרך זו ניתן לשמור אותו בקלות.

כאן, אתה מגדיר גם w וגם b כמשתנים.

class MyModel(tf.Module):
  def __init__(self, **kwargs):
    super().__init__(**kwargs)
    # Initialize the weights to `5.0` and the bias to `0.0`
    # In practice, these should be randomly initialized
    self.w = tf.Variable(5.0)
    self.b = tf.Variable(0.0)

  def __call__(self, x):
    return self.w * x + self.b

model = MyModel()

# List the variables tf.modules's built-in variable aggregation.
print("Variables:", model.variables)

# Verify the model works
assert model(3.0).numpy() == 15.0
Variables: (<tf.Variable 'Variable:0' shape=() dtype=float32, numpy=0.0>, <tf.Variable 'Variable:0' shape=() dtype=float32, numpy=5.0>)
2021-12-08 17:11:44.542944: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.

המשתנים הראשוניים מוגדרים כאן בצורה קבועה, אבל Keras מגיע עם כל אחד ממספר מאתחלים שבהם אתה יכול להשתמש, עם או בלי שאר ה-Keras.

הגדר פונקציית אובדן

פונקציית הפסד מודדת עד כמה התפוקה של מודל עבור קלט נתון תואמת את תפוקת היעד. המטרה היא למזער את ההבדל הזה במהלך האימון. הגדר את הפסד L2 הסטנדרטי, המכונה גם שגיאת "ממוצע בריבוע":

# This computes a single loss value for an entire batch
def loss(target_y, predicted_y):
  return tf.reduce_mean(tf.square(target_y - predicted_y))

לפני אימון המודל, אתה יכול לדמיין את ערך ההפסד על ידי שרטוט תחזיות המודל באדום ונתוני האימון בכחול:

plt.plot(x, y, '.', label="Data")
plt.plot(x, f(x), label="Ground truth")
plt.plot(x, model(x), label="Predictions")
plt.legend()
plt.show()

print("Current loss: %1.6f" % loss(y, model(x)).numpy())

png

Current loss: 10.301712

הגדר לולאת אימון

לולאת האימון מורכבת מביצוע שוב ושוב של שלוש משימות לפי הסדר:

  • שליחת אצווה של תשומות דרך המודל ליצירת פלטים
  • חישוב ההפסד על ידי השוואת התפוקות לפלט (או לתווית)
  • שימוש בקלטת מעבר כדי למצוא את ההדרגות
  • אופטימיזציה של המשתנים עם שיפועים אלה

עבור דוגמה זו, אתה יכול לאמן את המודל באמצעות ירידה בשיפוע .

ישנן גרסאות רבות של סכימת הירידה בשיפוע שנלכדות ב- tf.keras.optimizers . אבל ברוח הבנייה מעקרונות ראשונים, כאן תוכלו ליישם את המתמטיקה הבסיסית בעצמכם בעזרת tf.GradientTape אוטומטית ו- tf.assign_sub ערך (המשלבת tf.assign ו- tf.sub ):

# Given a callable model, inputs, outputs, and a learning rate...
def train(model, x, y, learning_rate):

  with tf.GradientTape() as t:
    # Trainable variables are automatically tracked by GradientTape
    current_loss = loss(y, model(x))

  # Use GradientTape to calculate the gradients with respect to W and b
  dw, db = t.gradient(current_loss, [model.w, model.b])

  # Subtract the gradient scaled by the learning rate
  model.w.assign_sub(learning_rate * dw)
  model.b.assign_sub(learning_rate * db)

לעיון באימונים, אתה יכול לשלוח את אותה אצווה של x ו- y דרך לולאת האימון, ולראות כיצד W ו- b מתפתחים.

model = MyModel()

# Collect the history of W-values and b-values to plot later
weights = []
biases = []
epochs = range(10)

# Define a training loop
def report(model, loss):
  return f"W = {model.w.numpy():1.2f}, b = {model.b.numpy():1.2f}, loss={current_loss:2.5f}"


def training_loop(model, x, y):

  for epoch in epochs:
    # Update the model with the single giant batch
    train(model, x, y, learning_rate=0.1)

    # Track this before I update
    weights.append(model.w.numpy())
    biases.append(model.b.numpy())
    current_loss = loss(y, model(x))

    print(f"Epoch {epoch:2d}:")
    print("    ", report(model, current_loss))

תעשה את האימון

current_loss = loss(y, model(x))

print(f"Starting:")
print("    ", report(model, current_loss))

training_loop(model, x, y)
Starting:
     W = 5.00, b = 0.00, loss=10.30171
Epoch  0:
     W = 4.46, b = 0.40, loss=10.30171
Epoch  1:
     W = 4.06, b = 0.72, loss=10.30171
Epoch  2:
     W = 3.77, b = 0.97, loss=10.30171
Epoch  3:
     W = 3.56, b = 1.18, loss=10.30171
Epoch  4:
     W = 3.40, b = 1.34, loss=10.30171
Epoch  5:
     W = 3.29, b = 1.47, loss=10.30171
Epoch  6:
     W = 3.21, b = 1.58, loss=10.30171
Epoch  7:
     W = 3.15, b = 1.66, loss=10.30171
Epoch  8:
     W = 3.10, b = 1.73, loss=10.30171
Epoch  9:
     W = 3.07, b = 1.78, loss=10.30171

תכנן את התפתחות המשקולות לאורך זמן:

plt.plot(epochs, weights, label='Weights', color=colors[0])
plt.plot(epochs, [TRUE_W] * len(epochs), '--',
         label = "True weight", color=colors[0])

plt.plot(epochs, biases, label='bias', color=colors[1])
plt.plot(epochs, [TRUE_B] * len(epochs), "--",
         label="True bias", color=colors[1])

plt.legend()
plt.show()

png

דמיינו כיצד המודל המאומן מתפקד

plt.plot(x, y, '.', label="Data")
plt.plot(x, f(x), label="Ground truth")
plt.plot(x, model(x), label="Predictions")
plt.legend()
plt.show()

print("Current loss: %1.6f" % loss(model(x), y).numpy())

png

Current loss: 0.897898

אותו פתרון, אבל עם קרס

זה שימושי לעמת את הקוד שלמעלה עם המקביל ב-Keras.

הגדרת המודל נראית בדיוק אותו הדבר אם אתה מחלק תת tf.keras.Model . זכור שדגמי Keras יורשים בסופו של דבר מהמודול.

class MyModelKeras(tf.keras.Model):
  def __init__(self, **kwargs):
    super().__init__(**kwargs)
    # Initialize the weights to `5.0` and the bias to `0.0`
    # In practice, these should be randomly initialized
    self.w = tf.Variable(5.0)
    self.b = tf.Variable(0.0)

  def call(self, x):
    return self.w * x + self.b

keras_model = MyModelKeras()

# Reuse the training loop with a Keras model
training_loop(keras_model, x, y)

# You can also save a checkpoint using Keras's built-in support
keras_model.save_weights("my_checkpoint")
Epoch  0:
     W = 4.46, b = 0.40, loss=10.30171
Epoch  1:
     W = 4.06, b = 0.72, loss=10.30171
Epoch  2:
     W = 3.77, b = 0.97, loss=10.30171
Epoch  3:
     W = 3.56, b = 1.18, loss=10.30171
Epoch  4:
     W = 3.40, b = 1.34, loss=10.30171
Epoch  5:
     W = 3.29, b = 1.47, loss=10.30171
Epoch  6:
     W = 3.21, b = 1.58, loss=10.30171
Epoch  7:
     W = 3.15, b = 1.66, loss=10.30171
Epoch  8:
     W = 3.10, b = 1.73, loss=10.30171
Epoch  9:
     W = 3.07, b = 1.78, loss=10.30171

במקום לכתוב לולאות אימון חדשות בכל פעם שאתה יוצר מודל, אתה יכול להשתמש בתכונות המובנות של Keras כקיצור דרך. זה יכול להיות שימושי כאשר אינך רוצה לכתוב או לנפות באגים בלולאות אימון של Python.

אם תעשה זאת, תצטרך להשתמש ב- model.compile() כדי להגדיר את הפרמטרים, וב- model.fit() כדי לאמן. זה יכול להיות פחות קוד להשתמש ביישומי Keras של אובדן L2 וירידה בשיפוע, שוב כקיצור דרך. ניתן להשתמש בהפסדים ובאופטימיזציית Keras גם מחוץ לפונקציות הנוחות הללו, והדוגמה הקודמת הייתה יכולה להשתמש בהם.

keras_model = MyModelKeras()

# compile sets the training parameters
keras_model.compile(
    # By default, fit() uses tf.function().  You can
    # turn that off for debugging, but it is on now.
    run_eagerly=False,

    # Using a built-in optimizer, configuring as an object
    optimizer=tf.keras.optimizers.SGD(learning_rate=0.1),

    # Keras comes with built-in MSE error
    # However, you could use the loss function
    # defined above
    loss=tf.keras.losses.mean_squared_error,
)

Keras fit מצפה לנתונים באצווה או למערך נתונים שלם כמערך NumPy. מערכי NumPy נחתכים לאצוות וברירת המחדל לגודל אצווה של 32.

במקרה זה, כדי להתאים את ההתנהגות של הלולאה בכתב יד, עליך להעביר את x כאצווה בודדת בגודל 1000.

print(x.shape[0])
keras_model.fit(x, y, epochs=10, batch_size=1000)
201
Epoch 1/10
1/1 [==============================] - 0s 242ms/step - loss: 10.3017
Epoch 2/10
1/1 [==============================] - 0s 3ms/step - loss: 6.3148
Epoch 3/10
1/1 [==============================] - 0s 3ms/step - loss: 4.0341
Epoch 4/10
1/1 [==============================] - 0s 3ms/step - loss: 2.7191
Epoch 5/10
1/1 [==============================] - 0s 3ms/step - loss: 1.9548
Epoch 6/10
1/1 [==============================] - 0s 2ms/step - loss: 1.5068
Epoch 7/10
1/1 [==============================] - 0s 3ms/step - loss: 1.2422
Epoch 8/10
1/1 [==============================] - 0s 2ms/step - loss: 1.0845
Epoch 9/10
1/1 [==============================] - 0s 2ms/step - loss: 0.9899
Epoch 10/10
1/1 [==============================] - 0s 3ms/step - loss: 0.9327
<keras.callbacks.History at 0x7f02ad940050>

שימו לב ש-Keras מדפיס את ההפסד לאחר אימון, לא לפני, כך שההפסד הראשון נראה נמוך יותר, אבל חוץ מזה, זה מראה בעצם את אותם ביצועי אימון.

הצעדים הבאים

במדריך זה, ראית כיצד להשתמש במחלקות הליבה של טנסורים, משתנים, מודולים וקלטת שיפוע כדי לבנות ולהכשיר מודל, ועוד כיצד הרעיונות הללו ממפות ל-Keras.

עם זאת, מדובר בבעיה פשוטה ביותר. להקדמה מעשית יותר, ראה הדרכה מותאמת אישית .

למידע נוסף על שימוש בלולאות אימון מובנות של Keras, עיין במדריך זה . למידע נוסף על לולאות אימון ו-Keras, עיין במדריך זה . לכתיבת לולאות אימון מבוזרות מותאמות אישית, עיין במדריך זה .