Đào tạo và đánh giá với các phương pháp tích hợp

Xem trên TensorFlow.org Chạy trong Google Colab Xem nguồn trên GitHub Tải xuống sổ ghi chép

Thành lập

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

Giới thiệu

Đây dẫn bìa đào tạo, đánh giá và dự đoán (suy luận) mô hình khi sử dụng built-in API cho đào tạo & xác nhận (như Model.fit() , Model.evaluate()Model.predict() ).

Nếu bạn đang quan tâm đến việc tận dụng fit() trong khi quy định cụ thể chức năng bước đào tạo riêng của bạn, vui lòng xem Tuỳ chỉnh những gì xảy ra trong fit() hướng dẫn .

Nếu bạn đang quan tâm bằng văn bản đào tạo & đánh giá riêng của vòng bạn từ đầu, hãy xem hướng dẫn "viết một vòng lặp đào tạo từ đầu" .

Nói chung, cho dù bạn đang sử dụng các vòng lặp tích hợp sẵn hay tự viết, đào tạo và đánh giá mô hình hoạt động theo cùng một cách trên mọi loại mô hình Keras - Mô hình tuần tự, mô hình được xây dựng bằng API chức năng và mô hình được viết từ đầu qua phân lớp mô hình.

Hướng dẫn này không bao gồm đào tạo phân phối, mà được bao phủ trong của chúng tôi hướng tới đa GPU & đào tạo phân phối .

Tổng quan về API: ví dụ end-to-end đầu tiên

Khi thông qua dữ liệu để được xây dựng trong đào tạo vòng của một người mẫu, bạn có nên sử dụng mảng NumPy (nếu dữ liệu của bạn là nhỏ và phù hợp trong bộ nhớ) hoặc tf.data Dataset đối tượng. Trong vài đoạn tiếp theo, chúng ta sẽ sử dụng tập dữ liệu MNIST dưới dạng mảng NumPy, để trình bày cách sử dụng các trình tối ưu hóa, tổn thất và số liệu.

Hãy xem xét mô hình sau (ở đây, chúng tôi xây dựng với API chức năng, nhưng nó cũng có thể là mô hình Tuần tự hoặc mô hình phân lớp):

inputs = keras.Input(shape=(784,), name="digits")
x = layers.Dense(64, activation="relu", name="dense_1")(inputs)
x = layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = layers.Dense(10, activation="softmax", name="predictions")(x)

model = keras.Model(inputs=inputs, outputs=outputs)

Đây là quy trình làm việc end-to-end điển hình trông như thế nào, bao gồm:

  • Tập huấn
  • Xác thực trên một tập hợp lưu giữ được tạo từ dữ liệu đào tạo ban đầu
  • Đánh giá về dữ liệu thử nghiệm

Chúng tôi sẽ sử dụng dữ liệu MNIST cho ví dụ này.

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()

# Preprocess the data (these are NumPy arrays)
x_train = x_train.reshape(60000, 784).astype("float32") / 255
x_test = x_test.reshape(10000, 784).astype("float32") / 255

y_train = y_train.astype("float32")
y_test = y_test.astype("float32")

# Reserve 10,000 samples for validation
x_val = x_train[-10000:]
y_val = y_train[-10000:]
x_train = x_train[:-10000]
y_train = y_train[:-10000]

Chúng tôi chỉ định cấu hình đào tạo (trình tối ưu hóa, mất mát, số liệu):

model.compile(
    optimizer=keras.optimizers.RMSprop(),  # Optimizer
    # Loss function to minimize
    loss=keras.losses.SparseCategoricalCrossentropy(),
    # List of metrics to monitor
    metrics=[keras.metrics.SparseCategoricalAccuracy()],
)

Chúng tôi gọi fit() , mà sẽ đào tạo các mô hình bằng cách cắt các dữ liệu vào "lô" của kích thước batch_size , và liên tục lặp lại trên toàn bộ dữ liệu cho một số lượng nhất định của epochs .

print("Fit model on training data")
history = model.fit(
    x_train,
    y_train,
    batch_size=64,
    epochs=2,
    # We pass some validation for
    # monitoring validation loss and metrics
    # at the end of each epoch
    validation_data=(x_val, y_val),
)
Fit model on training data
Epoch 1/2
782/782 [==============================] - 3s 3ms/step - loss: 0.3387 - sparse_categorical_accuracy: 0.9050 - val_loss: 0.1957 - val_sparse_categorical_accuracy: 0.9426
Epoch 2/2
782/782 [==============================] - 2s 3ms/step - loss: 0.1543 - sparse_categorical_accuracy: 0.9548 - val_loss: 0.1425 - val_sparse_categorical_accuracy: 0.9593

Các trở history đối tượng nắm giữ một kỷ lục của các giá trị tổn thất và giá trị chỉ số trong đào tạo:

history.history
{'loss': [0.3386789858341217, 0.1543138176202774],
 'sparse_categorical_accuracy': [0.9050400257110596, 0.9548400044441223],
 'val_loss': [0.19569723308086395, 0.14253544807434082],
 'val_sparse_categorical_accuracy': [0.9426000118255615, 0.9592999815940857]}

Chúng tôi đánh giá các mô hình trên dữ liệu thử nghiệm thông qua evaluate() :

# Evaluate the model on the test data using `evaluate`
print("Evaluate on test data")
results = model.evaluate(x_test, y_test, batch_size=128)
print("test loss, test acc:", results)

# Generate predictions (probabilities -- the output of the last layer)
# on new data using `predict`
print("Generate predictions for 3 samples")
predictions = model.predict(x_test[:3])
print("predictions shape:", predictions.shape)
Evaluate on test data
79/79 [==============================] - 0s 2ms/step - loss: 0.1414 - sparse_categorical_accuracy: 0.9569
test loss, test acc: [0.14140386879444122, 0.9569000005722046]
Generate predictions for 3 samples
predictions shape: (3, 10)

Bây giờ, chúng ta hãy xem xét từng phần của quy trình làm việc này một cách chi tiết.

Các compile() phương pháp: chỉ định một mất mát, số liệu, và một ưu

Để đào tạo một mô hình với fit() , bạn cần phải xác định một hàm mất mát, một ưu hoa, và tùy chọn, một số số liệu để giám sát.

Bạn vượt qua những mô hình như các đối số cho các compile() phương pháp:

model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(),
    metrics=[keras.metrics.SparseCategoricalAccuracy()],
)

Các metrics lập luận phải là một danh sách - mô hình của bạn có thể có bất kỳ số lượng số liệu.

Nếu mô hình của bạn có nhiều đầu ra, bạn có thể chỉ định tổn thất và số liệu khác nhau cho từng đầu ra và bạn có thể điều chỉnh mức đóng góp của từng đầu ra vào tổng tổn thất của mô hình. Bạn sẽ tìm thấy thêm chi tiết về vấn đề này trong các dữ liệu Đi qua để nhiều đầu vào, nhiều đầu ra mô hình phần.

