Xem trên TensorFlow.org | Chạy trong Google Colab | Xem nguồn trên GitHub | Tải xuống sổ ghi chép |
Sổ tay này trình bày cách gỡ lỗi đường dẫn đào tạo khi di chuyển sang TF2. Nó bao gồm các thành phần sau:
- Các bước được đề xuất và các mẫu mã để gỡ lỗi quy trình đào tạo
- Công cụ gỡ lỗi
- Các nguồn liên quan khác
Một giả định là bạn có mã TF1.x và các mô hình được đào tạo để so sánh và bạn muốn xây dựng mô hình TF2 đạt được độ chính xác xác thực tương tự.
Máy tính xách tay này KHÔNG đề cập đến việc gỡ lỗi các vấn đề về hiệu suất đối với tốc độ đào tạo / suy luận hoặc sử dụng bộ nhớ.
Gỡ lỗi quy trình làm việc
Dưới đây là quy trình chung để gỡ lỗi các đường dẫn đào tạo TF2 của bạn. Lưu ý rằng bạn không cần phải làm theo các bước sau theo thứ tự. Bạn cũng có thể sử dụng cách tiếp cận tìm kiếm nhị phân trong đó bạn kiểm tra mô hình ở bước trung gian và thu hẹp phạm vi gỡ lỗi.
Sửa lỗi biên dịch và thời gian chạy
Xác thực chuyển tiếp một lần (trong một hướng dẫn riêng)
Một. Trên một thiết bị CPU
- Xác minh các biến chỉ được tạo một lần
- Kiểm tra số lượng biến, tên và hình dạng phù hợp
- Đặt lại tất cả các biến, kiểm tra sự tương đương về số với tất cả tính ngẫu nhiên bị tắt
- Căn chỉnh việc tạo số ngẫu nhiên, kiểm tra sự tương đương của số trong suy luận
- (Tùy chọn) Các điểm kiểm tra được tải đúng cách và các mô hình TF1.x / TF2 tạo ra đầu ra đồng nhất
b. Trên thiết bị GPU / TPU đơn
C. Với chiến lược đa thiết bị
Xác thực tương đương số đào tạo mô hình trong một vài bước (các mẫu mã có sẵn bên dưới)
Một. Xác thực bước đào tạo duy nhất bằng cách sử dụng dữ liệu nhỏ và cố định trên thiết bị CPU đơn. Cụ thể, hãy kiểm tra sự tương đương về số cho các thành phần sau
- tính toán tổn thất
- số liệu
- tỷ lệ học
- tính toán và cập nhật gradient
b. Kiểm tra thống kê sau khi đào tạo 3 bước trở lên để xác minh các hành vi của trình tối ưu hóa như động lượng, vẫn với dữ liệu cố định trên thiết bị CPU đơn
C. Trên thiết bị GPU / TPU đơn
d. Với các chiến lược đa thiết bị (xem phần giới thiệu về MultiProcessRunner ở dưới cùng)
Thử nghiệm bao trùm từ đầu đến cuối trên tập dữ liệu thực
Một. Kiểm tra hành vi đào tạo với TensorBoard
- sử dụng các trình tối ưu hóa đơn giản, ví dụ như SGD và các chiến lược phân phối đơn giản, ví dụ như
tf.distribute.OneDeviceStrategy
trước - số liệu đào tạo
- số liệu đánh giá
- tìm ra dung sai hợp lý cho tính ngẫu nhiên vốn có là bao nhiêu
b. Kiểm tra tính tương đương với trình tối ưu hóa nâng cao / công cụ lập lịch biểu / phân phối tốc độ học nâng cao
C. Kiểm tra tính tương đương khi sử dụng độ chính xác hỗn hợp
- sử dụng các trình tối ưu hóa đơn giản, ví dụ như SGD và các chiến lược phân phối đơn giản, ví dụ như
Tiêu chuẩn sản phẩm bổ sung
Thành lập
pip uninstall -y -q tensorflow
# Install tf-nightly as the DeterministicRandomTestTool is only available in
# Tensorflow 2.8
pip install -q tf-nightly
Xác thực một lần chuyển tiếp
Xác thực chuyển tiếp một lần, bao gồm cả tải điểm kiểm tra, được đề cập trong một chuyên mục khác.
import sys
import unittest
import numpy as np
import tensorflow as tf
import tensorflow.compat.v1 as v1
Đào tạo mô hình xác nhận tương đương số trong một vài bước
Thiết lập cấu hình mô hình và chuẩn bị một tập dữ liệu giả.
params = {
'input_size': 3,
'num_classes': 3,
'layer_1_size': 2,
'layer_2_size': 2,
'num_train_steps': 100,
'init_lr': 1e-3,
'end_lr': 0.0,
'decay_steps': 1000,
'lr_power': 1.0,
}
# make a small fixed dataset
fake_x = np.ones((2, params['input_size']), dtype=np.float32)
fake_y = np.zeros((2, params['num_classes']), dtype=np.int32)
fake_y[0][0] = 1
fake_y[1][1] = 1
step_num = 3
Xác định mô hình TF1.x.
# Assume there is an existing TF1.x model using estimator API
# Wrap the model_fn to log necessary tensors for result comparison
class SimpleModelWrapper():
def __init__(self):
self.logged_ops = {}
self.logs = {
'step': [],
'lr': [],
'loss': [],
'grads_and_vars': [],
'layer_out': []}
def model_fn(self, features, labels, mode, params):
out_1 = tf.compat.v1.layers.dense(features, units=params['layer_1_size'])
out_2 = tf.compat.v1.layers.dense(out_1, units=params['layer_2_size'])
logits = tf.compat.v1.layers.dense(out_2, units=params['num_classes'])
loss = tf.compat.v1.losses.softmax_cross_entropy(labels, logits)
# skip EstimatorSpec details for prediction and evaluation
if mode == tf.estimator.ModeKeys.PREDICT:
pass
if mode == tf.estimator.ModeKeys.EVAL:
pass
assert mode == tf.estimator.ModeKeys.TRAIN
global_step = tf.compat.v1.train.get_or_create_global_step()
lr = tf.compat.v1.train.polynomial_decay(
learning_rate=params['init_lr'],
global_step=global_step,
decay_steps=params['decay_steps'],
end_learning_rate=params['end_lr'],
power=params['lr_power'])
optmizer = tf.compat.v1.train.GradientDescentOptimizer(lr)
grads_and_vars = optmizer.compute_gradients(
loss=loss,
var_list=graph.get_collection(
tf.compat.v1.GraphKeys.TRAINABLE_VARIABLES))
train_op = optmizer.apply_gradients(
grads_and_vars,
global_step=global_step)
# log tensors
self.logged_ops['step'] = global_step
self.logged_ops['lr'] = lr
self.logged_ops['loss'] = loss
self.logged_ops['grads_and_vars'] = grads_and_vars
self.logged_ops['layer_out'] = {
'layer_1': out_1,
'layer_2': out_2,
'logits': logits}
return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)
def update_logs(self, logs):
for key in logs.keys():
model_tf1.logs[key].append(logs[key])
Lớp v1.keras.utils.DeterministicRandomTestTool
sau đây cung cấp scope()
có thể thực hiện các hoạt động ngẫu nhiên có trạng thái sử dụng cùng một hạt giống trên cả biểu đồ / phiên TF1 và thực thi háo hức,
Công cụ này cung cấp hai chế độ kiểm tra:
-
constant
sử dụng cùng một hạt giống cho mọi hoạt động bất kể nó đã được gọi bao nhiêu lần và, -
num_random_ops
sử dụng số lượng các hoạt động ngẫu nhiên có trạng thái đã quan sát trước đó làm hạt giống hoạt động.
Điều này áp dụng cho cả các phép toán ngẫu nhiên có trạng thái được sử dụng để tạo và khởi tạo các biến và các phép toán ngẫu nhiên có trạng thái được sử dụng trong tính toán (chẳng hạn như cho các lớp bỏ học).
random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
WARNING:tensorflow:From /tmp/ipykernel_26769/2689227634.py:1: The name tf.keras.utils.DeterministicRandomTestTool is deprecated. Please use tf.compat.v1.keras.utils.DeterministicRandomTestTool instead.
Chạy mô hình TF1.x ở chế độ đồ thị. Thu thập số liệu thống kê cho 3 bước đào tạo đầu tiên để so sánh số tương đương.
with random_tool.scope():
graph = tf.Graph()
with graph.as_default(), tf.compat.v1.Session(graph=graph) as sess:
model_tf1 = SimpleModelWrapper()
# build the model
inputs = tf.compat.v1.placeholder(tf.float32, shape=(None, params['input_size']))
labels = tf.compat.v1.placeholder(tf.float32, shape=(None, params['num_classes']))
spec = model_tf1.model_fn(inputs, labels, tf.estimator.ModeKeys.TRAIN, params)
train_op = spec.train_op
sess.run(tf.compat.v1.global_variables_initializer())
for step in range(step_num):
# log everything and update the model for one step
logs, _ = sess.run(
[model_tf1.logged_ops, train_op],
feed_dict={inputs: fake_x, labels: fake_y})
model_tf1.update_logs(logs)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:14: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead. /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/legacy_tf_layers/core.py:261: UserWarning: `layer.apply` is deprecated and will be removed in a future version. Please use `layer.__call__` method instead. return layer.apply(inputs) /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:15: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead. from ipykernel import kernelapp as app /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:16: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead. app.launch_new_instance()
Xác định mô hình TF2.
class SimpleModel(tf.keras.Model):
def __init__(self, params, *args, **kwargs):
super(SimpleModel, self).__init__(*args, **kwargs)
# define the model
self.dense_1 = tf.keras.layers.Dense(params['layer_1_size'])
self.dense_2 = tf.keras.layers.Dense(params['layer_2_size'])
self.out = tf.keras.layers.Dense(params['num_classes'])
learning_rate_fn = tf.keras.optimizers.schedules.PolynomialDecay(
initial_learning_rate=params['init_lr'],
decay_steps=params['decay_steps'],
end_learning_rate=params['end_lr'],
power=params['lr_power'])
self.optimizer = tf.keras.optimizers.SGD(learning_rate_fn)
self.compiled_loss = tf.keras.losses.CategoricalCrossentropy(from_logits=True)
self.logs = {
'lr': [],
'loss': [],
'grads': [],
'weights': [],
'layer_out': []}
def call(self, inputs):
out_1 = self.dense_1(inputs)
out_2 = self.dense_2(out_1)
logits = self.out(out_2)
# log output features for every layer for comparison
layer_wise_out = {
'layer_1': out_1,
'layer_2': out_2,
'logits': logits}
self.logs['layer_out'].append(layer_wise_out)
return logits
def train_step(self, data):
x, y = data
with tf.GradientTape() as tape:
logits = self(x)
loss = self.compiled_loss(y, logits)
grads = tape.gradient(loss, self.trainable_weights)
# log training statistics
step = self.optimizer.iterations.numpy()
self.logs['lr'].append(self.optimizer.learning_rate(step).numpy())
self.logs['loss'].append(loss.numpy())
self.logs['grads'].append(grads)
self.logs['weights'].append(self.trainable_weights)
# update model
self.optimizer.apply_gradients(zip(grads, self.trainable_weights))
return
Chạy mô hình TF2 ở chế độ háo hức. Thu thập số liệu thống kê cho 3 bước đào tạo đầu tiên để so sánh số tương đương.
random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
model_tf2 = SimpleModel(params)
for step in range(step_num):
model_tf2.train_step([fake_x, fake_y])
So sánh sự tương đương về số cho một vài bước đào tạo đầu tiên.
Bạn cũng có thể kiểm tra sổ tay xác thực tính đúng đắn và tương đương số để có lời khuyên bổ sung cho tính tương đương số.
np.testing.assert_allclose(model_tf1.logs['lr'], model_tf2.logs['lr'])
np.testing.assert_allclose(model_tf1.logs['loss'], model_tf2.logs['loss'])
for step in range(step_num):
for name in model_tf1.logs['layer_out'][step]:
np.testing.assert_allclose(
model_tf1.logs['layer_out'][step][name],
model_tf2.logs['layer_out'][step][name])
Bài kiểm tra đơn vị
Có một số loại kiểm thử đơn vị có thể giúp gỡ lỗi mã di chuyển của bạn.
- Xác thực một lần chuyển tiếp
- Đào tạo mô hình xác nhận tương đương số trong một vài bước
- Hiệu suất suy luận điểm chuẩn
- Mô hình được đào tạo đưa ra dự đoán chính xác trên các điểm dữ liệu cố định và đơn giản
Bạn có thể sử dụng @parameterized.parameters
để kiểm tra các mô hình có cấu hình khác nhau. Chi tiết với mẫu mã .
Lưu ý rằng có thể chạy các API phiên và thực thi háo hức trong cùng một trường hợp thử nghiệm. Các đoạn mã dưới đây cho biết cách thực hiện.
import unittest
class TestNumericalEquivalence(unittest.TestCase):
# copied from code samples above
def setup(self):
# record statistics for 100 training steps
step_num = 100
# setup TF 1 model
random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
# run TF1.x code in graph mode with context management
graph = tf.Graph()
with graph.as_default(), tf.compat.v1.Session(graph=graph) as sess:
self.model_tf1 = SimpleModelWrapper()
# build the model
inputs = tf.compat.v1.placeholder(tf.float32, shape=(None, params['input_size']))
labels = tf.compat.v1.placeholder(tf.float32, shape=(None, params['num_classes']))
spec = self.model_tf1.model_fn(inputs, labels, tf.estimator.ModeKeys.TRAIN, params)
train_op = spec.train_op
sess.run(tf.compat.v1.global_variables_initializer())
for step in range(step_num):
# log everything and update the model for one step
logs, _ = sess.run(
[self.model_tf1.logged_ops, train_op],
feed_dict={inputs: fake_x, labels: fake_y})
self.model_tf1.update_logs(logs)
# setup TF2 model
random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
self.model_tf2 = SimpleModel(params)
for step in range(step_num):
self.model_tf2.train_step([fake_x, fake_y])
def test_learning_rate(self):
np.testing.assert_allclose(
self.model_tf1.logs['lr'],
self.model_tf2.logs['lr'])
def test_training_loss(self):
# adopt different tolerance strategies before and after 10 steps
first_n_step = 10
# abosolute difference is limited below 1e-5
# set `equal_nan` to be False to detect potential NaN loss issues
abosolute_tolerance = 1e-5
np.testing.assert_allclose(
actual=self.model_tf1.logs['loss'][:first_n_step],
desired=self.model_tf2.logs['loss'][:first_n_step],
atol=abosolute_tolerance,
equal_nan=False)
# relative difference is limited below 5%
relative_tolerance = 0.05
np.testing.assert_allclose(self.model_tf1.logs['loss'][first_n_step:],
self.model_tf2.logs['loss'][first_n_step:],
rtol=relative_tolerance,
equal_nan=False)
Công cụ gỡ lỗi
tf.print
tf.print so với print / logging.info
- Với các đối số có thể định cấu hình,
tf.print
có thể hiển thị một cách đệ quy một số phần tử đầu tiên và cuối cùng của mỗi kích thước cho các tensors được in. Kiểm tra tài liệu API để biết chi tiết. - Để thực thi nhanh chóng, cả
print
vàtf.print
in giá trị của tensor. Tuy nhiên, quá trìnhprint
có thể liên quan đến việc sao chép từ thiết bị đến máy chủ, điều này có thể làm chậm mã của bạn. - Đối với chế độ biểu đồ bao gồm việc sử dụng bên trong
tf.function
, bạn cần sử dụngtf.print
để in giá trị tensor thực tế.tf.print
được biên dịch thành một op trong biểu đồ, trong khiprint
vàlogging.info
chỉ ghi nhật ký tại thời điểm theo dõi, điều này thường không như bạn muốn. -
tf.print
cũng hỗ trợ in các bộ căng tổng hợp nhưtf.RaggedTensor
vàtf.sparse.SparseTensor
. - Bạn cũng có thể sử dụng lệnh gọi lại để theo dõi các chỉ số và biến. Vui lòng kiểm tra cách sử dụng lệnh gọi lại tùy chỉnh với thuộc tính log và self.model .
tf.print so với in bên trong tf. Chức năng
# `print` prints info of tensor object
# `tf.print` prints the tensor value
@tf.function
def dummy_func(num):
num += 1
print(num)
tf.print(num)
return num
_ = dummy_func(tf.constant([1.0]))
# Output:
# Tensor("add:0", shape=(1,), dtype=float32)
# [2]
Tensor("add:0", shape=(1,), dtype=float32) [2]
tf.distribute.Strategy
- Nếu hàm
tf.function
chứatf.print
được thực thi trên worker, chẳng hạn như khi sử dụngTPUStrategy
hoặcParameterServerStrategy
, bạn cần kiểm tra nhật ký máy chủ worker / tham số để tìm các giá trị được in. - Đối với
print
hoặclogging.info
, nhật ký sẽ được in trên bộ điều phối khi sử dụngParameterServerStrategy
và nhật ký sẽ được in trên STDOUT trên worker0 khi sử dụng TPU.
tf.keras.Model
- Khi sử dụng mô hình API tuần tự và chức năng, nếu bạn muốn in các giá trị, ví dụ: đầu vào mô hình hoặc tính năng trung gian sau một số lớp, bạn có các tùy chọn sau.
- Viết một lớp tùy chỉnh
tf.print
. In các đầu vào. - Bao gồm các đầu ra trung gian mà bạn muốn kiểm tra trong các đầu ra của mô hình.
- Viết một lớp tùy chỉnh
- Các lớp
tf.keras.layers.Lambda
có (de) giới hạn tuần tự hóa. Để tránh các vấn đề về tải điểm kiểm tra, hãy viết một lớp phân lớp tùy chỉnh thay thế. Kiểm tra tài liệu API để biết thêm chi tiết. - Bạn không thể
tf.print
kết quả đầu ra trung gian trongtf.keras.callbacks.LambdaCallback
nếu bạn không có quyền truy cập vào các giá trị thực mà thay vào đó chỉ đến các đối tượng tensor Keras tượng trưng.
Tùy chọn 1: viết một lớp tùy chỉnh
class PrintLayer(tf.keras.layers.Layer):
def call(self, inputs):
tf.print(inputs)
return inputs
def get_model():
inputs = tf.keras.layers.Input(shape=(1,))
out_1 = tf.keras.layers.Dense(4)(inputs)
out_2 = tf.keras.layers.Dense(1)(out_1)
# use custom layer to tf.print intermediate features
out_3 = PrintLayer()(out_2)
model = tf.keras.Model(inputs=inputs, outputs=out_3)
return model
model = get_model()
model.compile(optimizer="adam", loss="mse")
model.fit([1, 2, 3], [0.0, 0.0, 1.0])
[[-0.327884018] [-0.109294668] [-0.218589336]] 1/1 [==============================] - 0s 280ms/step - loss: 0.6077 <keras.callbacks.History at 0x7f63d46bf190>
Tùy chọn 2: bao gồm các đầu ra trung gian mà bạn muốn kiểm tra trong các đầu ra của mô hình.
Lưu ý rằng trong trường hợp đó, bạn có thể cần một số tùy chỉnh để sử dụng Model.fit
.
def get_model():
inputs = tf.keras.layers.Input(shape=(1,))
out_1 = tf.keras.layers.Dense(4)(inputs)
out_2 = tf.keras.layers.Dense(1)(out_1)
# include intermediate values in model outputs
model = tf.keras.Model(
inputs=inputs,
outputs={
'inputs': inputs,
'out_1': out_1,
'out_2': out_2})
return model
pdb
Bạn có thể sử dụng pdb cả trong terminal và Colab để kiểm tra các giá trị trung gian để gỡ lỗi.
Trực quan hóa đồ thị với TensorBoard
Bạn có thể kiểm tra đồ thị TensorFlow với TensorBoard . TensorBoard cũng được hỗ trợ trên colab . TensorBoard là một công cụ tuyệt vời để trực quan hóa các bản tóm tắt. Bạn có thể sử dụng nó để so sánh tốc độ học tập, trọng số mô hình, thang độ dốc, số liệu đào tạo / xác thực hoặc thậm chí mô hình kết quả trung gian giữa mô hình TF1.x và mô hình TF2 đã di chuyển thông qua quá trình đào tạo và xem các giá trị có giống như mong đợi hay không.
TensorFlow Profiler
TensorFlow Profiler có thể giúp bạn hình dung tiến trình thực thi trên GPU / TPU. Bạn có thể xem Colab Demo này để biết cách sử dụng cơ bản của nó.
MultiProcessRunner
MultiProcessRunner là một công cụ hữu ích khi gỡ lỗi với MultiWorkerMirroredStrategy và ParameterServerStrategy. Bạn có thể xem ví dụ cụ thể này để biết cách sử dụng của nó.
Cụ thể đối với các trường hợp của hai chiến lược này, bạn nên 1) không chỉ có các bài kiểm tra đơn vị để bao quát luồng của chúng, 2) mà còn cố gắng tạo lại các lỗi bằng cách sử dụng nó trong bài kiểm tra đơn vị để tránh khởi chạy công việc được phân phối thực sự mỗi khi họ cố gắng một sửa chữa.