บันทึกวันที่! Google I / O ส่งคืนวันที่ 18-20 พฤษภาคม ลงทะเบียนตอนนี้
หน้านี้ได้รับการแปลโดย Cloud Translation API
Switch to English

การฝึกอบรมและการประเมินผลด้วยวิธีการในตัว

ดูใน TensorFlow.org เรียกใช้ใน Google Colab ดูแหล่งที่มาบน GitHub ดาวน์โหลดสมุดบันทึก

ติดตั้ง

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

บทนำ

คู่มือนี้ครอบคลุมแบบจำลองการฝึกอบรมการประเมินผลและการคาดคะเน (การอนุมาน) เมื่อใช้ API ในตัวสำหรับการฝึกอบรมและการตรวจสอบความถูกต้อง (เช่น Model.fit() , Model.evaluate() และ Model.predict() )

หากคุณสนใจที่จะใช้ประโยชน์จากความ fit() ในขณะที่ระบุฟังก์ชันขั้นตอนการฝึกของคุณเองโปรดดูคู่มือการ ปรับแต่งสิ่งที่เกิดขึ้นอย่าง fit()

หากคุณสนใจที่จะเขียนลูปการฝึกอบรมและการประเมินผลของคุณเองตั้งแต่เริ่มต้นโปรดดูคู่มือ "การเขียนลูปการฝึกอบรมตั้งแต่เริ่มต้น"

โดยทั่วไปไม่ว่าคุณจะใช้ลูปในตัวหรือเขียนแบบของคุณเองการฝึกอบรมและการประเมินแบบจำลองจะทำงานในลักษณะเดียวกันอย่างเคร่งครัดในรูปแบบ Keras ทุกประเภท - โมเดลต่อเนื่องแบบจำลองที่สร้างขึ้นด้วย Functional API และแบบจำลองที่เขียนขึ้นเอง คลาสย่อยของโมเดล

คู่มือนี้ไม่ครอบคลุมถึงการฝึกอบรมแบบกระจายซึ่งครอบคลุมอยู่ใน คู่มือ ของเรา เกี่ยวกับการฝึกอบรมแบบ multi-GPU และแบบกระจาย

ภาพรวม API: ตัวอย่างแรกจากต้นทางถึงปลายทาง

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

ลองพิจารณาโมเดลต่อไปนี้ (ที่นี่เราสร้างด้วย Functional API แต่อาจเป็นโมเดลลำดับหรือโมเดลคลาสย่อยก็ได้เช่นกัน):

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)

นี่คือลักษณะของขั้นตอนการทำงานแบบ end-to-end โดยทั่วไปประกอบด้วย:

  • การฝึกอบรม
  • การตรวจสอบความถูกต้องของชุดการระงับที่สร้างขึ้นจากข้อมูลการฝึกอบรมเดิม
  • การประเมินข้อมูลการทดสอบ

เราจะใช้ข้อมูล MNIST สำหรับตัวอย่างนี้

(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]
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 0s 0us/step

เราระบุการกำหนดค่าการฝึกอบรม (เครื่องมือเพิ่มประสิทธิภาพการสูญเสียตัวชี้วัด):

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

ที่เราเรียกว่า fit() ซึ่งจะฝึกรูปแบบโดยการหั่นข้อมูลลงใน "แบทช์" ขนาด batch_size และซ้ำ ๆ วนมากกว่าชุดข้อมูลทั้งหมดสำหรับจำนวนที่กำหนดของ 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.5769 - sparse_categorical_accuracy: 0.8386 - val_loss: 0.1833 - val_sparse_categorical_accuracy: 0.9464
Epoch 2/2
782/782 [==============================] - 2s 2ms/step - loss: 0.1621 - sparse_categorical_accuracy: 0.9518 - val_loss: 0.1467 - val_sparse_categorical_accuracy: 0.9579

ออบเจ็กต์ history ส่งคืนเก็บบันทึกค่าการสูญเสียและค่าเมตริกระหว่างการฝึกอบรม:

history.history
{'loss': [0.3323673903942108, 0.15159013867378235],
 'sparse_categorical_accuracy': [0.9050800204277039, 0.9542400240898132],
 'val_loss': [0.18328842520713806, 0.14667865633964539],
 'val_sparse_categorical_accuracy': [0.946399986743927, 0.9578999876976013]}

เราประเมินแบบจำลองบนข้อมูลการทดสอบผ่านการ 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.1449 - sparse_categorical_accuracy: 0.9539
test loss, test acc: [0.14493884146213531, 0.9538999795913696]
Generate predictions for 3 samples
predictions shape: (3, 10)

ตอนนี้เรามาดูรายละเอียดของเวิร์กโฟลว์แต่ละชิ้นกัน

วิธีการ compile() : การระบุการสูญเสียเมตริกและเครื่องมือเพิ่มประสิทธิภาพ

ในการฝึกโมเดลด้วย fit() คุณต้องระบุฟังก์ชันการสูญเสียเครื่องมือเพิ่มประสิทธิภาพและเมตริกบางอย่างที่จะตรวจสอบ

คุณส่งผ่านสิ่งเหล่านี้ไปยังโมเดลเป็นอาร์กิวเมนต์ไปยังเมธอด compile() :

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

