ลูปการฝึกขั้นพื้นฐาน

ดูบน TensorFlow.org ทำงานใน Google Colab ดูแหล่งที่มาบน GitHub ดาวน์โหลดโน๊ตบุ๊ค

ในคู่มือก่อนหน้านี้ คุณได้เรียนรู้เกี่ยวกับ เท นเซอร์ ตัวแปร เทปเกรเดียนต์ และ โมดูล ในคู่มือนี้ คุณจะประกอบสิ่งเหล่านี้เข้าด้วยกันเพื่อฝึกโมเดล

TensorFlow ยังรวม tf.Keras API ซึ่งเป็น API เครือข่ายประสาทเทียมระดับสูงที่ให้นามธรรมที่เป็นประโยชน์เพื่อลดต้นแบบ อย่างไรก็ตาม ในคู่มือนี้ คุณจะใช้คลาสพื้นฐาน

ติดตั้ง

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\) (bias)

นี่เป็นปัญหาพื้นฐานที่สุดของแมชชีนเลิร์นนิง: จาก \(x\) และ \(y\)ให้ลองค้นหาความชันและออฟเซ็ตของเส้นโดย ใช้การถดถอยเชิงเส้นอย่างง่าย

ข้อมูล

การเรียนรู้ภายใต้การดูแลใช้ อินพุต (ปกติจะแสดงเป็น x ) และ เอาต์พุต (ระบุ y มักเรียกว่า labels ) เป้าหมายคือการเรียนรู้จากอินพุตและเอาต์พุตที่จับคู่กัน เพื่อให้คุณสามารถคาดการณ์มูลค่าของเอาต์พุตจากอินพุตได้

ข้อมูลที่ป้อนเข้าแต่ละครั้งใน 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

การเปรียบเทียบโค้ดด้านบนกับโค้ดที่เทียบเท่ากันใน Keras นั้นมีประโยชน์

การกำหนดโมเดลจะเหมือนกันทุกประการหากคุณ subclass 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
ตัวยึดตำแหน่ง22

แทนที่จะเขียนลูปการฝึกใหม่ในแต่ละครั้งที่คุณสร้างแบบจำลอง คุณสามารถใช้คุณสมบัติในตัวของ 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 โปรดดู คู่มือ นี้ สำหรับการเขียนลูปการฝึกแบบกระจายแบบกำหนดเอง โปรดดู คู่มือ นี้