Xem trên TensorFlow.org | Chạy trong Google Colab | Xem nguồn trên GitHub | Tải xuống sổ ghi chép |
Trong các hướng dẫn trước, bạn đã học về tensor , biến , băng gradient và mô-đun . Trong hướng dẫn này, bạn sẽ lắp tất cả những thứ này lại với nhau để đào tạo các mô hình.
TensorFlow cũng bao gồm API tf.Keras , một API mạng thần kinh cấp cao cung cấp các thông tin tóm tắt hữu ích để giảm bớt các bản viết sẵn. Tuy nhiên, trong hướng dẫn này, bạn sẽ sử dụng các lớp cơ bản.
Thành lập
import tensorflow as tf
import matplotlib.pyplot as plt
colors = plt.rcParams['axes.prop_cycle'].by_key()['color']
Giải quyết các vấn đề về học máy
Giải quyết vấn đề học máy thường bao gồm các bước sau:
- Lấy dữ liệu đào tạo.
- Xác định mô hình.
- Xác định một hàm mất mát.
- Chạy qua dữ liệu đào tạo, tính toán tổn thất từ giá trị lý tưởng
- Tính toán độ dốc cho sự mất mát đó và sử dụng trình tối ưu hóa để điều chỉnh các biến cho phù hợp với dữ liệu.
- Đánh giá kết quả của bạn.
Với mục đích minh họa, trong hướng dẫn này, bạn sẽ phát triển một mô hình tuyến tính đơn giản, \(f(x) = x * W + b\), có hai biến: \(W\) (weights) và \(b\) (bias).
Đây là bài toán cơ bản nhất của máy học: Cho \(x\) và \(y\), cố gắng tìm độ dốc và độ lệch của một đường thông qua hồi quy tuyến tính đơn giản .
Dữ liệu
Học có giám sát sử dụng đầu vào (thường được ký hiệu là x ) và đầu ra (ký hiệu là y , thường được gọi là nhãn ). Mục đích là học từ các đầu vào và đầu ra được ghép nối để bạn có thể dự đoán giá trị của đầu ra từ một đầu vào.
Mỗi đầu vào dữ liệu của bạn, trong TensorFlow, hầu như luôn được biểu thị bằng một tensor và thường là một vectơ. Trong đào tạo có giám sát, đầu ra (hoặc giá trị bạn muốn dự đoán) cũng là một tensor.
Dưới đây là một số dữ liệu được tổng hợp bằng cách thêm nhiễu Gaussian (Bình thường) vào các điểm dọc theo một đường thẳng.
# 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()
Các hàng căng thường được tập hợp lại với nhau theo lô , hoặc các nhóm đầu vào và đầu ra xếp chồng lên nhau. Theo dõi có thể mang lại một số lợi ích đào tạo và hoạt động tốt với máy gia tốc và tính toán vectơ. Với mức độ nhỏ của tập dữ liệu này, bạn có thể coi toàn bộ tập dữ liệu như một lô duy nhất.
Xác định mô hình
Sử dụng tf.Variable
để biểu diễn tất cả các trọng số trong một mô hình. Một tf.Variable
lưu trữ một giá trị và cung cấp giá trị này ở dạng tensor khi cần thiết. Xem hướng dẫn biến để biết thêm chi tiết.
Sử dụng tf.Module
để đóng gói các biến và phép tính. Bạn có thể sử dụng bất kỳ đối tượng Python nào, nhưng bằng cách này, nó có thể được lưu dễ dàng.
Ở đây, bạn xác định cả w và b là các biến.
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.
Các biến ban đầu được đặt ở đây theo cách cố định, nhưng Keras đi kèm với bất kỳ công cụ nào trong số các công cụ sinh học mà bạn có thể sử dụng, có hoặc không có phần còn lại của Keras .
Xác định một hàm mất mát
Hàm tổn thất đo lường mức độ đầu ra của một mô hình đối với một đầu vào nhất định phù hợp với đầu ra mục tiêu. Mục đích là để giảm thiểu sự khác biệt này trong quá trình đào tạo. Xác định tổn thất L2 tiêu chuẩn, còn được gọi là lỗi "bình phương trung bình":
# 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))
Trước khi đào tạo mô hình, bạn có thể hình dung giá trị tổn thất bằng cách vẽ biểu đồ dự đoán của mô hình bằng màu đỏ và dữ liệu đào tạo màu xanh lam:
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
Xác định vòng lặp đào tạo
Vòng lặp đào tạo bao gồm lặp lại ba nhiệm vụ theo thứ tự:
- Gửi một loạt đầu vào thông qua mô hình để tạo ra đầu ra
- Tính toán tổn thất bằng cách so sánh kết quả đầu ra với đầu ra (hoặc nhãn)
- Sử dụng băng gradient để tìm các gradient
- Tối ưu hóa các biến với các gradient đó
Đối với ví dụ này, bạn có thể đào tạo mô hình bằng cách sử dụng gradient descent .
Có nhiều biến thể của lược đồ giảm độ dốc được ghi lại trong tf.keras.optimizers
. Nhưng trên tinh thần xây dựng từ những nguyên tắc đầu tiên, ở đây bạn sẽ tự thực hiện phép toán cơ bản với sự trợ giúp của tf.GradientTape
để phân biệt tự động và tf.assign_sub
để giảm giá trị (kết hợp tf.assign
và 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)
Để xem qua quá trình đào tạo, bạn có thể gửi cùng một lô x và y thông qua vòng lặp đào tạo và xem W
và b
phát triển như thế nào.
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))
Thực hiện đào tạo
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
Vẽ biểu đồ sự phát triển của trọng lượng theo thời gian:
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()
Hình dung cách hoạt động của mô hình được đào tạo
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
Giải pháp tương tự, nhưng với Keras
Sẽ rất hữu ích khi đối chiếu đoạn mã trên với đoạn mã tương đương trong Keras.
Việc xác định mô hình trông giống hệt nhau nếu bạn phân lớp tf.keras.Model
. Hãy nhớ rằng các mô hình Keras cuối cùng kế thừa từ mô-đun.
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
Thay vì viết các vòng huấn luyện mới mỗi khi bạn tạo một mô hình, bạn có thể sử dụng các tính năng tích hợp sẵn của Keras làm lối tắt. Điều này có thể hữu ích khi bạn không muốn viết hoặc gỡ lỗi các vòng huấn luyện Python.
Nếu làm như vậy, bạn sẽ cần sử dụng model.compile()
để đặt các tham số và model.fit()
để huấn luyện. Có thể ít mã hơn để sử dụng các triển khai Keras của mất L2 và giảm độ dốc, một lần nữa như một phím tắt. Keras lỗ và bộ tối ưu hóa cũng có thể được sử dụng bên ngoài các chức năng tiện lợi này, và ví dụ trước có thể đã sử dụng chúng.
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
mong đợi dữ liệu theo lô hoặc một tập dữ liệu hoàn chỉnh dưới dạng mảng NumPy. Mảng NumPy được chia nhỏ thành các lô và mặc định có kích thước lô là 32.
Trong trường hợp này, để phù hợp với hành vi của vòng lặp viết tay, bạn nên chuyển x
vào dưới dạng một lô duy nhất có kích thước 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>
Lưu ý rằng Keras in ra sự mất mát sau khi đào tạo, không phải trước đó, vì vậy tổn thất đầu tiên có vẻ thấp hơn, nhưng về cơ bản điều này cho thấy hiệu suất đào tạo giống nhau.
Bước tiếp theo
Trong hướng dẫn này, bạn đã biết cách sử dụng các lớp cốt lõi của tensor, biến, mô-đun và băng gradient để xây dựng và đào tạo một mô hình cũng như cách những ý tưởng đó ánh xạ với Keras.
Tuy nhiên, đây là một vấn đề cực kỳ đơn giản. Để có phần giới thiệu thiết thực hơn, hãy xem Hướng dẫn đào tạo tùy chỉnh .
Để biết thêm về cách sử dụng các vòng huấn luyện Keras tích hợp, hãy xem hướng dẫn này . Để biết thêm về các vòng huấn luyện và Keras, hãy xem hướng dẫn này . Để viết các vòng huấn luyện phân tán tùy chỉnh, hãy xem hướng dẫn này .