อาร์กิวเมนต์ metrics ควรเป็นรายการ - โมเดลของคุณสามารถมีเมตริกกี่ตัวก็ได้

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

โปรดทราบว่าหากคุณพอใจกับการตั้งค่าเริ่มต้นในหลาย ๆ กรณีตัวเพิ่มประสิทธิภาพการสูญเสียและเมตริกสามารถระบุผ่านตัวระบุสตริงเป็นทางลัดได้:

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

เพื่อนำมาใช้ใหม่ในภายหลังให้ใส่นิยามโมเดลของเราและคอมไพล์ขั้นตอนในฟังก์ชัน เราจะเรียกพวกเขาหลาย ๆ ครั้งตามตัวอย่างต่างๆในคู่มือนี้

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

มีเครื่องมือเพิ่มประสิทธิภาพการสูญเสียและเมตริกในตัวมากมาย

โดยทั่วไปคุณไม่จำเป็นต้องสร้างการสูญเสียเมตริกหรือเครื่องมือเพิ่มประสิทธิภาพของคุณเองตั้งแต่ต้นเพราะสิ่งที่คุณต้องการนั้นน่าจะเป็นส่วนหนึ่งของ Keras API อยู่แล้ว:

เครื่องมือเพิ่มประสิทธิภาพ:

  • SGD() (มีหรือไม่มีโมเมนตัม)
  • RMSprop()
  • Adam()
  • เป็นต้น

การสูญเสีย:

  • MeanSquaredError()
  • KLDivergence()
  • CosineSimilarity()
  • เป็นต้น

เมตริก:

  • AUC()
  • Precision()
  • Recall()
  • เป็นต้น

การสูญเสียที่กำหนดเอง

หากคุณต้องการสร้างการสูญเสียที่กำหนดเอง Keras มีสองวิธีในการทำเช่นนั้น

วิธีแรกเกี่ยวข้องกับการสร้างฟังก์ชันที่รับอินพุต y_true และ y_pred ตัวอย่างต่อไปนี้แสดงฟังก์ชันการสูญเสียที่คำนวณค่าเฉลี่ยกำลังสองข้อผิดพลาดระหว่างข้อมูลจริงและการคาดคะเน:

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 [==============================] - 1s 1ms/step - loss: 0.0272
<tensorflow.python.keras.callbacks.History at 0x7fb6b01c09e8>

หากคุณต้องการฟังก์ชันการสูญเสียที่รับพารามิเตอร์ข้าง y_true และ y_pred คุณสามารถย่อยคลาส tf.keras.losses.Loss และใช้สองวิธีต่อไปนี้:

  • __init__(self) : ยอมรับพารามิเตอร์ที่จะส่งผ่านระหว่างการเรียกใช้ฟังก์ชันการสูญเสียของคุณ
  • call(self, y_true, y_pred) : ใช้เป้าหมาย (y_true) และการคาดคะเนแบบจำลอง (y_pred) เพื่อคำนวณการสูญเสียของโมเดล

สมมติว่าคุณต้องการใช้ค่าเฉลี่ยข้อผิดพลาดกำลังสอง แต่มีคำที่เพิ่มเข้ามาซึ่งจะยกเลิกการกระตุ้นค่าการคาดการณ์ที่อยู่ห่างจาก 0.5 (เราถือว่าเป้าหมายเชิงหมวดหมู่มีการเข้ารหัสเพียงจุดเดียวและรับค่าระหว่าง 0 ถึง 1) สิ่งนี้สร้างแรงจูงใจให้นางแบบไม่มั่นใจจนเกินไปซึ่งอาจช่วยลดการฟิตติ้งมากเกินไป (เราไม่รู้ว่าจะได้ผลหรือไม่จนกว่าเราจะลอง!)

นี่คือวิธีที่คุณจะทำ:

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.0489
<tensorflow.python.keras.callbacks.History at 0x7fb6b00725f8>

เมตริกที่กำหนดเอง

หากคุณต้องการเมตริกที่ไม่ได้เป็นส่วนหนึ่งของ API คุณสามารถสร้างเมตริกที่กำหนดเองได้อย่างง่ายดายโดยใช้คลาสย่อย tf.keras.metrics.Metric คุณจะต้องใช้ 4 วิธี:

  • __init__(self) ซึ่งคุณจะสร้างตัวแปรสถานะสำหรับเมตริกของคุณ
  • update_state(self, y_true, y_pred, sample_weight=None) ซึ่งใช้เป้าหมาย y_true และการคาดคะเนแบบจำลอง y_pred เพื่ออัปเดตตัวแปรสถานะ
  • result(self) ซึ่งใช้ตัวแปรสถานะเพื่อคำนวณผลลัพธ์สุดท้าย
  • reset_states(self) ซึ่งทำให้สถานะของเมตริกเริ่มต้นใหม่

การอัปเดตสถานะและการคำนวณผลลัพธ์จะแยกจากกัน (ใน update_state() และ result() ตามลำดับ) เนื่องจากในบางกรณีการคำนวณผลลัพธ์อาจมีราคาแพงมากและจะดำเนินการเป็นระยะ ๆ เท่านั้น