Lưu ý rằng nếu bạn hài lòng với cài đặt mặc định, trong nhiều trường hợp, trình tối ưu hóa, mất mát và chỉ số có thể được chỉ định thông qua số nhận dạng chuỗi dưới dạng phím tắt:

model.compile(
    optimizer="rmsprop",
    loss="sparse_categorical_crossentropy",
    metrics=["sparse_categorical_accuracy"],
)

Để sử dụng lại sau này, chúng ta hãy đặt định nghĩa mô hình và bước biên dịch của chúng ta trong các hàm; chúng tôi sẽ gọi chúng nhiều lần qua các ví dụ khác nhau trong hướng dẫn này.

def get_uncompiled_model():
    inputs = keras.Input(shape=(784,), name="digits")
    x = layers.Dense(64, activation="relu", name="dense_1")(inputs)
    x = layers.Dense(64, activation="relu", name="dense_2")(x)
    outputs = layers.Dense(10, activation="softmax", name="predictions")(x)
    model = keras.Model(inputs=inputs, outputs=outputs)
    return model


def get_compiled_model():
    model = get_uncompiled_model()
    model.compile(
        optimizer="rmsprop",
        loss="sparse_categorical_crossentropy",
        metrics=["sparse_categorical_accuracy"],
    )
    return model

Nhiều trình tối ưu hóa, tổn thất và số liệu được tích hợp sẵn có sẵn

Nói chung, bạn sẽ không phải tạo lỗ, số liệu hoặc trình tối ưu hóa của riêng mình từ đầu, vì những gì bạn cần có thể đã là một phần của API Keras:

Trình tối ưu hóa:

  • SGD() (có hoặc không có đà)
  • RMSprop()
  • Adam()
  • Vân vân.

Lỗ vốn:

  • MeanSquaredError()
  • KLDivergence()
  • CosineSimilarity()
  • Vân vân.

Số liệu:

  • AUC()
  • Precision()
  • Recall()
  • Vân vân.

Tổn thất tùy chỉnh

Nếu bạn cần tạo lỗ tùy chỉnh, Keras cung cấp hai cách để thực hiện.

Phương pháp đầu tiên liên quan đến việc tạo ra một chức năng chấp nhận đầu vào y_truey_pred . Ví dụ sau đây cho thấy một hàm mất mát tính toán sai số trung bình bình phương giữa dữ liệu thực và các dự đoán:

def custom_mean_squared_error(y_true, y_pred):
    return tf.math.reduce_mean(tf.square(y_true - y_pred))


model = get_uncompiled_model()
model.compile(optimizer=keras.optimizers.Adam(), loss=custom_mean_squared_error)

# We need to one-hot encode the labels to use MSE
y_train_one_hot = tf.one_hot(y_train, depth=10)
model.fit(x_train, y_train_one_hot, batch_size=64, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 0.0162
<keras.callbacks.History at 0x7ff8881ba250>

Nếu bạn cần một hàm mất mà mất trong các thông số bên cạnh y_truey_pred , bạn có thể phân lớp các tf.keras.losses.Loss lớp và thực hiện hai phương pháp sau đây:

  • __init__(self) : chấp nhận các thông số để vượt qua trong suốt cuộc gọi của chức năng bị mất của bạn
  • call(self, y_true, y_pred) : sử dụng các chỉ tiêu (y_true) và các dự đoán mô hình (y_pred) để tính toán thiệt hại của mô hình

Giả sử bạn muốn sử dụng sai số trung bình bình phương, nhưng với một thuật ngữ được thêm vào sẽ giảm khuyến khích các giá trị dự đoán khác xa 0,5 (chúng tôi giả định rằng các mục tiêu phân loại được mã hóa một lần và nhận các giá trị từ 0 đến 1). Điều này tạo ra động lực để người mẫu không quá tự tin, điều này có thể giúp giảm tình trạng quá mặc (chúng tôi sẽ không biết liệu nó có hoạt động hay không cho đến khi chúng tôi thử!).

Đây là cách bạn sẽ làm điều đó:

class CustomMSE(keras.losses.Loss):
    def __init__(self, regularization_factor=0.1, name="custom_mse"):
        super().__init__(name=name)
        self.regularization_factor = regularization_factor

    def call(self, y_true, y_pred):
        mse = tf.math.reduce_mean(tf.square(y_true - y_pred))
        reg = tf.math.reduce_mean(tf.square(0.5 - y_pred))
        return mse + reg * self.regularization_factor


model = get_uncompiled_model()
model.compile(optimizer=keras.optimizers.Adam(), loss=CustomMSE())

y_train_one_hot = tf.one_hot(y_train, depth=10)
model.fit(x_train, y_train_one_hot, batch_size=64, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 0.0388
<keras.callbacks.History at 0x7ff8882130d0>

Chỉ số tùy chỉnh

Nếu bạn cần một thước đo đó không phải là một phần của API, bạn có thể dễ dàng tạo ra chỉ số tùy chỉnh bởi subclassing tf.keras.metrics.Metric lớp. Bạn sẽ cần thực hiện 4 phương pháp:

  • __init__(self) , trong đó bạn sẽ tạo ra biến trạng thái cho chỉ số của bạn.
  • update_state(self, y_true, y_pred, sample_weight=None) , trong đó sử dụng các chỉ tiêu y_true và các dự đoán mô hình y_pred để cập nhật các biến trạng thái.
  • result(self) , trong đó sử dụng các biến trạng thái để tính toán kết quả cuối cùng.
  • reset_state(self) , mà reinitializes tình trạng của chỉ số.

Cập nhật trạng thái và kết quả tính toán được lưu giữ riêng biệt (trong update_state()result() , tương ứng) bởi vì trong một số trường hợp, kết quả tính toán có thể rất tốn kém và sẽ chỉ được thực hiện theo định kỳ.

Dưới đây là một ví dụ đơn giản cho thấy làm thế nào để thực hiện một CategoricalTruePositives số liệu đếm có bao nhiêu mẫu được phân loại chính xác là thuộc về một lớp học đưa ra:

class CategoricalTruePositives(keras.metrics.Metric):
    def __init__(self, name="categorical_true_positives", **kwargs):
        super(CategoricalTruePositives, self).__init__(name=name, **kwargs)
        self.true_positives = self.add_weight(name="ctp", initializer="zeros")

    def update_state(self, y_true, y_pred, sample_weight=None):
        y_pred = tf.reshape(tf.argmax(y_pred, axis=1), shape=(-1, 1))
        values = tf.cast(y_true, "int32") == tf.cast(y_pred, "int32")
        values = tf.cast(values, "float32")
        if sample_weight is not None:
            sample_weight = tf.cast(sample_weight, "float32")
            values = tf.multiply(values, sample_weight)
        self.true_positives.assign_add(tf.reduce_sum(values))

    def result(self):
        return self.true_positives

    def reset_state(self):
        # The state of the metric will be reset at the start of each epoch.
        self.true_positives.assign(0.0)


model = get_uncompiled_model()
model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(),
    metrics=[CategoricalTruePositives()],
)
model.fit(x_train, y_train, batch_size=64, epochs=3)
Epoch 1/3
782/782 [==============================] - 2s 3ms/step - loss: 0.3404 - categorical_true_positives: 45217.0000
Epoch 2/3
782/782 [==============================] - 2s 3ms/step - loss: 0.1588 - categorical_true_positives: 47606.0000
Epoch 3/3
782/782 [==============================] - 2s 3ms/step - loss: 0.1168 - categorical_true_positives: 48278.0000
<keras.callbacks.History at 0x7ff8880a3610>

Xử lý tổn thất và số liệu không phù hợp với chữ ký chuẩn

Đại đa số thiệt hại và số liệu có thể được tính từ y_truey_pred , nơi y_pred là kết quả của mô hình của bạn - nhưng không phải tất cả trong số họ. Ví dụ, sự mất quy định có thể chỉ yêu cầu kích hoạt một lớp (không có mục tiêu trong trường hợp này) và sự kích hoạt này có thể không phải là đầu ra của mô hình.

Trong trường hợp này, bạn có thể gọi self.add_loss(loss_value) từ bên trong gọi phương thức của một lớp tùy chỉnh. Thiệt hại thêm theo cách này được thêm vào sự mất mát "chính" trong đào tạo (một trong những truyền cho compile() ). Dưới đây là một ví dụ đơn giản bổ sung quy định hoạt động (lưu ý rằng quy định hoạt động được tích hợp sẵn trong tất cả các lớp Keras - lớp này chỉ nhằm mục đích cung cấp một ví dụ cụ thể):

class ActivityRegularizationLayer(layers.Layer):
    def call(self, inputs):
        self.add_loss(tf.reduce_sum(inputs) * 0.1)
        return inputs  # Pass-through layer.


inputs = keras.Input(shape=(784,), name="digits")
x = layers.Dense(64, activation="relu", name="dense_1")(inputs)

# Insert activity regularization as a layer
x = ActivityRegularizationLayer()(x)

x = layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = layers.Dense(10, name="predictions")(x)

model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)

