![]() | ![]() | ![]() | ![]() |
ติดตั้ง
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)
ณ เวลารวบรวม เราสามารถระบุความสูญเสียที่แตกต่างกันไปยังผลลัพธ์ที่ต่างกัน โดยส่งฟังก์ชันการสูญเสียเป็นรายการ:
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
โทรกลับ