ต่อไปนี้เป็นตัวอย่างง่ายๆที่แสดงวิธีการใช้ตัวชี้วัดการจัด CategoricalTruePositives ที่จะนับจำนวนตัวอย่างที่ถูกจัดประเภทอย่างถูกต้องว่าเป็นของคลาสที่กำหนด:

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_states(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 2ms/step - loss: 0.5782 - categorical_true_positives: 22110.9323
Epoch 2/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1737 - categorical_true_positives: 23825.8212
Epoch 3/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1254 - categorical_true_positives: 24152.4547
<tensorflow.python.keras.callbacks.History at 0x7fb6a42a55f8>

การจัดการการสูญเสียและเมตริกที่ไม่ตรงกับลายเซ็นมาตรฐาน

การสูญเสียและเมตริกส่วนใหญ่ที่ท่วมท้นสามารถคำนวณได้จาก y_true และ y_pred โดยที่ y_pred เป็นผลลัพธ์ของโมเดลของคุณ - แต่ไม่ใช่ทั้งหมด ตัวอย่างเช่นการสูญเสียการทำให้เป็นมาตรฐานอาจต้องการการเปิดใช้งานเลเยอร์เท่านั้น (ไม่มีเป้าหมายในกรณีนี้) และการเปิดใช้งานนี้อาจไม่ใช่เอาต์พุตแบบจำลอง

ในกรณีเช่นนี้คุณสามารถเรียก self.add_loss(loss_value) จากภายในวิธีการเรียกของเลเยอร์ที่กำหนดเอง การสูญเสียที่เพิ่มด้วยวิธีนี้จะถูกเพิ่มเข้าไปในการสูญเสีย "หลัก" ในระหว่างการฝึกอบรม (การสูญเสียที่ส่งผ่านไปยัง compile() ) นี่คือตัวอย่างง่ายๆที่เพิ่มการทำให้เป็นมาตรฐานของกิจกรรม (โปรดทราบว่าการทำให้เป็นมาตรฐานของกิจกรรมนั้นมีอยู่แล้วในเลเยอร์ Keras ทั้งหมด - เลเยอร์นี้เป็นเพียงตัวอย่างที่เป็นรูปธรรมเท่านั้น):

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: 3.4140
<tensorflow.python.keras.callbacks.History at 0x7fb6a4233748>

คุณสามารถทำได้เช่นเดียวกันสำหรับการบันทึกค่าเมตริกโดยใช้ 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.5646 - std_of_activation: 0.9702
<tensorflow.python.keras.callbacks.History at 0x7fb6a40cf6a0>

ใน Functional API คุณยังสามารถเรียก model.add_loss(loss_tensor) หรือ model.add_metric(metric_tensor, name, aggregation)

นี่คือตัวอย่างง่ายๆ:

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 2ms/step - loss: 3.6195 - std_of_activation: 0.0020
<tensorflow.python.keras.callbacks.History at 0x7fb6a07d42b0>

โปรดทราบว่าเมื่อคุณส่งการสูญเสียผ่าน add_loss() มันจะเป็นไปได้ที่จะเรียกใช้ compile() โดยไม่มีฟังก์ชันการสูญเสียเนื่องจากโมเดลมีการสูญเสียที่จะลดน้อยที่สุดอยู่แล้ว

พิจารณาเลเยอร์ LogisticEndpoint ต่อไปนี้: ใช้เป็นอินพุตเป้าหมายและบันทึกและติดตามการสูญเสีย add_loss() ผ่าน add_loss() นอกจากนี้ยังติดตามความแม่นยำในการจัดหมวดหมู่ผ่าน 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)

คุณสามารถใช้ในโมเดลที่มีอินพุตสองอินพุต (ข้อมูลอินพุตและเป้าหมาย) คอมไพล์โดยไม่มีอาร์กิวเมนต์ loss เช่นนี้:

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 222ms/step - loss: 0.9652 - binary_accuracy: 0.0000e+00
<tensorflow.python.keras.callbacks.History at 0x7fb6a05e01d0>

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการฝึกโมเดลมัลติอินพุตโปรดดูส่วนการ ส่งผ่านข้อมูลไปยังโมเดลมัลติอินพุตหลายเอาต์พุต

ตั้งค่าการระงับการตรวจสอบความถูกต้องโดยอัตโนมัติ

ในตัวอย่าง end-to-end แรกที่คุณเห็นเราใช้อาร์กิวเมนต์ validation_data เพื่อส่ง tuple ของอาร์เรย์ NumPy (x_val, y_val) ไปยังแบบจำลองเพื่อประเมินการสูญเสียการตรวจสอบความถูกต้องและเมตริกการตรวจสอบความถูกต้องในตอนท้ายของแต่ละยุค

นี่คืออีกทางเลือกหนึ่ง: อาร์กิวเมนต์ validation_split ช่วยให้คุณสามารถจองส่วนหนึ่งของข้อมูลการฝึกอบรมของคุณโดยอัตโนมัติสำหรับการตรวจสอบความถูกต้อง ค่าอาร์กิวเมนต์แสดงถึงเศษส่วนของข้อมูลที่จะสงวนไว้สำหรับการตรวจสอบความถูกต้องดังนั้นจึงควรกำหนดเป็นตัวเลขที่สูงกว่า 0 และต่ำกว่า 1 ตัวอย่างเช่น validation_split=0.2 หมายถึง "ใช้ 20% ของข้อมูลเพื่อการตรวจสอบความถูกต้อง" และ validation_split=0.6 หมายถึง "ใช้ 60% ของข้อมูลเพื่อการตรวจสอบความถูกต้อง"