# The displayed loss will be much higher than before
# due to the regularization component.
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 2.4545
<keras.callbacks.History at 0x7ff87c53f310>

Bạn có thể làm tương tự cho đăng nhập giá trị số liệu, sử dụng add_metric() :

class MetricLoggingLayer(layers.Layer):
    def call(self, inputs):
        # The `aggregation` argument defines
        # how to aggregate the per-batch values
        # over each epoch:
        # in this case we simply average them.
        self.add_metric(
            keras.backend.std(inputs), name="std_of_activation", aggregation="mean"
        )
        return inputs  # Pass-through layer.


inputs = keras.Input(shape=(784,), name="digits")
x = layers.Dense(64, activation="relu", name="dense_1")(inputs)

# Insert std logging as a layer.
x = MetricLoggingLayer()(x)

x = layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = layers.Dense(10, name="predictions")(x)

model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 0.3461 - std_of_activation: 0.9929
<keras.callbacks.History at 0x7ff87c3d5bd0>

Trong API chức năng , bạn cũng có thể gọi model.add_loss(loss_tensor) , hoặc model.add_metric(metric_tensor, name, aggregation) .

Đây là một ví dụ đơn giản:

inputs = keras.Input(shape=(784,), name="digits")
x1 = layers.Dense(64, activation="relu", name="dense_1")(inputs)
x2 = layers.Dense(64, activation="relu", name="dense_2")(x1)
outputs = layers.Dense(10, name="predictions")(x2)
model = keras.Model(inputs=inputs, outputs=outputs)

model.add_loss(tf.reduce_sum(x1) * 0.1)

model.add_metric(keras.backend.std(x1), name="std_of_activation", aggregation="mean")

model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 2s 3ms/step - loss: 2.4647 - std_of_activation: 0.0017
<keras.callbacks.History at 0x7ff87c216f90>

Lưu ý rằng khi bạn vượt qua tổn thất qua add_loss() , nó trở nên có thể gọi compile() mà không có một chức năng thua lỗ, kể từ khi mô hình đã có một sự mất mát để giảm thiểu.

Hãy xem xét những điều sau LogisticEndpoint lớp: phải mất như đầu vào mục tiêu & logits, và nó theo dõi một sự mất mát crossentropy qua add_loss() . Nó cũng theo dõi chính xác phân loại qua add_metric() .

class LogisticEndpoint(keras.layers.Layer):
    def __init__(self, name=None):
        super(LogisticEndpoint, self).__init__(name=name)
        self.loss_fn = keras.losses.BinaryCrossentropy(from_logits=True)
        self.accuracy_fn = keras.metrics.BinaryAccuracy()

    def call(self, targets, logits, sample_weights=None):
        # Compute the training-time loss value and add it
        # to the layer using `self.add_loss()`.
        loss = self.loss_fn(targets, logits, sample_weights)
        self.add_loss(loss)

        # Log accuracy as a metric and add it
        # to the layer using `self.add_metric()`.
        acc = self.accuracy_fn(targets, logits, sample_weights)
        self.add_metric(acc, name="accuracy")

        # Return the inference-time prediction tensor (for `.predict()`).
        return tf.nn.softmax(logits)

Bạn có thể sử dụng nó trong một mô hình với hai đầu vào (dữ liệu đầu vào và mục tiêu), biên soạn mà không có một loss đối số, như thế này:

import numpy as np

inputs = keras.Input(shape=(3,), name="inputs")
targets = keras.Input(shape=(10,), name="targets")
logits = keras.layers.Dense(10)(inputs)
predictions = LogisticEndpoint(name="predictions")(logits, targets)

model = keras.Model(inputs=[inputs, targets], outputs=predictions)
model.compile(optimizer="adam")  # No loss argument!

data = {
    "inputs": np.random.random((3, 3)),
    "targets": np.random.random((3, 10)),
}
model.fit(data)
1/1 [==============================] - 0s 414ms/step - loss: 0.9889 - binary_accuracy: 0.0000e+00
<keras.callbacks.History at 0x7ff87c0848d0>

Để biết thêm thông tin về đào tạo mô hình multi-input, hãy xem phần Truyền dữ liệu đến nhiều đầu vào, các mô hình đa đầu ra.

Tự động thiết lập riêng một tập hợp quy trình xác thực

Trong lần đầu tiên dụ end-to-end bạn đã thấy, chúng tôi sử dụng validation_data lập luận để thông qua một tuple của mảng NumPy (x_val, y_val) với mô hình để đánh giá thiệt hại và số liệu xác nhận xác nhận ở phần cuối của mỗi thời đại.

Dưới đây là một lựa chọn khác: lập luận validation_split cho phép bạn tự động một phần dự trữ của dữ liệu huấn luyện của bạn để xác nhận. Giá trị tham số đại diện cho phần của dữ liệu được dành riêng cho các xác nhận, vì vậy nó nên được đặt thành một số cao hơn 0 và nhỏ hơn 1. Ví dụ, validation_split=0.2 có nghĩa là "sử dụng 20% dữ liệu để xác nhận", và validation_split=0.6 có nghĩa là "sử dụng 60% dữ liệu để xác nhận".

