مشاهده در 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\) (طرفداری).
این ابتدایی ترین مشکلات یادگیری ماشین است: با توجه به \(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()
تانسورها معمولاً به صورت دستهای با هم جمع میشوند ، یا گروههایی از ورودیها و خروجیها روی هم چیده میشوند. دستهبندی میتواند برخی از مزایای آموزشی را به همراه داشته باشد و با شتابدهندهها و محاسبات برداری به خوبی کار میکند. با توجه به اینکه این مجموعه داده چقدر کوچک است، می توانید کل مجموعه داده را به عنوان یک دسته واحد در نظر بگیرید.
مدل را تعریف کنید
از tf.Variable
برای نمایش تمام وزن ها در یک مدل استفاده کنید. یک tf.Variable
یک مقدار را ذخیره می کند و در صورت نیاز آن را به شکل تانسور ارائه می دهد. برای جزئیات بیشتر به راهنمای متغیر مراجعه کنید.
از tf.Module
برای کپسوله کردن متغیرها و محاسبات استفاده کنید. شما می توانید از هر شی پایتون استفاده کنید، اما به این ترتیب می توان آن را به راحتی ذخیره کرد.
در اینجا، شما هم 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())
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()
نحوه عملکرد مدل آموزش دیده را تجسم کنید
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())
Current loss: 0.897898
همان راه حل، اما با Keras
مغایرت کد بالا با معادل آن در 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 به عنوان میانبر استفاده کنید. این می تواند زمانی مفید باشد که نمی خواهید حلقه های آموزشی پایتون را بنویسید یا اشکال زدایی کنید.
اگر این کار را انجام دادید، باید از 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، به این راهنما مراجعه کنید. برای نوشتن حلقه های آموزشی توزیع شده سفارشی، به این راهنما مراجعه کنید.