วิธีคำนวณการตรวจสอบความถูกต้องคือการรับตัวอย่าง x% สุดท้ายของอาร์เรย์ที่ได้รับจากการเรียก fit() ก่อนการสับเปลี่ยนใด ๆ

โปรดทราบว่าคุณสามารถใช้ได้เฉพาะ validation_split เมื่อฝึกกับข้อมูล NumPy

model = get_compiled_model()
model.fit(x_train, y_train, batch_size=64, validation_split=0.2, epochs=1)
625/625 [==============================] - 2s 2ms/step - loss: 0.6075 - sparse_categorical_accuracy: 0.8389 - val_loss: 0.2291 - val_sparse_categorical_accuracy: 0.9322
<tensorflow.python.keras.callbacks.History at 0x7fb6a0504240>

การฝึกอบรมและการประเมินผลจากชุดข้อมูล tf.data

ในวรรคสามที่ผ่านมาคุณเคยเห็นวิธีการจัดการกับความสูญเสียที่ตัวชี้วัดและเพิ่มประสิทธิภาพและคุณได้เห็นวิธีการใช้ validation_data และ validation_split ข้อโต้แย้งใน fit() เมื่อข้อมูลของคุณจะถูกส่งเป็นอาร์เรย์ NumPy

ตอนนี้เรามาดูกรณีที่ข้อมูลของคุณอยู่ในรูปแบบของวัตถุtf.data.Dataset

tf.data API คือชุดของยูทิลิตี้ใน TensorFlow 2.0 สำหรับการโหลดและประมวลผลข้อมูลล่วงหน้าด้วยวิธีที่รวดเร็วและปรับขนาดได้

สำหรับคำแนะนำฉบับสมบูรณ์เกี่ยวกับการสร้าง Datasets โปรดดู เอกสาร tf.data

คุณสามารถส่งอินสแตนซ์ Dataset ไปยังวิธีการที่ fit() evaluate() และ 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 2ms/step - loss: 0.5652 - sparse_categorical_accuracy: 0.8404
Epoch 2/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1721 - sparse_categorical_accuracy: 0.9497
Epoch 3/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1170 - sparse_categorical_accuracy: 0.9645
Evaluate
157/157 [==============================] - 0s 2ms/step - loss: 0.1308 - sparse_categorical_accuracy: 0.9602
{'loss': 0.13075917959213257,
 'sparse_categorical_accuracy': 0.9602000117301941}

โปรดทราบว่าชุดข้อมูลจะถูกรีเซ็ตเมื่อสิ้นสุดแต่ละยุคดังนั้นจึงสามารถนำกลับมาใช้ในยุคถัดไปได้

หากคุณต้องการเรียกใช้การฝึกอบรมเฉพาะกลุ่มที่กำหนดจากชุดข้อมูลนี้คุณสามารถส่งอาร์กิวเมนต์ steps_per_epoch ซึ่งระบุจำนวนขั้นตอนการฝึกอบรมที่โมเดลควรเรียกใช้โดยใช้ชุดข้อมูลนี้ก่อนที่จะไปยังยุคถัดไป

หากคุณทำเช่นนี้ชุดข้อมูลจะไม่ถูกรีเซ็ตในตอนท้ายของแต่ละยุค แต่เราจะวาดแบตช์ถัดไปแทน ในที่สุดชุดข้อมูลจะหมดข้อมูล (เว้นแต่จะเป็นชุดข้อมูลแบบวนซ้ำไม่สิ้นสุด)

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 2ms/step - loss: 1.2664 - sparse_categorical_accuracy: 0.6389
Epoch 2/3
100/100 [==============================] - 0s 2ms/step - loss: 0.3868 - sparse_categorical_accuracy: 0.8875
Epoch 3/3
100/100 [==============================] - 0s 2ms/step - loss: 0.3578 - sparse_categorical_accuracy: 0.8981
<tensorflow.python.keras.callbacks.History at 0x7fb6a02a5358>

การใช้ชุดข้อมูลการตรวจสอบความถูกต้อง

คุณสามารถส่งผ่านอินสแตนซ์ Dataset เป็นอาร์กิวเมนต์ validation_data 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 [==============================] - 2s 3ms/step - loss: 0.5754 - sparse_categorical_accuracy: 0.8384 - val_loss: 0.1829 - val_sparse_categorical_accuracy: 0.9465
<tensorflow.python.keras.callbacks.History at 0x7fb6a01651d0>

ในตอนท้ายของแต่ละยุคโมเดลจะวนซ้ำบนชุดข้อมูลการตรวจสอบความถูกต้องและคำนวณเมตริกการสูญเสียการตรวจสอบความถูกต้องและการตรวจสอบความถูกต้อง