Cách xác nhận được tính là bằng cách lấy x ngoái% mẫu của các mảng nhận được fit() cuộc gọi, trước khi bất kỳ xáo trộn.

Lưu ý rằng bạn chỉ có thể sử dụng validation_split khi đào tạo với dữ liệu NumPy.

model = get_compiled_model()
model.fit(x_train, y_train, batch_size=64, validation_split=0.2, epochs=1)
625/625 [==============================] - 2s 3ms/step - loss: 0.3682 - sparse_categorical_accuracy: 0.8957 - val_loss: 0.2276 - val_sparse_categorical_accuracy: 0.9301
<keras.callbacks.History at 0x7ff81c680890>

Đào tạo và đánh giá từ Bộ dữ liệu tf.data

Trong một vài đoạn văn vừa qua, bạn đã nhìn thấy làm thế nào để xử lý các khoản lỗ, số liệu, và tối ưu, và bạn đã nhìn thấy làm thế nào để sử dụng validation_datavalidation_split luận trong fit() , khi dữ liệu của bạn được thông qua như là mảng NumPy.

Hãy để bây giờ hãy nhìn vào trường hợp dữ liệu của bạn đi kèm trong các hình thức của một tf.data.Dataset đối tượng.

Các tf.data API là một tập hợp các tiện ích trong TensorFlow 2.0 để tải và dữ liệu tiền xử lý trong một cách đó là nhanh chóng và khả năng mở rộng.

Đối với một hướng dẫn đầy đủ về việc tạo Datasets , xem tài liệu tf.data .

Bạn có thể vượt qua một Dataset dụ trực tiếp đến các phương pháp fit() , evaluate() , và predict() :

model = get_compiled_model()

# First, let's create a training Dataset instance.
# For the sake of our example, we'll use the same MNIST data as before.
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
# Shuffle and slice the dataset.
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

# Now we get a test dataset.
test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test))
test_dataset = test_dataset.batch(64)

# Since the dataset already takes care of batching,
# we don't pass a `batch_size` argument.
model.fit(train_dataset, epochs=3)

# You can also evaluate or predict on a dataset.
print("Evaluate")
result = model.evaluate(test_dataset)
dict(zip(model.metrics_names, result))
Epoch 1/3
782/782 [==============================] - 2s 3ms/step - loss: 0.3372 - sparse_categorical_accuracy: 0.9047
Epoch 2/3
782/782 [==============================] - 2s 3ms/step - loss: 0.1596 - sparse_categorical_accuracy: 0.9523
Epoch 3/3
782/782 [==============================] - 2s 3ms/step - loss: 0.1171 - sparse_categorical_accuracy: 0.9655
Evaluate
157/157 [==============================] - 0s 2ms/step - loss: 0.1211 - sparse_categorical_accuracy: 0.9648
{'loss': 0.12107347697019577,
 'sparse_categorical_accuracy': 0.9648000001907349}

Lưu ý rằng Tập dữ liệu được đặt lại vào cuối mỗi kỷ nguyên, vì vậy nó có thể được sử dụng lại cho kỷ nguyên tiếp theo.

Nếu bạn muốn chạy chỉ đào tạo về một số cụ thể của lô từ Dataset này, bạn có thể vượt qua steps_per_epoch lập luận, trong đó nêu rõ có bao nhiêu đào tạo bước mô hình nên chạy sử dụng Dataset này trước khi chuyển sang kỷ nguyên tiếp theo.

Nếu bạn làm điều này, tập dữ liệu sẽ không được đặt lại vào cuối mỗi kỷ nguyên, thay vào đó chúng tôi chỉ tiếp tục vẽ các lô tiếp theo. Tập dữ liệu cuối cùng sẽ hết dữ liệu (trừ khi nó là tập dữ liệu lặp lại vô hạn).

model = get_compiled_model()

# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

# Only use the 100 batches per epoch (that's 64 * 100 samples)
model.fit(train_dataset, epochs=3, steps_per_epoch=100)
Epoch 1/3
100/100 [==============================] - 1s 3ms/step - loss: 0.7937 - sparse_categorical_accuracy: 0.7894
Epoch 2/3
100/100 [==============================] - 0s 3ms/step - loss: 0.3699 - sparse_categorical_accuracy: 0.8938
Epoch 3/3
100/100 [==============================] - 0s 3ms/step - loss: 0.3155 - sparse_categorical_accuracy: 0.9061
<keras.callbacks.History at 0x7ff81c587e90>

Sử dụng tập dữ liệu xác thực

Bạn có thể vượt qua một Dataset dụ như validation_data luận trong fit() :

model = get_compiled_model()

# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

# Prepare the validation dataset
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_dataset = val_dataset.batch(64)

model.fit(train_dataset, epochs=1, validation_data=val_dataset)
782/782 [==============================] - 3s 3ms/step - loss: 0.3380 - sparse_categorical_accuracy: 0.9035 - val_loss: 0.2015 - val_sparse_categorical_accuracy: 0.9405
<keras.callbacks.History at 0x7ff81c30e450>

Vào cuối mỗi kỷ nguyên, mô hình sẽ lặp lại tập dữ liệu xác thực và tính toán các chỉ số xác thực và mất xác thực.

Nếu bạn muốn chạy xác nhận chỉ trên một số cụ thể của lô từ tập dữ liệu này, bạn có thể vượt qua validation_steps lập luận, trong đó nêu rõ có bao nhiêu xác nhận các bước mô hình nên chạy với dữ liệu xác nhận trước khi làm gián đoạn xác nhận và chuyển sang kỷ nguyên tiếp theo:

model = get_compiled_model()

# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

# Prepare the validation dataset
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_dataset = val_dataset.batch(64)

model.fit(
    train_dataset,
    epochs=1,
    # Only run validation using the first 10 batches of the dataset
    # using the `validation_steps` argument
    validation_data=val_dataset,
    validation_steps=10,
)
782/782 [==============================] - 3s 3ms/step - loss: 0.3369 - sparse_categorical_accuracy: 0.9036 - val_loss: 0.2953 - val_sparse_categorical_accuracy: 0.9187
<keras.callbacks.History at 0x7ff81c30e310>

Lưu ý rằng tập dữ liệu xác thực sẽ được đặt lại sau mỗi lần sử dụng (để bạn luôn đánh giá trên các mẫu giống nhau từ kỷ nguyên này sang kỷ nguyên khác).

Đối số validation_split (tạo ra một tập người hết từ dữ liệu huấn luyện) không được hỗ trợ khi đào tạo từ Dataset đối tượng, vì tính năng này đòi hỏi khả năng index các mẫu của các tập hợp dữ liệu, đó là không thể ở chung với Dataset API.

