ช่วยปกป้อง Great Barrier Reef กับ TensorFlow บน Kaggle เข้าร่วมท้าทาย

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

ดูบน TensorFlow.org ทำงานใน Google Colab ดูแหล่งที่มาบน GitHub ดาวน์โหลดโน๊ตบุ๊ค

ติดตั้ง

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

บทนำ

คู่มือนี้ครอบคลุมการฝึกอบรมการประเมินผลและการทำนาย (อนุมาน) รุ่นเมื่อใช้ในตัว APIs สำหรับการฝึกอบรมและการตรวจสอบ (เช่น 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]

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

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.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

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

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]}

เราจะประเมินรูปแบบจากข้อมูลการทดสอบผ่าน 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)

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

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 [==============================] - 2s 2ms/step - loss: 0.0162
<keras.callbacks.History at 0x7ff8881ba250>

หากคุณต้องการฟังก์ชั่นการสูญเสียที่จะเกิดในพารามิเตอร์ข้าง 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.0388
<keras.callbacks.History at 0x7ff8882130d0>

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

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

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

ปรับปรุงรัฐและผลการคำนวณจะถูกเก็บไว้ที่แยกจากกัน (ใน 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_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>

การจัดการความสูญเสียและตัวชี้วัดที่ไม่เข้ากับลายเซ็นมาตรฐาน

ส่วนใหญ่ที่ครอบงำของการสูญเสียและตัวชี้วัดสามารถคำนวณได้จาก 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: 2.4545
<keras.callbacks.History at 0x7ff87c53f310>

คุณสามารถทำเช่นเดียวกันสำหรับการเข้าสู่ระบบเมตริกค่าใช้ 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>

ใน 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 3ms/step - loss: 2.4647 - std_of_activation: 0.0017
<keras.callbacks.History at 0x7ff87c216f90>

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

พิจารณาต่อไปนี้ LogisticEndpoint ชั้น: มันจะใช้เวลาเป็นปัจจัยการผลิตและเป้าหมาย logits และจะติดตามการสูญเสีย crossentropy ผ่าน 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)

คุณสามารถใช้มันในรูปแบบที่มีสองอินพุต (input ข้อมูลและเป้าหมาย) รวบรวมโดยไม่ต้องมี 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 414ms/step - loss: 0.9889 - binary_accuracy: 0.0000e+00
<keras.callbacks.History at 0x7ff87c0848d0>

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

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

ในแบบ 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 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>

การฝึกอบรมและการประเมินจาก tf.data Datasets

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

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

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

สำหรับเป็นคู่มือที่สมบูรณ์เกี่ยวกับการสร้าง 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 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}

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

หากคุณต้องการที่จะเรียกใช้การฝึกอบรมเฉพาะในหมายเลขเฉพาะของแบตช์จากชุดข้อมูลนี้คุณสามารถผ่าน 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 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>

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

คุณสามารถส่ง 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 [==============================] - 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>

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

หากคุณต้องการที่จะทำงานการตรวจสอบเฉพาะในหมายเลขเฉพาะของแบตช์จากชุดข้อมูลนี้คุณสามารถผ่าน 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 [==============================] - 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>

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

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

รองรับรูปแบบอินพุตอื่น ๆ

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

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

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

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

ใช้ keras.utils.Sequence วัตถุเป็น input

keras.utils.Sequence เป็นโปรแกรมที่คุณสามารถซับคลาสที่จะได้รับกำเนิดงูหลามที่มีสองคุณสมบัติที่สำคัญ:

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

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

  • __getitem__
  • __len__

วิธีการ __getitem__ ควรกลับชุดสมบูรณ์ หากคุณต้องการที่จะปรับเปลี่ยนชุดของคุณระหว่าง epochs คุณอาจใช้ 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 3ms/step - loss: 0.3708 - sparse_categorical_accuracy: 0.9032
<keras.callbacks.History at 0x7ff80c7ddd10>

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

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

  • เมื่อการฝึกอบรมจากข้อมูล NumPy: ผ่าน sample_weight อาร์กิวเมนต์ Model.fit()
  • เมื่อการฝึกอบรมจาก tf.data หรือประเภทอื่น ๆ ของ iterator: อัตราผลตอบแทน (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 3ms/step - loss: 0.3806 - sparse_categorical_accuracy: 0.9000
<keras.callbacks.History at 0x7ff80c650350>

นี่คือการจับคู่ 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 [==============================] - 3s 3ms/step - loss: 0.3588 - sparse_categorical_accuracy: 0.9070
<keras.callbacks.History at 0x7ff80c51cb50>

ส่งข้อมูลไปยังโมเดลหลายอินพุตและหลายเอาต์พุต

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

พิจารณารูปแบบต่อไปนี้ซึ่งมีภาพข้อมูลของรูปร่าง (32, 32, 3) (ว่า (height, width, channels) ) และการป้อนข้อมูลอนุกรมเวลาของรูปร่าง (None, 10) (ที่ (timesteps, features) ) แบบจำลองของเราจะมีสองผลคำนวณจากการรวมกันของปัจจัยการผลิตเหล่านี้: เป็น "คะแนน" (ของรูปร่าง (1,) ) และการกระจายความน่าจะเป็นในช่วงห้าชั้นเรียน (ของรูปร่าง (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]
)

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

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

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

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 ทำแผนที่เพื่อผลที่ได้รับฟังก์ชั่นการสูญเสีย ) หรือ dicts ทำแผนที่ชื่อส่งออกไปยังอาร์เรย์ 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>

นี่คือ Dataset กรณีการใช้งาน: ในทำนองเดียวกันเป็นสิ่งที่เราทำสำหรับอาร์เรย์ NumPy ที่ Dataset ควรกลับ tuple ของ 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>

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

การเรียกกลับใน 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.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>

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

มีการโทรกลับในตัวจำนวนมากใน 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
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>

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

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

สำหรับคำแนะนำที่สมบูรณ์ในอนุกรมและประหยัดดู คู่มือในการออมและการ serializing รุ่น

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

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

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

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

คุณสามารถใช้การเรียนรู้แบบคงกำหนดการอัตราการสลายตัวโดยการส่งผ่านวัตถุตารางเวลาเป็น 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)
<keras.callbacks.TensorBoard at 0x7ff88c8c04d0>

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