หากคุณต้องการเรียกใช้การตรวจสอบความถูกต้องเฉพาะกับกลุ่มข้อมูลที่ระบุจากชุดข้อมูลนี้คุณสามารถส่งผ่านอาร์กิวเมนต์ validation_steps ซึ่งระบุจำนวนขั้นตอนการตรวจสอบที่โมเดลควรรันด้วยชุดข้อมูลการตรวจสอบความถูกต้องก่อนที่จะขัดจังหวะการตรวจสอบความถูกต้องและไปยังยุคถัดไป:

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 [==============================] - 2s 2ms/step - loss: 0.5503 - sparse_categorical_accuracy: 0.8507 - val_loss: 0.3296 - val_sparse_categorical_accuracy: 0.9062
<tensorflow.python.keras.callbacks.History at 0x7fb6a02e4630>

โปรดทราบว่าชุดข้อมูลการตรวจสอบความถูกต้องจะถูกรีเซ็ตหลังจากการใช้งานแต่ละครั้ง (ดังนั้นคุณจะได้รับการประเมินจากตัวอย่างเดียวกันตั้งแต่ยุคจนถึงยุค)

ไม่รองรับอาร์กิวเมนต์ validation_split (การสร้างชุดการระงับจากข้อมูลการฝึกอบรม) เมื่อฝึกจากออบเจ็กต์ Dataset เนื่องจากฟีเจอร์นี้ต้องการความสามารถในการทำดัชนีตัวอย่างของชุดข้อมูลซึ่งโดยทั่วไปไม่สามารถทำได้ด้วย Dataset API

รองรับรูปแบบการป้อนข้อมูลอื่น ๆ

นอกจากอาร์เรย์ NumPy, เทนเซอร์ที่กระตือรือร้นและ Datasets TensorFlow แล้วยังสามารถฝึกโมเดล Keras โดยใช้ดาต้าเฟรมของ Pandas หรือจากเครื่องกำเนิด Python ที่ให้ข้อมูลและป้ายกำกับเป็นกลุ่ม

โดยเฉพาะอย่างยิ่งคลาส keras.utils.Sequence มีอินเทอร์เฟซที่เรียบง่ายในการสร้างตัวสร้างข้อมูล Python ที่รับรู้การประมวลผลหลายขั้นตอนและสามารถสับเปลี่ยนได้

โดยทั่วไปเราขอแนะนำให้คุณใช้:

  • ป้อนข้อมูล NumPy หากข้อมูลของคุณมีขนาดเล็กและพอดีกับหน่วยความจำ
  • Dataset อบเจ็กต์ Dataset หากคุณมีชุดข้อมูลขนาดใหญ่และคุณต้องทำการฝึกอบรมแบบกระจาย
  • Sequence อบเจ็กต์หากคุณมีชุดข้อมูลขนาดใหญ่และคุณจำเป็นต้องทำการประมวลผลฝั่ง Python แบบกำหนดเองจำนวนมากซึ่งไม่สามารถทำได้ใน TensorFlow (เช่นหากคุณใช้ไลบรารีภายนอกในการโหลดข้อมูลหรือการประมวลผลล่วงหน้า)

ใช้ออบเจ็กต์ keras.utils.Sequence เป็นอินพุต

keras.utils.Sequence เป็นยูทิลิตี้ที่คุณสามารถซับคลาสเพื่อรับตัวสร้าง Python ที่มีคุณสมบัติสำคัญสองประการ:

  • ทำงานได้ดีกับการประมวลผลหลายขั้นตอน
  • สามารถสับเปลี่ยนได้ (เช่นเมื่อส่ง shuffle=True in fit() )

Sequence ต้องใช้สองวิธี:

  • __getitem__
  • __len__

เมธอด __getitem__ ควรส่งคืนชุดงานที่สมบูรณ์ หากคุณต้องการแก้ไขชุดข้อมูลระหว่างยุคคุณสามารถใช้ on_epoch_end

นี่คือตัวอย่างสั้น ๆ :

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)

การใช้การถ่วงน้ำหนักตัวอย่างและการถ่วงน้ำหนักชั้นเรียน

ด้วยการตั้งค่าเริ่มต้นน้ำหนักของตัวอย่างจะถูกกำหนดโดยความถี่ในชุดข้อมูล มีสองวิธีในการถ่วงน้ำหนักข้อมูลโดยไม่ขึ้นอยู่กับความถี่ของกลุ่มตัวอย่าง:

  • น้ำหนักคลาส
  • ตัวอย่างน้ำหนัก

น้ำหนักคลาส

แห่งนี้ตั้งอยู่โดยผ่านพจนานุกรมไป class_weight อาร์กิวเมนต์ Model.fit() พจนานุกรมนี้แมปดัชนีคลาสกับน้ำหนักที่ควรใช้สำหรับตัวอย่างที่เป็นของคลาสนี้

สิ่งนี้สามารถใช้เพื่อปรับสมดุลของคลาสโดยไม่ต้องสุ่มตัวอย่างใหม่หรือฝึกโมเดลที่ให้ความสำคัญกับคลาสใดคลาสหนึ่งมากขึ้น

ตัวอย่างเช่นถ้าคลาส "0" ครึ่งหนึ่งแสดงเป็นคลาส "1" ในข้อมูลของคุณคุณสามารถใช้ Model.fit(..., class_weight={0: 1., 1: 0.5})