Các định dạng đầu vào khác được hỗ trợ

Bên cạnh mảng NumPy, tensors háo hức, và TensorFlow Datasets , nó có thể đào tạo một mô hình Keras sử dụng dataframes Pandas, hoặc từ máy phát điện Python lô sản lượng của dữ liệu & nhãn.

Đặc biệt, keras.utils.Sequence lớp Mời một giao diện đơn giản để xây dựng Python phát dữ liệu được đa xử-aware và có thể được xáo trộn.

Nói chung, chúng tôi khuyên bạn nên sử dụng:

  • Dữ liệu đầu vào NumPy nếu dữ liệu của bạn nhỏ và vừa với bộ nhớ
  • Dataset đối tượng nếu bạn có bộ dữ liệu lớn và bạn cần phải làm đào tạo phân phối
  • Sequence các đối tượng nếu bạn có bộ dữ liệu lớn và bạn cần phải làm rất nhiều tùy chỉnh chế biến Python-side mà không thể được thực hiện trong TensorFlow (ví dụ như nếu bạn dựa vào thư viện bên ngoài để tải dữ liệu hoặc tiền xử lý).

Sử dụng một keras.utils.Sequence đối tượng như là đầu vào

keras.utils.Sequence là một tiện ích mà bạn có thể phân lớp để có được một máy phát điện Python với hai thuộc tính quan trọng:

  • Nó hoạt động tốt với đa xử lý.
  • Nó có thể được xáo trộn (ví dụ như khi đi qua shuffle=Truefit() ).

Một Sequence phải thực hiện hai phương pháp:

  • __getitem__
  • __len__

Phương pháp __getitem__ nên trả lại một lô hoàn chỉnh. Nếu bạn muốn thay đổi dữ liệu của bạn giữa các thời kỳ, bạn có thể thực hiện on_epoch_end .

Đây là một ví dụ nhanh:

from skimage.io import imread
from skimage.transform import resize
import numpy as np

# Here, `filenames` is list of path to the images
# and `labels` are the associated labels.

class CIFAR10Sequence(Sequence):
    def __init__(self, filenames, labels, batch_size):
        self.filenames, self.labels = filenames, labels
        self.batch_size = batch_size

    def __len__(self):
        return int(np.ceil(len(self.filenames) / float(self.batch_size)))

    def __getitem__(self, idx):
        batch_x = self.filenames[idx * self.batch_size:(idx + 1) * self.batch_size]
        batch_y = self.labels[idx * self.batch_size:(idx + 1) * self.batch_size]
        return np.array([
            resize(imread(filename), (200, 200))
               for filename in batch_x]), np.array(batch_y)

sequence = CIFAR10Sequence(filenames, labels, batch_size)
model.fit(sequence, epochs=10)

Sử dụng trọng số mẫu và trọng số lớp

Với cài đặt mặc định, trọng lượng của một mẫu được quyết định bởi tần suất của nó trong tập dữ liệu. Có hai phương pháp để cân dữ liệu, không phụ thuộc vào tần số mẫu:

  • Trọng lượng hạng
  • Trọng lượng mẫu

Trọng lượng hạng

Này được thiết lập bằng cách thông qua một cuốn từ điển với class_weight lập luận để Model.fit() . Từ điển này ánh xạ các chỉ số của lớp với trọng lượng sẽ được sử dụng cho các mẫu thuộc lớp này.

Điều này có thể được sử dụng để cân bằng các lớp mà không cần lấy mẫu lại hoặc để đào tạo một mô hình có tầm quan trọng hơn đối với một lớp cụ thể.

Ví dụ, nếu lớp "0" là một nửa như thể hiện dưới dạng lớp "1" trong dữ liệu của bạn, bạn có thể sử dụng Model.fit(..., class_weight={0: 1., 1: 0.5}) .

Đây là một ví dụ NumPy trong đó chúng tôi sử dụng trọng số lớp hoặc trọng số mẫu để đưa ra tầm quan trọng hơn cho việc phân loại chính xác lớp số 5 (là chữ số "5" trong tập dữ liệu MNIST).

import numpy as np

class_weight = {
    0: 1.0,
    1: 1.0,
    2: 1.0,
    3: 1.0,
    4: 1.0,
    # Set weight "2" for class "5",
    # making this class 2x more important
    5: 2.0,
    6: 1.0,
    7: 1.0,
    8: 1.0,
    9: 1.0,
}

print("Fit with class weight")
model = get_compiled_model()
model.fit(x_train, y_train, class_weight=class_weight, batch_size=64, epochs=1)
Fit with class weight
782/782 [==============================] - 2s 3ms/step - loss: 0.3708 - sparse_categorical_accuracy: 0.9032
<keras.callbacks.History at 0x7ff80c7ddd10>

Trọng lượng mẫu

Để kiểm soát chi tiết hoặc nếu bạn không xây dựng bộ phân loại, bạn có thể sử dụng "trọng số mẫu".

  • Khi đào tạo từ dữ liệu NumPy: Vượt qua sample_weight lập luận để Model.fit() .
  • Khi đào tạo từ tf.data hoặc bất kỳ loại khác của iterator: Năng suất (input_batch, label_batch, sample_weight_batch) tuples.

Mảng "trọng lượng mẫu" là một mảng số chỉ định khối lượng mỗi mẫu trong một lô phải có để tính toán tổng hao hụt. Nó thường được sử dụng trong các bài toán phân loại không cân bằng (ý tưởng là tạo trọng lượng nhiều hơn cho các lớp hiếm thấy).

Khi trọng lượng được sử dụng là những người thân và số không, mảng có thể được sử dụng như một mặt nạ cho hàm tổn thất (hoàn toàn loại bỏ sự đóng góp của các mẫu nhất định để tổng lỗ).

sample_weight = np.ones(shape=(len(y_train),))
sample_weight[y_train == 5] = 2.0

print("Fit with sample weight")
model = get_compiled_model()
model.fit(x_train, y_train, sample_weight=sample_weight, batch_size=64, epochs=1)
Fit with sample weight
782/782 [==============================] - 2s 3ms/step - loss: 0.3806 - sparse_categorical_accuracy: 0.9000
<keras.callbacks.History at 0x7ff80c650350>

Dưới đây là một phù hợp với Dataset dụ:

sample_weight = np.ones(shape=(len(y_train),))
sample_weight[y_train == 5] = 2.0

# Create a Dataset that includes sample weights
# (3rd element in the return tuple).
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train, sample_weight))

# Shuffle and slice the dataset.
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

model = get_compiled_model()
model.fit(train_dataset, epochs=1)
782/782 [==============================] - 3s 3ms/step - loss: 0.3588 - sparse_categorical_accuracy: 0.9070
<keras.callbacks.History at 0x7ff80c51cb50>

Truyền dữ liệu sang các mô hình đa đầu vào, đa đầu ra

