ความรู้เบื้องต้นเกี่ยวกับการไล่ระดับสีและการสร้างความแตกต่างอัตโนมัติ

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

การแยกความแตกต่างและการไล่ระดับสีอัตโนมัติ

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

ในคู่มือนี้ คุณจะสำรวจวิธีการคำนวณการไล่ระดับสีด้วย TensorFlow โดยเฉพาะอย่างยิ่งใน การดำเนินการอย่างกระตือรือร้น

ติดตั้ง

import numpy as np
import matplotlib.pyplot as plt

import tensorflow as tf

การคำนวณการไล่ระดับสี

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

เทปไล่โทนสี

TensorFlow จัดเตรียม tf.GradientTape API สำหรับการแยกความแตกต่างโดยอัตโนมัติ นั่นคือ การคำนวณเกรเดียนต์ของการคำนวณที่เกี่ยวกับอินพุตบางตัว ปกติแล้ว tf.Variable s TensorFlow "บันทึก" การดำเนินการที่เกี่ยวข้องซึ่งดำเนินการภายในบริบทของ tf.GradientTape ลงบน "เทป" จากนั้น TensorFlow จะใช้เทปนั้นเพื่อคำนวณการไล่ระดับของการคำนวณที่ "บันทึกไว้" โดยใช้ โหมด Reverse mode differentiation

นี่เป็นตัวอย่างง่ายๆ:

x = tf.Variable(3.0)

with tf.GradientTape() as tape:
  y = x**2

เมื่อคุณได้บันทึกการดำเนินการบางอย่างแล้ว ให้ใช้ GradientTape.gradient(target, sources) เพื่อคำนวณการไล่ระดับของเป้าหมายบางส่วน (มักจะสูญเสีย) ที่สัมพันธ์กับแหล่งที่มาบางส่วน (มักจะเป็นตัวแปรของโมเดล):

# dy = 2x * dx
dy_dx = tape.gradient(y, x)
dy_dx.numpy()
6.0

ตัวอย่างข้างต้นใช้สเกลาร์ แต่ tf.GradientTape ทำงานได้อย่างง่ายดายบนเทนเซอร์ใดๆ:

w = tf.Variable(tf.random.normal((3, 2)), name='w')
b = tf.Variable(tf.zeros(2, dtype=tf.float32), name='b')
x = [[1., 2., 3.]]

with tf.GradientTape(persistent=True) as tape:
  y = x @ w + b
  loss = tf.reduce_mean(y**2)

เพื่อให้ได้ระดับความ loss ที่สัมพันธ์กับตัวแปรทั้งสอง คุณสามารถส่งผ่านทั้งสองแหล่งไปยังวิธีการ gradient ได้ เทปมีความยืดหยุ่นเกี่ยวกับวิธีการส่งแหล่งที่มา และจะยอมรับการรวมรายการหรือพจนานุกรมที่ซ้อนกัน และส่งคืนโครงสร้างการไล่ระดับสีในลักษณะเดียวกัน (ดู tf.nest )

[dl_dw, dl_db] = tape.gradient(loss, [w, b])

การไล่ระดับสีตามแหล่งที่มาแต่ละแหล่งจะมีรูปทรงของแหล่งกำเนิด:

print(w.shape)
print(dl_dw.shape)
(3, 2)
(3, 2)

นี่คือการคำนวณการไล่ระดับสีอีกครั้ง คราวนี้ผ่านพจนานุกรมของตัวแปร:

my_vars = {
    'w': w,
    'b': b
}

grad = tape.gradient(loss, my_vars)
grad['b']
<tf.Tensor: shape=(2,), dtype=float32, numpy=array([-1.6920902, -3.2363236], dtype=float32)>

การไล่สีตามโมเดล

เป็นเรื่องปกติที่จะรวบรวม tf.Variables ลงใน tf.Module หรือหนึ่งในคลาสย่อย ( layers.Layer , keras.Model ) สำหรับ จุดตรวจสอบ และการ ส่งออก

ในกรณีส่วนใหญ่ คุณจะต้องคำนวณการไล่ระดับสีตามตัวแปรที่ฝึกได้ของแบบจำลอง เนื่องจากคลาสย่อยทั้งหมดของ tf.Module รวมตัวแปรไว้ในคุณสมบัติ Module.trainable_variables คุณจึงสามารถคำนวณการไล่ระดับสีเหล่านี้ได้ในโค้ดสองสามบรรทัด:

layer = tf.keras.layers.Dense(2, activation='relu')
x = tf.constant([[1., 2., 3.]])

with tf.GradientTape() as tape:
  # Forward pass
  y = layer(x)
  loss = tf.reduce_mean(y**2)

# Calculate gradients with respect to every trainable variable
grad = tape.gradient(loss, layer.trainable_variables)
for var, g in zip(layer.trainable_variables, grad):
  print(f'{var.name}, shape: {g.shape}')
dense/kernel:0, shape: (3, 2)
dense/bias:0, shape: (2,)

ควบคุมสิ่งที่ดูเทป

พฤติกรรมเริ่มต้นคือการบันทึกการดำเนินการทั้งหมดหลังจากเข้าถึง tf.Variable ที่ฝึกได้ เหตุผลคือ:

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

ตัวอย่างเช่น สิ่งต่อไปนี้ล้มเหลวในการคำนวณการไล่ระดับสีเนื่องจาก tf.Tensor ไม่ได้ "ดู" โดยค่าเริ่มต้น และ tf.Variable ไม่สามารถฝึกได้:

# A trainable variable
x0 = tf.Variable(3.0, name='x0')
# Not trainable
x1 = tf.Variable(3.0, name='x1', trainable=False)
# Not a Variable: A variable + tensor returns a tensor.
x2 = tf.Variable(2.0, name='x2') + 1.0
# Not a variable
x3 = tf.constant(3.0, name='x3')

with tf.GradientTape() as tape:
  y = (x0**2) + (x1**2) + (x2**2)

grad = tape.gradient(y, [x0, x1, x2, x3])

for g in grad:
  print(g)
tf.Tensor(6.0, shape=(), dtype=float32)
None
None
None

คุณสามารถระบุตัวแปรที่เทปกำลังรับชมได้โดยใช้เมธอด GradientTape.watched_variables :

[var.name for var in tape.watched_variables()]
['x0:0']

tf.GradientTape มีตะขอที่ให้ผู้ใช้ควบคุมสิ่งที่ดูอยู่หรือไม่ดู

ในการบันทึกการไล่ระดับสีเกี่ยวกับ tf.Tensor คุณต้องเรียก GradientTape.watch(x) :