นี่คือตัวอย่าง NumPy ที่เราใช้น้ำหนักคลาสหรือน้ำหนักตัวอย่างเพื่อให้ความสำคัญมากขึ้นกับการจัดประเภทที่ถูกต้องของคลาส # 5 (ซึ่งก็คือตัวเลข "5" ในชุดข้อมูล 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 2ms/step - loss: 0.6269 - sparse_categorical_accuracy: 0.8396
<tensorflow.python.keras.callbacks.History at 0x7fb6ca2479b0>

ตัวอย่างน้ำหนัก

สำหรับการควบคุมแบบละเอียดหรือหากคุณไม่ได้สร้างลักษณนามคุณสามารถใช้ "ตุ้มน้ำหนักตัวอย่าง"

  • เมื่อการฝึกอบรมจากข้อมูล NumPy: ผ่าน sample_weight อาร์กิวเมนต์ Model.fit()
  • เมื่อฝึกจาก tf.data หรือตัววนซ้ำประเภทอื่น ๆ : Yield (input_batch, label_batch, sample_weight_batch) tuples

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

เมื่อน้ำหนักที่ใช้เป็นค่าหนึ่งและศูนย์อาร์เรย์สามารถใช้เป็นมาส ก์ สำหรับฟังก์ชันการสูญเสียได้ (เป็นการละทิ้งการมีส่วนร่วมของตัวอย่างบางส่วนต่อการสูญเสียทั้งหมด)

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 2ms/step - loss: 0.6540 - sparse_categorical_accuracy: 0.8302
<tensorflow.python.keras.callbacks.History at 0x7fb6b03db128>

นี่คือตัวอย่าง Dataset ตรงกัน:

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 [==============================] - 2s 2ms/step - loss: 0.6052 - sparse_categorical_accuracy: 0.8477
<tensorflow.python.keras.callbacks.History at 0x7fb6a40cc908>

การส่งผ่านข้อมูลไปยังแบบหลายอินพุตหลายเอาต์พุต

ในตัวอย่างก่อนหน้านี้เรากำลังพิจารณาโมเดลที่มีอินพุตเดียว (เทนเซอร์ของรูปร่าง (764,) ) และเอาท์พุตเดียว (การคาดคะเนรูปร่างเทนเซอร์ (10,) ) แต่โมเดลที่มีอินพุตหรือเอาต์พุตหลายตัวล่ะ?

พิจารณารูปแบบต่อไปนี้ซึ่งมีการป้อนรูปภาพของรูปร่าง (32, 32, 3) (นั่นคือ (height, width, channels) ) และการป้อนข้อมูลอนุกรมเวลาของรูปร่าง (None, 10) (นั่นคือ (timesteps, features) ) แบบจำลองของเราจะมีสองเอาต์พุตที่คำนวณจากการรวมกันของอินพุตเหล่านี้: "คะแนน" (ของรูปร่าง (1,) ) และการแจกแจงความน่าจะเป็นในห้าคลาส (ของรูปร่าง (5,) )

0afecaed 60

มาพล็อตแบบจำลองนี้เพื่อให้คุณเห็นได้ชัดเจนว่าเรากำลังทำอะไรอยู่ที่นี่ (โปรดทราบว่ารูปร่างที่แสดงในพล็อตเป็นรูปแบตช์แทนที่จะเป็นรูปร่างต่อตัวอย่าง)

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

png

ในเวลาคอมไพล์เราสามารถระบุการสูญเสียที่แตกต่างกันไปยังเอาต์พุตที่แตกต่างกันได้โดยส่งผ่านฟังก์ชันการสูญเสียเป็นรายการ:

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

หากเราส่งผ่านฟังก์ชันการสูญเสียเพียงครั้งเดียวไปยังแบบจำลองฟังก์ชันการสูญเสียเดียวกันจะถูกนำไปใช้กับทุกเอาต์พุต (ซึ่งไม่เหมาะสมที่นี่)

ในทำนองเดียวกันสำหรับเมตริก:

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()],
    ],
)

เนื่องจากเราตั้งชื่อให้กับเลเยอร์เอาต์พุตของเราเราจึงสามารถระบุการสูญเสียและเมตริกต่อเอาต์พุตผ่านคำสั่ง:

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()],
    },
)

เราขอแนะนำให้ใช้ชื่อที่ชัดเจนและเขียนตามคำบอกหากคุณมีมากกว่า 2 เอาต์พุต

เป็นไปได้ที่จะให้น้ำหนักที่แตกต่างกันสำหรับการสูญเสียเฉพาะผลลัพธ์ที่แตกต่างกัน (ตัวอย่างเช่นอาจมีคนต้องการให้สิทธิ์การสูญเสีย "คะแนน" ในตัวอย่างของเราโดยให้ความสำคัญเป็น 2 เท่าของการสูญเสียคลาส) โดยใช้อาร์กิวเมนต์ loss_weights :

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},
)

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

# 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()},
)

การส่งผ่านข้อมูลไปยังโมเดลหลายอินพุตหรือหลายเอาต์พุตแบบ fit() ทำงานในลักษณะเดียวกันกับการระบุฟังก์ชันการสูญเสียในการคอมไพล์: คุณสามารถส่งผ่าน รายการอาร์เรย์ NumPy (ด้วยการแมป 1: 1 ไปยังเอาต์พุตที่ได้รับฟังก์ชันการสูญเสีย ) หรือ กำหนดการแมปชื่อเอาต์พุตกับอาร์เรย์ 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 [==============================] - 10s 10ms/step - loss: 12.4255 - score_output_loss: 0.7638 - class_output_loss: 11.6617
4/4 [==============================] - 0s 5ms/step - loss: 11.1176 - score_output_loss: 0.6303 - class_output_loss: 10.4873
<tensorflow.python.keras.callbacks.History at 0x7fb6a02ed828>