Trong ví dụ trước, chúng tôi đã xem xét một mô hình với một đầu vào duy nhất (một tensor hình dạng (764,) ) và một đầu ra duy nhất (một tensor dự đoán hình dạng (10,) ). Nhưng những mô hình có nhiều đầu vào hoặc đầu ra thì sao?

Hãy xem xét các mô hình sau đây, trong đó có một ảnh đầu vào hình dạng (32, 32, 3) (nghĩa của (height, width, channels) ) và một chuỗi thời gian đầu vào của hình dạng (None, 10) (nghĩa của (timesteps, features) ). Mô hình của chúng tôi sẽ có hai kết quả đầu ra được tính từ sự kết hợp của các yếu tố đầu vào: một "điểm" (hình dạng (1,) ) và một phân bố xác suất trên năm lớp (hình dạng (5,) ).

image_input = keras.Input(shape=(32, 32, 3), name="img_input")
timeseries_input = keras.Input(shape=(None, 10), name="ts_input")

x1 = layers.Conv2D(3, 3)(image_input)
x1 = layers.GlobalMaxPooling2D()(x1)

x2 = layers.Conv1D(3, 3)(timeseries_input)
x2 = layers.GlobalMaxPooling1D()(x2)

x = layers.concatenate([x1, x2])

score_output = layers.Dense(1, name="score_output")(x)
class_output = layers.Dense(5, name="class_output")(x)

model = keras.Model(
    inputs=[image_input, timeseries_input], outputs=[score_output, class_output]
)

Hãy vẽ biểu đồ của mô hình này, để bạn có thể thấy rõ chúng ta đang làm gì ở đây (lưu ý rằng các hình thể hiện trong biểu đồ là hình dạng lô, chứ không phải hình dạng theo từng mẫu).

keras.utils.plot_model(model, "multi_input_and_output_model.png", show_shapes=True)

png

Tại thời điểm biên dịch, chúng tôi có thể chỉ định các tổn thất khác nhau cho các đầu ra khác nhau, bằng cách chuyển các hàm tổn thất dưới dạng danh sách:

model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss=[keras.losses.MeanSquaredError(), keras.losses.CategoricalCrossentropy()],
)

Nếu chúng ta chỉ chuyển một hàm tổn thất duy nhất vào mô hình, thì hàm tổn thất tương tự sẽ được áp dụng cho mọi đầu ra (điều này không thích hợp ở đây).

Tương tự như vậy đối với các chỉ số:

model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss=[keras.losses.MeanSquaredError(), keras.losses.CategoricalCrossentropy()],
    metrics=[
        [
            keras.metrics.MeanAbsolutePercentageError(),
            keras.metrics.MeanAbsoluteError(),
        ],
        [keras.metrics.CategoricalAccuracy()],
    ],
)

Vì chúng tôi đã đặt tên cho các lớp đầu ra của mình, chúng tôi cũng có thể chỉ định các số liệu và tổn thất trên mỗi đầu ra thông qua một mệnh lệnh:

model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss={
        "score_output": keras.losses.MeanSquaredError(),
        "class_output": keras.losses.CategoricalCrossentropy(),
    },
    metrics={
        "score_output": [
            keras.metrics.MeanAbsolutePercentageError(),
            keras.metrics.MeanAbsoluteError(),
        ],
        "class_output": [keras.metrics.CategoricalAccuracy()],
    },
)

Chúng tôi khuyên bạn nên sử dụng các tên và mệnh đề rõ ràng nếu bạn có nhiều hơn 2 đầu ra.

Có thể cung cấp cho trọng lượng khác nhau để thiệt hại sản lượng cụ thể khác nhau (ví dụ, người ta có thể muốn vinh các "điểm" mất trong ví dụ của chúng tôi, bằng cách cho 2x tầm quan trọng của việc mất lớp), sử dụng loss_weights luận:

model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss={
        "score_output": keras.losses.MeanSquaredError(),
        "class_output": keras.losses.CategoricalCrossentropy(),
    },
    metrics={
        "score_output": [
            keras.metrics.MeanAbsolutePercentageError(),
            keras.metrics.MeanAbsoluteError(),
        ],
        "class_output": [keras.metrics.CategoricalAccuracy()],
    },
    loss_weights={"score_output": 2.0, "class_output": 1.0},
)

Bạn cũng có thể chọn không tính toán khoản lỗ cho một số đầu ra nhất định, nếu các đầu ra này dành cho dự đoán chứ không phải để đào tạo:

# List loss version
model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss=[None, keras.losses.CategoricalCrossentropy()],
)

# Or dict loss version
model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss={"class_output": keras.losses.CategoricalCrossentropy()},
)

Truyền dữ liệu đến một đa đầu vào hoặc mô hình đa sản lượng trong fit() làm việc trong một cách tương tự như cách xác định một hàm mất mát trong biên dịch: bạn có thể vượt qua danh sách các mảng NumPy (với 1: 1 bản đồ để các kết quả đầu ra đã nhận được một hàm mất ) hoặc dicts lập bản đồ tên đầu ra để mảng NumPy.

model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss=[keras.losses.MeanSquaredError(), keras.losses.CategoricalCrossentropy()],
)

# Generate dummy NumPy data
img_data = np.random.random_sample(size=(100, 32, 32, 3))
ts_data = np.random.random_sample(size=(100, 20, 10))
score_targets = np.random.random_sample(size=(100, 1))
class_targets = np.random.random_sample(size=(100, 5))

# Fit on lists
model.fit([img_data, ts_data], [score_targets, class_targets], batch_size=32, epochs=1)

# Alternatively, fit on dicts
model.fit(
    {"img_input": img_data, "ts_input": ts_data},
    {"score_output": score_targets, "class_output": class_targets},
    batch_size=32,
    epochs=1,
)
4/4 [==============================] - 2s 9ms/step - loss: 5.6917 - score_output_loss: 0.1031 - class_output_loss: 5.5886
4/4 [==============================] - 0s 6ms/step - loss: 4.4108 - score_output_loss: 0.0999 - class_output_loss: 4.3109
<keras.callbacks.History at 0x7ff80c3b4110>

Đây là Dataset trường hợp sử dụng: tương tự như những gì chúng tôi đã làm cho mảng NumPy, các Dataset sẽ trả về một tuple của dicts.

train_dataset = tf.data.Dataset.from_tensor_slices(
    (
        {"img_input": img_data, "ts_input": ts_data},
        {"score_output": score_targets, "class_output": class_targets},
    )
)
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

model.fit(train_dataset, epochs=1)
2/2 [==============================] - 0s 21ms/step - loss: 4.2451 - score_output_loss: 0.0993 - class_output_loss: 4.1458
<keras.callbacks.History at 0x7ff80c3ed450>

Sử dụng các cuộc gọi lại