นี่คือกรณีการใช้งาน Dataset : เช่นเดียวกับสิ่งที่เราทำกับอาร์เรย์ NumPy Dataset ควรส่งคืน tuple ของคำสั่ง

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 27ms/step - loss: 10.9011 - score_output_loss: 0.4919 - class_output_loss: 10.4092
<tensorflow.python.keras.callbacks.History at 0x7fb6b00ae9e8>

ใช้การโทรกลับ

การเรียกกลับใน Keras เป็นวัตถุที่ถูกเรียกในจุดที่แตกต่างกันระหว่างการฝึกอบรม (ในช่วงเริ่มต้นของยุคเมื่อสิ้นสุดชุดงานในตอนท้ายของยุค ฯลฯ ) สามารถใช้เพื่อปรับใช้พฤติกรรมบางอย่างเช่น:

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

สามารถส่งการโทรกลับเป็นรายการไปยังการโทรของคุณเพื่อให้ 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.6076 - sparse_categorical_accuracy: 0.8350 - val_loss: 0.2323 - val_sparse_categorical_accuracy: 0.9306
Epoch 2/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1925 - sparse_categorical_accuracy: 0.9436 - val_loss: 0.1828 - val_sparse_categorical_accuracy: 0.9446
Epoch 3/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1310 - sparse_categorical_accuracy: 0.9616 - val_loss: 0.1580 - val_sparse_categorical_accuracy: 0.9510
Epoch 4/20
625/625 [==============================] - 1s 2ms/step - loss: 0.0967 - sparse_categorical_accuracy: 0.9700 - val_loss: 0.1681 - val_sparse_categorical_accuracy: 0.9490
Epoch 5/20
625/625 [==============================] - 1s 2ms/step - loss: 0.0841 - sparse_categorical_accuracy: 0.9742 - val_loss: 0.1482 - val_sparse_categorical_accuracy: 0.9568
Epoch 00005: early stopping
<tensorflow.python.keras.callbacks.History at 0x7fb63c5945c0>

มีการโทรกลับในตัวมากมาย

มีการโทรกลับในตัวมากมายที่มีอยู่แล้วใน Keras เช่น:

  • ModelCheckpoint : บันทึกโมเดลเป็นระยะ
  • EarlyStopping : หยุดการฝึกเมื่อการฝึกอบรมไม่ได้ปรับปรุงเมตริกการตรวจสอบความถูกต้องอีกต่อไป
  • TensorBoard : เขียนบันทึกโมเดลเป็นระยะซึ่งสามารถมองเห็นได้ใน TensorBoard (รายละเอียดเพิ่มเติมในส่วน "การแสดงภาพ")
  • CSVLogger : สตรีมข้อมูลการสูญเสียและเมตริกไปยังไฟล์ CSV
  • เป็นต้น

ดู เอกสารการติดต่อกลับ สำหรับรายการทั้งหมด

การเขียนโทรกลับของคุณเอง

คุณสามารถสร้างการโทรกลับแบบกำหนดเองได้โดยการขยายคลาสฐาน keras.callbacks.Callback การเรียกกลับมีการเข้าถึงโมเดลที่เกี่ยวข้องผ่านคุณสมบัติคลาส self.model

อย่าลืมอ่าน คู่มือฉบับสมบูรณ์เกี่ยวกับการเขียนการโทรกลับแบบกำหนดเอง

นี่คือตัวอย่างง่ายๆในการบันทึกรายการค่าการสูญเสียต่อชุดระหว่างการฝึก:

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"))

แบบจำลองการตรวจสอบ

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

วิธีที่ง่ายที่สุดในการบรรลุเป้าหมายนี้คือการเรียกกลับ ModelCheckpoint :

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
625/625 [==============================] - 2s 2ms/step - loss: 0.6397 - sparse_categorical_accuracy: 0.8210 - val_loss: 0.2310 - val_sparse_categorical_accuracy: 0.9326

Epoch 00001: val_loss improved from inf to 0.23098, saving model to mymodel_1
INFO:tensorflow:Assets written to: mymodel_1/assets
Epoch 2/2
625/625 [==============================] - 1s 2ms/step - loss: 0.1885 - sparse_categorical_accuracy: 0.9454 - val_loss: 0.1851 - val_sparse_categorical_accuracy: 0.9435

Epoch 00002: val_loss improved from 0.23098 to 0.18510, saving model to mymodel_2
INFO:tensorflow:Assets written to: mymodel_2/assets
<tensorflow.python.keras.callbacks.History at 0x7fb6a04271d0>