Callbacks trong Keras là các đối tượng được gọi tại các điểm khác nhau trong quá trình huấn luyện (khi bắt đầu một kỷ nguyên, vào cuối một lô, vào cuối một kỷ nguyên, v.v.). Chúng có thể được sử dụng để thực hiện các hành vi nhất định, chẳng hạn như:

  • Thực hiện xác thực ở các điểm khác nhau trong quá trình đào tạo (ngoài xác thực theo từng kỷ nguyên được tích hợp sẵn)
  • Kiểm tra mô hình theo khoảng thời gian đều đặn hoặc khi nó vượt quá ngưỡng chính xác nhất định
  • Thay đổi tốc độ học tập của mô hình khi việc đào tạo dường như đang ổn định
  • Thực hiện tinh chỉnh các lớp trên cùng khi đào tạo có vẻ ổn định
  • Gửi thông báo qua email hoặc tin nhắn tức thì khi quá trình đào tạo kết thúc hoặc khi vượt quá ngưỡng hiệu suất nhất định
  • Vân vân.

Callbacks có thể được thông qua như là một danh sách cuộc gọi của bạn để fit() :

model = get_compiled_model()

callbacks = [
    keras.callbacks.EarlyStopping(
        # Stop training when `val_loss` is no longer improving
        monitor="val_loss",
        # "no longer improving" being defined as "no better than 1e-2 less"
        min_delta=1e-2,
        # "no longer improving" being further defined as "for at least 2 epochs"
        patience=2,
        verbose=1,
    )
]
model.fit(
    x_train,
    y_train,
    epochs=20,
    batch_size=64,
    callbacks=callbacks,
    validation_split=0.2,
)
Epoch 1/20
625/625 [==============================] - 2s 3ms/step - loss: 0.3725 - sparse_categorical_accuracy: 0.8939 - val_loss: 0.2314 - val_sparse_categorical_accuracy: 0.9321
Epoch 2/20
625/625 [==============================] - 2s 3ms/step - loss: 0.1805 - sparse_categorical_accuracy: 0.9471 - val_loss: 0.2012 - val_sparse_categorical_accuracy: 0.9379
Epoch 3/20
625/625 [==============================] - 2s 3ms/step - loss: 0.1346 - sparse_categorical_accuracy: 0.9603 - val_loss: 0.1651 - val_sparse_categorical_accuracy: 0.9505
Epoch 4/20
625/625 [==============================] - 2s 3ms/step - loss: 0.1065 - sparse_categorical_accuracy: 0.9684 - val_loss: 0.1510 - val_sparse_categorical_accuracy: 0.9571
Epoch 5/20
625/625 [==============================] - 2s 3ms/step - loss: 0.0884 - sparse_categorical_accuracy: 0.9734 - val_loss: 0.1505 - val_sparse_categorical_accuracy: 0.9538
Epoch 6/20
625/625 [==============================] - 2s 3ms/step - loss: 0.0746 - sparse_categorical_accuracy: 0.9778 - val_loss: 0.1508 - val_sparse_categorical_accuracy: 0.9575
Epoch 00006: early stopping
<keras.callbacks.History at 0x7ff80c64cad0>

Nhiều lệnh gọi lại tích hợp sẵn có sẵn

Có nhiều lệnh gọi lại tích hợp sẵn trong Keras, chẳng hạn như:

  • ModelCheckpoint : Định kỳ tiết kiệm mô hình.
  • EarlyStopping : Dừng đào tạo khi đào tạo không còn cải thiện các số liệu xác nhận.
  • TensorBoard : bản ghi mô hình kỳ ghi có thể được hình dung trong TensorBoard (chi tiết trong phần "Hình ảnh").
  • CSVLogger : suối mất và chỉ số dữ liệu vào một tập tin CSV.
  • Vân vân.

Xem các tài liệu hướng dẫn callbacks cho danh sách đầy đủ.

Viết cuộc gọi lại của riêng bạn

Bạn có thể tạo một callback tùy chỉnh bằng cách mở rộng các lớp cơ sở keras.callbacks.Callback . Một callback có quyền truy cập mẫu liên quan của nó thông qua thuộc tính lớp self.model .

Hãy chắc chắn để đọc hướng dẫn đầy đủ để viết callbacks tùy chỉnh .

Dưới đây là một ví dụ đơn giản lưu danh sách các giá trị tổn thất theo lô trong quá trình đào tạo:

class LossHistory(keras.callbacks.Callback):
    def on_train_begin(self, logs):
        self.per_batch_losses = []

    def on_batch_end(self, batch, logs):
        self.per_batch_losses.append(logs.get("loss"))

Các mô hình điểm kiểm tra

Khi bạn đang đào tạo mô hình trên các tập dữ liệu tương đối lớn, điều quan trọng là phải lưu các điểm kiểm tra của mô hình của bạn thường xuyên.

Cách dễ nhất để đạt được điều này là với ModelCheckpoint gọi lại:

model = get_compiled_model()

callbacks = [
    keras.callbacks.ModelCheckpoint(
        # Path where to save the model
        # The two parameters below mean that we will overwrite
        # the current checkpoint if and only if
        # the `val_loss` score has improved.
        # The saved model name will include the current epoch.
        filepath="mymodel_{epoch}",
        save_best_only=True,  # Only save a model if `val_loss` has improved.
        monitor="val_loss",
        verbose=1,
    )
]
model.fit(
    x_train, y_train, epochs=2, batch_size=64, callbacks=callbacks, validation_split=0.2
)
Epoch 1/2
613/625 [============================>.] - ETA: 0s - loss: 0.3693 - sparse_categorical_accuracy: 0.8972
Epoch 00001: val_loss improved from inf to 0.23508, saving model to mymodel_1
2021-11-12 20:11:50.182298: 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.
INFO:tensorflow:Assets written to: mymodel_1/assets
625/625 [==============================] - 3s 4ms/step - loss: 0.3660 - sparse_categorical_accuracy: 0.8979 - val_loss: 0.2351 - val_sparse_categorical_accuracy: 0.9273
Epoch 2/2
620/625 [============================>.] - ETA: 0s - loss: 0.1659 - sparse_categorical_accuracy: 0.9507
Epoch 00002: val_loss improved from 0.23508 to 0.16898, saving model to mymodel_2
INFO:tensorflow:Assets written to: mymodel_2/assets
625/625 [==============================] - 2s 3ms/step - loss: 0.1657 - sparse_categorical_accuracy: 0.9507 - val_loss: 0.1690 - val_sparse_categorical_accuracy: 0.9482
<keras.callbacks.History at 0x7ff8b577cc90>

Các ModelCheckpoint gọi lại có thể được sử dụng để thực hiện các lỗi khoan dung: khả năng đào tạo khởi động lại từ trạng thái lưu cuối cùng của mô hình đào tạo trường hợp bị gián đoạn một cách ngẫu nhiên. Đây là một ví dụ cơ bản:

import os

# Prepare a directory to store all the checkpoints.
checkpoint_dir = "./ckpt"
if not os.path.exists(checkpoint_dir):
    os.makedirs(checkpoint_dir)