การเรียกกลับ ModelCheckpoint สามารถใช้เพื่อใช้ความทนทานต่อความผิดพลาด: ความสามารถในการเริ่มต้นการฝึกอบรมจากสถานะที่บันทึกไว้ล่าสุดของโมเดลในกรณีที่การฝึกหยุดชะงักแบบสุ่ม นี่คือตัวอย่างพื้นฐาน:

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
  85/1563 [>.............................] - ETA: 2s - loss: 1.4465 - sparse_categorical_accuracy: 0.5717INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.93/assets
 185/1563 [==>...........................] - ETA: 5s - loss: 1.1118 - sparse_categorical_accuracy: 0.6784INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.69/assets
 284/1563 [====>.........................] - ETA: 5s - loss: 0.9495 - sparse_categorical_accuracy: 0.7266INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.58/assets
 385/1563 [======>.......................] - ETA: 5s - loss: 0.8464 - sparse_categorical_accuracy: 0.7569INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.52/assets
 485/1563 [========>.....................] - ETA: 5s - loss: 0.7749 - sparse_categorical_accuracy: 0.7776INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.47/assets
 585/1563 [==========>...................] - ETA: 4s - loss: 0.7210 - sparse_categorical_accuracy: 0.7930INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.44/assets
 685/1563 [============>.................] - ETA: 4s - loss: 0.6788 - sparse_categorical_accuracy: 0.8050INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.42/assets
 785/1563 [==============>...............] - ETA: 4s - loss: 0.6445 - sparse_categorical_accuracy: 0.8149INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.40/assets
 883/1563 [===============>..............] - ETA: 3s - loss: 0.6165 - sparse_categorical_accuracy: 0.8229INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.38/assets
 984/1563 [=================>............] - ETA: 3s - loss: 0.5917 - sparse_categorical_accuracy: 0.8299INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.37/assets
1082/1563 [===================>..........] - ETA: 2s - loss: 0.5709 - sparse_categorical_accuracy: 0.8358INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.35/assets
1185/1563 [=====================>........] - ETA: 1s - loss: 0.5517 - sparse_categorical_accuracy: 0.8413INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.34/assets
1282/1563 [=======================>......] - ETA: 1s - loss: 0.5356 - sparse_categorical_accuracy: 0.8459INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.33/assets
1384/1563 [=========================>....] - ETA: 0s - loss: 0.5202 - sparse_categorical_accuracy: 0.8503INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.32/assets
1484/1563 [===========================>..] - ETA: 0s - loss: 0.5065 - sparse_categorical_accuracy: 0.8542INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.31/assets
1563/1563 [==============================] - 9s 5ms/step - loss: 0.4965 - sparse_categorical_accuracy: 0.8570
<tensorflow.python.keras.callbacks.History at 0x7fb6a036f5c0>

นอกจากนี้คุณยังเขียนการโทรกลับของคุณเองเพื่อบันทึกและกู้คืนโมเดล

สำหรับคำแนะนำฉบับสมบูรณ์เกี่ยวกับการทำให้เป็นอนุกรมและการบันทึกโปรดดู คู่มือการบันทึกและการทำให้เป็นอนุกรม

การใช้ตารางอัตราการเรียนรู้

รูปแบบทั่วไปในการฝึกโมเดลการเรียนรู้เชิงลึกคือการค่อยๆลดการเรียนรู้ลงเมื่อการฝึกดำเนินไป โดยทั่วไปเรียกว่า "อัตราการลดลงของการเรียนรู้"

กำหนดการสลายการเรียนรู้อาจเป็นแบบคงที่ (กำหนดไว้ล่วงหน้าเป็นฟังก์ชันของยุคปัจจุบันหรือดัชนีแบทช์ปัจจุบัน) หรือไดนามิก (ตอบสนองต่อพฤติกรรมปัจจุบันของโมเดลโดยเฉพาะอย่างยิ่งการสูญเสียการตรวจสอบความถูกต้อง)

ส่งต่อกำหนดการไปยังเครื่องมือเพิ่มประสิทธิภาพ

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

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)

มีกำหนดการในตัวมากมาย: ExponentialDecay , PiecewiseConstantDecay , PolynomialDecay และ InverseTimeDecay

การใช้การโทรกลับเพื่อใช้ตารางอัตราการเรียนรู้แบบไดนามิก

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

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

แสดงภาพการสูญเสียและตัวชี้วัดระหว่างการฝึกอบรม

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

  • แปลงสดของการสูญเสียและตัวชี้วัดสำหรับการฝึกอบรมและการประเมินผล
  • (เป็นทางเลือก) การแสดงภาพฮิสโตแกรมของการเปิดใช้งานเลเยอร์ของคุณ
  • (เป็นทางเลือก) การแสดงภาพ 3 มิติของพื้นที่การฝังที่เรียนรู้โดยเลเยอร์การ Embedding ของคุณ

หากคุณติดตั้ง TensorFlow ด้วย pip คุณควรจะสามารถเปิด TensorBoard จากบรรทัดคำสั่ง:

tensorboard --logdir=/full_path_to_your_logs

ใช้การเรียกกลับ TensorBoard

วิธีที่ง่ายที่สุดในการใช้ TensorBoard กับโมเดล Keras และวิธี fit() คือการเรียกกลับของ TensorBoard

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

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)
<tensorflow.python.keras.callbacks.TensorBoard at 0x7fb6a422a748>

สำหรับข้อมูลเพิ่มเติมโปรดดู เอกสารสำหรับการโทรกลับของ TensorBoard