def make_or_restore_model():
    # Either restore the latest model, or create a fresh one
    # if there is no checkpoint available.
    checkpoints = [checkpoint_dir + "/" + name for name in os.listdir(checkpoint_dir)]
    if checkpoints:
        latest_checkpoint = max(checkpoints, key=os.path.getctime)
        print("Restoring from", latest_checkpoint)
        return keras.models.load_model(latest_checkpoint)
    print("Creating a new model")
    return get_compiled_model()


model = make_or_restore_model()
callbacks = [
    # This callback saves a SavedModel every 100 batches.
    # We include the training loss in the saved model name.
    keras.callbacks.ModelCheckpoint(
        filepath=checkpoint_dir + "/ckpt-loss={loss:.2f}", save_freq=100
    )
]
model.fit(x_train, y_train, epochs=1, callbacks=callbacks)
Creating a new model
  88/1563 [>.............................] - ETA: 3s - loss: 1.1203 - sparse_categorical_accuracy: 0.6911INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=1.04/assets
 185/1563 [==>...........................] - ETA: 6s - loss: 0.7768 - sparse_categorical_accuracy: 0.7858INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.75/assets
 286/1563 [====>.........................] - ETA: 6s - loss: 0.6382 - sparse_categorical_accuracy: 0.8211INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.63/assets
 383/1563 [======>.......................] - ETA: 6s - loss: 0.5584 - sparse_categorical_accuracy: 0.8433INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.55/assets
 484/1563 [========>.....................] - ETA: 6s - loss: 0.5032 - sparse_categorical_accuracy: 0.8578INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.50/assets
 586/1563 [==========>...................] - ETA: 5s - loss: 0.4644 - sparse_categorical_accuracy: 0.8684INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.46/assets
 685/1563 [============>.................] - ETA: 5s - loss: 0.4356 - sparse_categorical_accuracy: 0.8762INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.43/assets
 783/1563 [==============>...............] - ETA: 5s - loss: 0.4127 - sparse_categorical_accuracy: 0.8825INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.41/assets
 883/1563 [===============>..............] - ETA: 4s - loss: 0.3958 - sparse_categorical_accuracy: 0.8868INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.39/assets
 985/1563 [=================>............] - ETA: 3s - loss: 0.3766 - sparse_categorical_accuracy: 0.8918INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.38/assets
1086/1563 [===================>..........] - ETA: 3s - loss: 0.3624 - sparse_categorical_accuracy: 0.8958INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.36/assets
1184/1563 [=====================>........] - ETA: 2s - loss: 0.3498 - sparse_categorical_accuracy: 0.8994INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.35/assets
1283/1563 [=======================>......] - ETA: 1s - loss: 0.3383 - sparse_categorical_accuracy: 0.9029INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.34/assets
1386/1563 [=========================>....] - ETA: 1s - loss: 0.3265 - sparse_categorical_accuracy: 0.9058INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.33/assets
1485/1563 [===========================>..] - ETA: 0s - loss: 0.3184 - sparse_categorical_accuracy: 0.9081INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.32/assets
1563/1563 [==============================] - 11s 7ms/step - loss: 0.3122 - sparse_categorical_accuracy: 0.9097
<keras.callbacks.History at 0x7ff8b53e1dd0>

Bạn cũng có thể viết lệnh gọi lại của riêng mình để lưu và khôi phục các mô hình.

Để có hướng dẫn đầy đủ về serialization và tiết kiệm, vui lòng xem hướng dẫn để tiết kiệm và serializing Models .

Sử dụng lịch trình tỷ lệ học tập

Mô hình phổ biến khi đào tạo mô hình học sâu là giảm dần việc học khi quá trình đào tạo tiến triển. Điều này thường được gọi là "giảm tốc độ học tập".

Lịch trình phân rã học tập có thể là tĩnh (được cố định trước, như một chức năng của kỷ nguyên hiện tại hoặc chỉ số lô hiện tại) hoặc động (phản ứng với hành vi hiện tại của mô hình, cụ thể là mất xác thực).

Chuyển lịch trình cho trình tối ưu hóa

Bạn có thể dễ dàng sử dụng một lịch trình phân rã tỷ lệ học tĩnh bằng cách thông qua một đối tượng lịch như learning_rate luận trong tối ưu hóa của bạn:

initial_learning_rate = 0.1
lr_schedule = keras.optimizers.schedules.ExponentialDecay(
    initial_learning_rate, decay_steps=100000, decay_rate=0.96, staircase=True
)

optimizer = keras.optimizers.RMSprop(learning_rate=lr_schedule)

Một số lịch trình built-in có sẵn: ExponentialDecay , PiecewiseConstantDecay , PolynomialDecay , và InverseTimeDecay .

Sử dụng lệnh gọi lại để triển khai lịch biểu tốc độ học tập động

Không thể đạt được lịch trình tốc độ học động (ví dụ: giảm tốc độ học tập khi tình trạng mất xác thực không còn được cải thiện) với các đối tượng lịch trình này, vì trình tối ưu hóa không có quyền truy cập vào số liệu xác thực.

Tuy nhiên, các lệnh gọi lại có quyền truy cập vào tất cả các chỉ số, bao gồm cả chỉ số xác thực! Do đó, bạn có thể đạt được mẫu này bằng cách sử dụng lệnh gọi lại để sửa đổi tốc độ học hiện tại trên trình tối ưu hóa. Trong thực tế, điều này thậm chí được xây dựng-in như ReduceLROnPlateau gọi lại.

Hình dung tổn thất và các số liệu trong quá trình đào tạo

Cách tốt nhất để giữ một mắt trên mô hình của bạn trong thời gian đào tạo là sử dụng TensorBoard - một ứng dụng dựa trên trình duyệt mà bạn có thể cài đặt trên server cung cấp cho bạn:

  • Biểu đồ trực tiếp về mất mát và các số liệu để đào tạo và đánh giá
  • (tùy chọn) Hình ảnh hóa biểu đồ của các lần kích hoạt lớp của bạn
  • (tùy chọn) 3D visualizations của không gian nhúng học bằng cách của bạn Embedding lớp

Nếu bạn đã cài đặt TensorFlow bằng pip, bạn sẽ có thể khởi chạy TensorBoard từ dòng lệnh:

tensorboard --logdir=/full_path_to_your_logs

Sử dụng lệnh gọi lại TensorBoard

Cách đơn giản nhất để sử dụng TensorBoard với một mô hình Keras và fit() phương pháp là TensorBoard gọi lại.

Trong trường hợp đơn giản nhất, chỉ cần chỉ định nơi bạn muốn lệnh gọi lại ghi nhật ký và bạn đã sẵn sàng:

keras.callbacks.TensorBoard(
    log_dir="/full_path_to_your_logs",
    histogram_freq=0,  # How often to log histogram visualizations
    embeddings_freq=0,  # How often to log embedding visualizations
    update_freq="epoch",
)  # How often to write logs (default: once per epoch)
<keras.callbacks.TensorBoard at 0x7ff88c8c04d0>

Để biết thêm thông tin, xem tài liệu cho TensorBoard callback .