โอเวอร์ฟิตและอันเดอร์ฟิต

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

และเช่นเคย โค้ดในตัวอย่างนี้จะใช้ tf.keras API ซึ่งคุณสามารถเรียนรู้เพิ่มเติมได้ใน คู่มือ TensorFlow Keras

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

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

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

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

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

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

ในสมุดบันทึกนี้ เราจะสำรวจเทคนิคการทำให้เป็นมาตรฐานทั่วไปหลายอย่าง และใช้เทคนิคเหล่านี้เพื่อปรับปรุงแบบจำลองการจัดประเภท

ติดตั้ง

ก่อนเริ่มต้น ให้นำเข้าแพ็คเกจที่จำเป็น:

import tensorflow as tf

from tensorflow.keras import layers
from tensorflow.keras import regularizers

print(tf.__version__)
2.8.0-rc1
!pip install git+https://github.com/tensorflow/docs

import tensorflow_docs as tfdocs
import tensorflow_docs.modeling
import tensorflow_docs.plots
from  IPython import display
from matplotlib import pyplot as plt

import numpy as np

import pathlib
import shutil
import tempfile
logdir = pathlib.Path(tempfile.mkdtemp())/"tensorboard_logs"
shutil.rmtree(logdir, ignore_errors=True)

ชุดข้อมูล Higgs

เป้าหมายของบทช่วยสอนนี้ไม่ใช่การทำฟิสิกส์อนุภาค ดังนั้นอย่าจมอยู่กับรายละเอียดของชุดข้อมูล ประกอบด้วยตัวอย่าง 11,000,000 ตัวอย่าง โดยแต่ละรายการมีคุณสมบัติ 28 รายการ และป้ายกำกับคลาสไบนารี

gz = tf.keras.utils.get_file('HIGGS.csv.gz', 'http://mlphysics.ics.uci.edu/data/higgs/HIGGS.csv.gz')
Downloading data from http://mlphysics.ics.uci.edu/data/higgs/HIGGS.csv.gz
2816409600/2816407858 [==============================] - 123s 0us/step
2816417792/2816407858 [==============================] - 123s 0us/step
FEATURES = 28

คลาส tf.data.experimental.CsvDataset สามารถใช้เพื่ออ่านเร็กคอร์ด csv ได้โดยตรงจากไฟล์ gzip โดยไม่มีขั้นตอนการคลายการบีบอัดขั้นกลาง

ds = tf.data.experimental.CsvDataset(gz,[float(),]*(FEATURES+1), compression_type="GZIP")

คลาสตัวอ่าน csv นั้นส่งคืนรายการสเกลาร์สำหรับแต่ละเร็กคอร์ด ฟังก์ชันต่อไปนี้บรรจุรายการสเกลาร์เป็นคู่ (feature_vector, label)

def pack_row(*row):
  label = row[0]
  features = tf.stack(row[1:],1)
  return features, label

TensorFlow มีประสิทธิภาพสูงสุดเมื่อทำงานกับข้อมูลจำนวนมาก

ดังนั้น แทนที่จะบรรจุใหม่แต่ละแถว ให้สร้างชุดข้อมูลใหม่ที่มีกลุ่มตัวอย่าง 10,000 ตัวอย่าง ให้ใช้ pack_row Dataset แต่ละชุดงาน แล้วแยกชุดข้อมูลสำรองออกเป็นแต่ละระเบียน:

packed_ds = ds.batch(10000).map(pack_row).unbatch()

ดูบันทึกบางส่วนจาก packed_ds ใหม่นี้

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

for features,label in packed_ds.batch(1000).take(1):
  print(features[0])
  plt.hist(features.numpy().flatten(), bins = 101)
tf.Tensor(
[ 0.8692932  -0.6350818   0.22569026  0.32747006 -0.6899932   0.75420225
 -0.24857314 -1.0920639   0.          1.3749921  -0.6536742   0.9303491
  1.1074361   1.1389043  -1.5781983  -1.0469854   0.          0.65792954
 -0.01045457 -0.04576717  3.1019614   1.35376     0.9795631   0.97807616
  0.92000484  0.72165745  0.98875093  0.87667835], shape=(28,), dtype=float32)

png

เพื่อให้บทช่วยสอนนี้ค่อนข้างสั้น ให้ใช้เพียง 1,000 ตัวอย่างแรกสำหรับการตรวจสอบ และอีก 10,000 ตัวอย่างสำหรับการฝึกอบรม:

N_VALIDATION = int(1e3)
N_TRAIN = int(1e4)
BUFFER_SIZE = int(1e4)
BATCH_SIZE = 500
STEPS_PER_EPOCH = N_TRAIN//BATCH_SIZE

Dataset.skip และ Dataset.take ทำให้สิ่งนี้เป็นเรื่องง่าย

ในเวลาเดียวกัน ใช้เมธอด Dataset.cache เพื่อให้แน่ใจว่าตัวโหลดไม่จำเป็นต้องอ่านข้อมูลจากไฟล์ซ้ำในแต่ละยุค:

validate_ds = packed_ds.take(N_VALIDATION).cache()
train_ds = packed_ds.skip(N_VALIDATION).take(N_TRAIN).cache()
train_ds
<CacheDataset element_spec=(TensorSpec(shape=(28,), dtype=tf.float32, name=None), TensorSpec(shape=(), dtype=tf.float32, name=None))>

ชุดข้อมูลเหล่านี้ส่งคืนตัวอย่างแต่ละรายการ ใช้วิธีการ .batch เพื่อสร้างชุดงานที่มีขนาดเหมาะสมสำหรับการฝึก ก่อนจัดแบทช์ อย่าลืม .shuffle และ .repeat ชุดการฝึก

validate_ds = validate_ds.batch(BATCH_SIZE)
train_ds = train_ds.shuffle(BUFFER_SIZE).repeat().batch(BATCH_SIZE)

แสดงให้เห็นถึงการสวมใส่มากเกินไป

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

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

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

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

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

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

เริ่มต้นด้วยโมเดลง่ายๆ โดยใช้เลเยอร์เท่านั้น layers.Dense เป็นพื้นฐาน จากนั้นสร้างเวอร์ชันที่ใหญ่ขึ้น และเปรียบเทียบ

ขั้นตอนการอบรม

โมเดลจำนวนมากฝึกฝนได้ดีขึ้นหากคุณค่อยๆ ลดอัตราการเรียนรู้ระหว่างการฝึก ใช้ optimizers.schedules เพื่อลดอัตราการเรียนรู้เมื่อเวลาผ่านไป:

lr_schedule = tf.keras.optimizers.schedules.InverseTimeDecay(
  0.001,
  decay_steps=STEPS_PER_EPOCH*1000,
  decay_rate=1,
  staircase=False)

def get_optimizer():
  return tf.keras.optimizers.Adam(lr_schedule)

โค้ดด้านบนกำหนด schedules.InverseTimeDecay InverseTimeDecay เพื่อลดอัตราการเรียนรู้แบบไฮเปอร์โบลาลงเหลือ 1/2 ของอัตราฐานที่ 1,000 epochs, 1/3 ที่ 2000 epochs เป็นต้น

step = np.linspace(0,100000)
lr = lr_schedule(step)
plt.figure(figsize = (8,6))
plt.plot(step/STEPS_PER_EPOCH, lr)
plt.ylim([0,max(plt.ylim())])
plt.xlabel('Epoch')
_ = plt.ylabel('Learning Rate')

png

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

การฝึกอบรมสำหรับบทช่วยสอนนี้ดำเนินการในช่วงเวลาสั้นๆ มากมาย เพื่อลดเสียงรบกวนในการบันทึกให้ใช้ tfdocs.EpochDots ซึ่งพิมพ์ไฟล์ . สำหรับแต่ละยุค และชุดเมตริกทั้งหมดทุกๆ 100 ยุค

ถัดไปรวมถึง callbacks.EarlyStopping การหยุดก่อนกำหนดเพื่อหลีกเลี่ยงเวลาการฝึกอบรมที่ยาวนานและไม่จำเป็น โปรดทราบว่าการเรียกกลับนี้ถูกตั้งค่าให้มอนิเตอร์ val_binary_crossentropy ไม่ใช่ val_loss ความแตกต่างนี้จะมีความสำคัญในภายหลัง

ใช้ callbacks.TensorBoard เพื่อสร้างบันทึก TensorBoard สำหรับการฝึกอบรม

def get_callbacks(name):
  return [
    tfdocs.modeling.EpochDots(),
    tf.keras.callbacks.EarlyStopping(monitor='val_binary_crossentropy', patience=200),
    tf.keras.callbacks.TensorBoard(logdir/name),
  ]

ในทำนองเดียวกัน แต่ละรุ่นจะใช้การตั้งค่า Model.compile และ Model.fit เดียวกัน:

def compile_and_fit(model, name, optimizer=None, max_epochs=10000):
  if optimizer is None:
    optimizer = get_optimizer()
  model.compile(optimizer=optimizer,
                loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
                metrics=[
                  tf.keras.losses.BinaryCrossentropy(
                      from_logits=True, name='binary_crossentropy'),
                  'accuracy'])

  model.summary()

  history = model.fit(
    train_ds,
    steps_per_epoch = STEPS_PER_EPOCH,
    epochs=max_epochs,
    validation_data=validate_ds,
    callbacks=get_callbacks(name),
    verbose=0)
  return history

โมเดลจิ๋ว

เริ่มต้นด้วยการฝึกโมเดล:

tiny_model = tf.keras.Sequential([
    layers.Dense(16, activation='elu', input_shape=(FEATURES,)),
    layers.Dense(1)
])
size_histories = {}
size_histories['Tiny'] = compile_and_fit(tiny_model, 'sizes/Tiny')
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense (Dense)               (None, 16)                464       
                                                                 
 dense_1 (Dense)             (None, 1)                 17        
                                                                 
=================================================================
Total params: 481
Trainable params: 481
Non-trainable params: 0
_________________________________________________________________

Epoch: 0, accuracy:0.4961,  binary_crossentropy:0.7294,  loss:0.7294,  val_accuracy:0.4840,  val_binary_crossentropy:0.7200,  val_loss:0.7200,  
....................................................................................................
Epoch: 100, accuracy:0.5931,  binary_crossentropy:0.6279,  loss:0.6279,  val_accuracy:0.5860,  val_binary_crossentropy:0.6288,  val_loss:0.6288,  
....................................................................................................
Epoch: 200, accuracy:0.6157,  binary_crossentropy:0.6178,  loss:0.6178,  val_accuracy:0.6200,  val_binary_crossentropy:0.6134,  val_loss:0.6134,  
....................................................................................................
Epoch: 300, accuracy:0.6370,  binary_crossentropy:0.6086,  loss:0.6086,  val_accuracy:0.6220,  val_binary_crossentropy:0.6055,  val_loss:0.6055,  
....................................................................................................
Epoch: 400, accuracy:0.6522,  binary_crossentropy:0.6008,  loss:0.6008,  val_accuracy:0.6260,  val_binary_crossentropy:0.5997,  val_loss:0.5997,  
....................................................................................................
Epoch: 500, accuracy:0.6513,  binary_crossentropy:0.5946,  loss:0.5946,  val_accuracy:0.6480,  val_binary_crossentropy:0.5911,  val_loss:0.5911,  
....................................................................................................
Epoch: 600, accuracy:0.6636,  binary_crossentropy:0.5894,  loss:0.5894,  val_accuracy:0.6390,  val_binary_crossentropy:0.5898,  val_loss:0.5898,  
....................................................................................................
Epoch: 700, accuracy:0.6696,  binary_crossentropy:0.5852,  loss:0.5852,  val_accuracy:0.6530,  val_binary_crossentropy:0.5870,  val_loss:0.5870,  
....................................................................................................
Epoch: 800, accuracy:0.6706,  binary_crossentropy:0.5824,  loss:0.5824,  val_accuracy:0.6590,  val_binary_crossentropy:0.5850,  val_loss:0.5850,  
....................................................................................................
Epoch: 900, accuracy:0.6709,  binary_crossentropy:0.5796,  loss:0.5796,  val_accuracy:0.6680,  val_binary_crossentropy:0.5831,  val_loss:0.5831,  
....................................................................................................
Epoch: 1000, accuracy:0.6780,  binary_crossentropy:0.5769,  loss:0.5769,  val_accuracy:0.6530,  val_binary_crossentropy:0.5851,  val_loss:0.5851,  
....................................................................................................
Epoch: 1100, accuracy:0.6735,  binary_crossentropy:0.5752,  loss:0.5752,  val_accuracy:0.6620,  val_binary_crossentropy:0.5807,  val_loss:0.5807,  
....................................................................................................
Epoch: 1200, accuracy:0.6759,  binary_crossentropy:0.5729,  loss:0.5729,  val_accuracy:0.6620,  val_binary_crossentropy:0.5792,  val_loss:0.5792,  
....................................................................................................
Epoch: 1300, accuracy:0.6849,  binary_crossentropy:0.5716,  loss:0.5716,  val_accuracy:0.6450,  val_binary_crossentropy:0.5859,  val_loss:0.5859,  
....................................................................................................
Epoch: 1400, accuracy:0.6790,  binary_crossentropy:0.5695,  loss:0.5695,  val_accuracy:0.6700,  val_binary_crossentropy:0.5776,  val_loss:0.5776,  
....................................................................................................
Epoch: 1500, accuracy:0.6824,  binary_crossentropy:0.5681,  loss:0.5681,  val_accuracy:0.6730,  val_binary_crossentropy:0.5761,  val_loss:0.5761,  
....................................................................................................
Epoch: 1600, accuracy:0.6828,  binary_crossentropy:0.5669,  loss:0.5669,  val_accuracy:0.6690,  val_binary_crossentropy:0.5766,  val_loss:0.5766,  
....................................................................................................
Epoch: 1700, accuracy:0.6874,  binary_crossentropy:0.5657,  loss:0.5657,  val_accuracy:0.6600,  val_binary_crossentropy:0.5774,  val_loss:0.5774,  
....................................................................................................
Epoch: 1800, accuracy:0.6845,  binary_crossentropy:0.5655,  loss:0.5655,  val_accuracy:0.6780,  val_binary_crossentropy:0.5752,  val_loss:0.5752,  
....................................................................................................
Epoch: 1900, accuracy:0.6837,  binary_crossentropy:0.5644,  loss:0.5644,  val_accuracy:0.6790,  val_binary_crossentropy:0.5753,  val_loss:0.5753,  
....................................................................................................
Epoch: 2000, accuracy:0.6853,  binary_crossentropy:0.5632,  loss:0.5632,  val_accuracy:0.6780,  val_binary_crossentropy:0.5753,  val_loss:0.5753,  
....................................................................................................
Epoch: 2100, accuracy:0.6871,  binary_crossentropy:0.5625,  loss:0.5625,  val_accuracy:0.6670,  val_binary_crossentropy:0.5769,  val_loss:0.5769,  
...................................

ตอนนี้ตรวจสอบว่าโมเดลทำอย่างไร:

plotter = tfdocs.plots.HistoryPlotter(metric = 'binary_crossentropy', smoothing_std=10)
plotter.plot(size_histories)
plt.ylim([0.5, 0.7])
(0.5, 0.7)

png

รุ่นเล็ก

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

ลองสองชั้นที่ซ่อนอยู่โดยแต่ละหน่วยมี 16 หน่วย:

small_model = tf.keras.Sequential([
    # `input_shape` is only required here so that `.summary` works.
    layers.Dense(16, activation='elu', input_shape=(FEATURES,)),
    layers.Dense(16, activation='elu'),
    layers.Dense(1)
])
size_histories['Small'] = compile_and_fit(small_model, 'sizes/Small')
Model: "sequential_1"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense_2 (Dense)             (None, 16)                464       
                                                                 
 dense_3 (Dense)             (None, 16)                272       
                                                                 
 dense_4 (Dense)             (None, 1)                 17        
                                                                 
=================================================================
Total params: 753
Trainable params: 753
Non-trainable params: 0
_________________________________________________________________

Epoch: 0, accuracy:0.4864,  binary_crossentropy:0.7769,  loss:0.7769,  val_accuracy:0.4930,  val_binary_crossentropy:0.7211,  val_loss:0.7211,  
....................................................................................................
Epoch: 100, accuracy:0.6386,  binary_crossentropy:0.6052,  loss:0.6052,  val_accuracy:0.6020,  val_binary_crossentropy:0.6177,  val_loss:0.6177,  
....................................................................................................
Epoch: 200, accuracy:0.6697,  binary_crossentropy:0.5829,  loss:0.5829,  val_accuracy:0.6310,  val_binary_crossentropy:0.6018,  val_loss:0.6018,  
....................................................................................................
Epoch: 300, accuracy:0.6838,  binary_crossentropy:0.5721,  loss:0.5721,  val_accuracy:0.6490,  val_binary_crossentropy:0.5940,  val_loss:0.5940,  
....................................................................................................
Epoch: 400, accuracy:0.6911,  binary_crossentropy:0.5656,  loss:0.5656,  val_accuracy:0.6430,  val_binary_crossentropy:0.5985,  val_loss:0.5985,  
....................................................................................................
Epoch: 500, accuracy:0.6930,  binary_crossentropy:0.5607,  loss:0.5607,  val_accuracy:0.6430,  val_binary_crossentropy:0.6028,  val_loss:0.6028,  
.........................

รุ่นกลาง

ตอนนี้ลอง 3 เลเยอร์ที่ซ่อนอยู่โดยแต่ละ 64 ยูนิต:

medium_model = tf.keras.Sequential([
    layers.Dense(64, activation='elu', input_shape=(FEATURES,)),
    layers.Dense(64, activation='elu'),
    layers.Dense(64, activation='elu'),
    layers.Dense(1)
])

และฝึกโมเดลโดยใช้ข้อมูลเดียวกัน:

size_histories['Medium']  = compile_and_fit(medium_model, "sizes/Medium")
Model: "sequential_2"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense_5 (Dense)             (None, 64)                1856      
                                                                 
 dense_6 (Dense)             (None, 64)                4160      
                                                                 
 dense_7 (Dense)             (None, 64)                4160      
                                                                 
 dense_8 (Dense)             (None, 1)                 65        
                                                                 
=================================================================
Total params: 10,241
Trainable params: 10,241
Non-trainable params: 0
_________________________________________________________________

Epoch: 0, accuracy:0.5017,  binary_crossentropy:0.6840,  loss:0.6840,  val_accuracy:0.4790,  val_binary_crossentropy:0.6723,  val_loss:0.6723,  
....................................................................................................
Epoch: 100, accuracy:0.7173,  binary_crossentropy:0.5221,  loss:0.5221,  val_accuracy:0.6470,  val_binary_crossentropy:0.6111,  val_loss:0.6111,  
....................................................................................................
Epoch: 200, accuracy:0.7884,  binary_crossentropy:0.4270,  loss:0.4270,  val_accuracy:0.6390,  val_binary_crossentropy:0.7045,  val_loss:0.7045,  
..............................................................

รุ่นใหญ่

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

large_model = tf.keras.Sequential([
    layers.Dense(512, activation='elu', input_shape=(FEATURES,)),
    layers.Dense(512, activation='elu'),
    layers.Dense(512, activation='elu'),
    layers.Dense(512, activation='elu'),
    layers.Dense(1)
])

และอีกครั้ง ฝึกโมเดลโดยใช้ข้อมูลเดียวกัน:

size_histories['large'] = compile_and_fit(large_model, "sizes/large")
Model: "sequential_3"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense_9 (Dense)             (None, 512)               14848     
                                                                 
 dense_10 (Dense)            (None, 512)               262656    
                                                                 
 dense_11 (Dense)            (None, 512)               262656    
                                                                 
 dense_12 (Dense)            (None, 512)               262656    
                                                                 
 dense_13 (Dense)            (None, 1)                 513       
                                                                 
=================================================================
Total params: 803,329
Trainable params: 803,329
Non-trainable params: 0
_________________________________________________________________

Epoch: 0, accuracy:0.5145,  binary_crossentropy:0.7740,  loss:0.7740,  val_accuracy:0.4980,  val_binary_crossentropy:0.6793,  val_loss:0.6793,  
....................................................................................................
Epoch: 100, accuracy:1.0000,  binary_crossentropy:0.0020,  loss:0.0020,  val_accuracy:0.6600,  val_binary_crossentropy:1.8540,  val_loss:1.8540,  
....................................................................................................
Epoch: 200, accuracy:1.0000,  binary_crossentropy:0.0001,  loss:0.0001,  val_accuracy:0.6560,  val_binary_crossentropy:2.5293,  val_loss:2.5293,  
..........................

วางแผนการสูญเสียการฝึกอบรมและการตรวจสอบ

เส้นทึบแสดงถึงการสูญเสียการฝึก และเส้นประแสดงการสูญเสียการตรวจสอบ (จำไว้ว่า: การสูญเสียการตรวจสอบที่ต่ำกว่าบ่งชี้ถึงรูปแบบที่ดีกว่า)

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

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

สิ่งนี้ชัดเจนหากคุณพล็อตและเปรียบเทียบเมตริกการตรวจสอบกับเมตริกการฝึกอบรม

  • เป็นเรื่องปกติที่จะมีความแตกต่างเล็กน้อย
  • หากตัวชี้วัดทั้งสองเคลื่อนไปในทิศทางเดียวกัน ทุกอย่างก็เรียบร้อย
  • หากตัววัดการตรวจสอบเริ่มซบเซาในขณะที่ตัววัดการฝึกอบรมยังคงปรับปรุง แสดงว่าคุณใกล้จะฟิตเกินไปแล้ว
  • หากตัววัดการตรวจสอบความถูกต้องไปในทิศทางที่ไม่ถูกต้อง แสดงว่าโมเดลมีสัดส่วนมากเกินไปอย่างเห็นได้ชัด
plotter.plot(size_histories)
a = plt.xscale('log')
plt.xlim([5, max(plt.xlim())])
plt.ylim([0.5, 0.7])
plt.xlabel("Epochs [Log Scale]")
Text(0.5, 0, 'Epochs [Log Scale]')
ตัวยึดตำแหน่ง39

png

ดูใน TensorBoard

โมเดลเหล่านี้ทั้งหมดเขียนบันทึก TensorBoard ระหว่างการฝึก

เปิดโปรแกรมดู TensorBoard ที่ฝังไว้ภายในโน้ตบุ๊ก:

#docs_infra: no_execute

# Load the TensorBoard notebook extension
%load_ext tensorboard

# Open an embedded TensorBoard viewer
%tensorboard --logdir {logdir}/sizes

คุณสามารถดู ผลลัพธ์ของการรัน สมุดบันทึกนี้ครั้งก่อนได้ที่ TensorBoard.dev

TensorBoard.dev เป็นประสบการณ์ที่ได้รับการจัดการสำหรับการโฮสต์ ติดตาม และแชร์การทดลอง ML กับทุกคน

รวมอยู่ใน <iframe> เพื่อความสะดวก:

display.IFrame(
    src="https://tensorboard.dev/experiment/vW7jmmF9TmKmy3rbheMQpw/#scalars&_smoothingWeight=0.97",
    width="100%", height="800px")

หากคุณต้องการแชร์ผลลัพธ์ของ TensorBoard คุณสามารถอัปโหลดบันทึกไปยัง TensorBoard.dev โดยคัดลอกสิ่งต่อไปนี้ลงในเซลล์รหัส

tensorboard dev upload --logdir  {logdir}/sizes

กลยุทธ์ป้องกันการใส่มากเกินไป

ก่อนเข้าสู่เนื้อหาในส่วนนี้ ให้คัดลอกบันทึกการฝึกจากโมเดล "Tiny" ด้านบน เพื่อใช้เป็นข้อมูลพื้นฐานในการเปรียบเทียบ

shutil.rmtree(logdir/'regularizers/Tiny', ignore_errors=True)
shutil.copytree(logdir/'sizes/Tiny', logdir/'regularizers/Tiny')
PosixPath('/tmp/tmpn1rdh98q/tensorboard_logs/regularizers/Tiny')
regularizer_histories = {}
regularizer_histories['Tiny'] = size_histories['Tiny']

เพิ่มการปรับน้ำหนักให้สม่ำเสมอ

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

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

  • การทำให้เป็นมาตรฐาน L1 โดยที่ต้นทุนที่เพิ่มเป็นสัดส่วนกับค่าสัมบูรณ์ของสัมประสิทธิ์น้ำหนัก (กล่าวคือ กับสิ่งที่เรียกว่า "บรรทัดฐาน L1" ของตุ้มน้ำหนัก)

  • การทำให้เป็นมาตรฐาน L2 โดยที่ต้นทุนเพิ่มเป็นสัดส่วนกับกำลังสองของค่าสัมประสิทธิ์น้ำหนัก (กล่าวคือ เรียกว่า "บรรทัดฐาน L2" กำลังสองของตุ้มน้ำหนัก) การทำให้เป็นมาตรฐาน L2 เรียกอีกอย่างว่าการลดน้ำหนักในบริบทของโครงข่ายประสาทเทียม อย่าปล่อยให้ชื่ออื่นสร้างความสับสนให้กับคุณ: น้ำหนักที่ลดลงนั้นทางคณิตศาสตร์เหมือนกับการทำให้เป็นมาตรฐาน L2

การทำให้เป็นมาตรฐาน L1 ผลักน้ำหนักไปที่ศูนย์พอดีกระตุ้นให้เกิดแบบจำลองที่กระจัดกระจาย การทำให้เป็นมาตรฐานของ L2 จะลงโทษพารามิเตอร์น้ำหนักโดยไม่ทำให้เบาบาง เนื่องจากการปรับให้เป็นศูนย์สำหรับน้ำหนักขนาดเล็ก เหตุผลหนึ่งที่ทำให้ L2 เป็นเรื่องธรรมดามากกว่า

ใน tf.keras การปรับน้ำหนักให้เป็นมาตรฐานจะถูกเพิ่มโดยการส่งผ่านอินสแตนซ์ตัวปรับน้ำหนักไปยังเลเยอร์เป็นอาร์กิวเมนต์ของคำหลัก มาเพิ่มการปรับน้ำหนัก L2 กันเถอะ

l2_model = tf.keras.Sequential([
    layers.Dense(512, activation='elu',
                 kernel_regularizer=regularizers.l2(0.001),
                 input_shape=(FEATURES,)),
    layers.Dense(512, activation='elu',
                 kernel_regularizer=regularizers.l2(0.001)),
    layers.Dense(512, activation='elu',
                 kernel_regularizer=regularizers.l2(0.001)),
    layers.Dense(512, activation='elu',
                 kernel_regularizer=regularizers.l2(0.001)),
    layers.Dense(1)
])

regularizer_histories['l2'] = compile_and_fit(l2_model, "regularizers/l2")
Model: "sequential_4"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense_14 (Dense)            (None, 512)               14848     
                                                                 
 dense_15 (Dense)            (None, 512)               262656    
                                                                 
 dense_16 (Dense)            (None, 512)               262656    
                                                                 
 dense_17 (Dense)            (None, 512)               262656    
                                                                 
 dense_18 (Dense)            (None, 1)                 513       
                                                                 
=================================================================
Total params: 803,329
Trainable params: 803,329
Non-trainable params: 0
_________________________________________________________________

Epoch: 0, accuracy:0.5126,  binary_crossentropy:0.7481,  loss:2.2415,  val_accuracy:0.4950,  val_binary_crossentropy:0.6707,  val_loss:2.0653,  
....................................................................................................
Epoch: 100, accuracy:0.6625,  binary_crossentropy:0.5945,  loss:0.6173,  val_accuracy:0.6400,  val_binary_crossentropy:0.5871,  val_loss:0.6100,  
....................................................................................................
Epoch: 200, accuracy:0.6690,  binary_crossentropy:0.5864,  loss:0.6079,  val_accuracy:0.6650,  val_binary_crossentropy:0.5856,  val_loss:0.6076,  
....................................................................................................
Epoch: 300, accuracy:0.6790,  binary_crossentropy:0.5762,  loss:0.5976,  val_accuracy:0.6550,  val_binary_crossentropy:0.5881,  val_loss:0.6095,  
....................................................................................................
Epoch: 400, accuracy:0.6843,  binary_crossentropy:0.5697,  loss:0.5920,  val_accuracy:0.6650,  val_binary_crossentropy:0.5878,  val_loss:0.6101,  
....................................................................................................
Epoch: 500, accuracy:0.6897,  binary_crossentropy:0.5651,  loss:0.5907,  val_accuracy:0.6890,  val_binary_crossentropy:0.5798,  val_loss:0.6055,  
....................................................................................................
Epoch: 600, accuracy:0.6945,  binary_crossentropy:0.5610,  loss:0.5864,  val_accuracy:0.6820,  val_binary_crossentropy:0.5772,  val_loss:0.6026,  
..........................................................

l2(0.001) หมายความว่าทุกสัมประสิทธิ์ในเมทริกซ์น้ำหนักของเลเยอร์จะเพิ่ม 0.001 * weight_coefficient_value**2 ให้กับการ สูญเสีย ทั้งหมดของเครือข่าย

นั่นคือเหตุผลที่เรากำลังตรวจสอบ binary_crossentropy โดยตรง เนื่องจากไม่มีองค์ประกอบการทำให้เป็นมาตรฐานนี้ผสมอยู่

ดังนั้น โมเดล "Large" แบบเดียวกันที่มีการ L2 ให้เป็นมาตรฐานจึงทำงานได้ดีกว่ามาก:

plotter.plot(regularizer_histories)
plt.ylim([0.5, 0.7])
(0.5, 0.7)

png

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

ข้อมูลเพิ่มเติม

มีสองสิ่งสำคัญที่ควรทราบเกี่ยวกับการทำให้เป็นมาตรฐานประเภทนี้

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

result = l2_model(features)
regularization_loss=tf.add_n(l2_model.losses)

ประการที่สอง: การใช้งานนี้ทำงานโดยเพิ่มบทลงโทษด้านน้ำหนักให้กับการสูญเสียของแบบจำลอง จากนั้นจึงใช้ขั้นตอนการเพิ่มประสิทธิภาพมาตรฐานหลังจากนั้น

มีวิธีที่สองที่เรียกใช้ตัวเพิ่มประสิทธิภาพเฉพาะกับการสูญเสียดิบแทน จากนั้นในขณะที่ใช้ขั้นตอนที่คำนวณ โปรแกรมเพิ่มประสิทธิภาพก็ใช้การลดน้ำหนักบางส่วนด้วย "การสลายตัวของน้ำหนักแบบแยกส่วน" นี้มีให้เห็นในเครื่องมือเพิ่มประสิทธิภาพ เช่น optimizers.FTRL และ optimizers.AdamW

เพิ่มการออกกลางคัน

Dropout เป็นหนึ่งในเทคนิคการทำให้เป็นมาตรฐานและมีประสิทธิภาพมากที่สุดสำหรับโครงข่ายประสาทเทียม พัฒนาโดยฮินตันและนักศึกษาของเขาที่มหาวิทยาลัยโตรอนโต

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

การออกกลางคัน ใช้กับเลเยอร์ประกอบด้วย "การออกจากระบบ" แบบสุ่ม (เช่น ตั้งค่าเป็นศูนย์) คุณลักษณะเอาต์พุตจำนวนหนึ่งของเลเยอร์ระหว่างการฝึก สมมติว่าเลเยอร์ที่กำหนดโดยปกติจะส่งเวกเตอร์ [0.2, 0.5, 1.3, 0.8, 1.1] สำหรับตัวอย่างอินพุตที่กำหนดระหว่างการฝึก หลังจากใช้ dropout เวกเตอร์นี้จะมีรายการศูนย์สองสามรายการโดยสุ่มแจก เช่น [0, 0.5, 1.3, 0, 1.1]

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

ใน tf.keras คุณสามารถแนะนำ dropout ในเครือข่ายผ่านเลเยอร์ Dropout ซึ่งจะนำไปใช้กับเอาต์พุตของเลเยอร์ก่อนหน้านี้

มาเพิ่มเลเยอร์ Dropout สองเลเยอร์ในเครือข่ายของเราเพื่อดูว่าพวกมันช่วยลดการโอเวอร์ฟิตได้ดีเพียงใด:

dropout_model = tf.keras.Sequential([
    layers.Dense(512, activation='elu', input_shape=(FEATURES,)),
    layers.Dropout(0.5),
    layers.Dense(512, activation='elu'),
    layers.Dropout(0.5),
    layers.Dense(512, activation='elu'),
    layers.Dropout(0.5),
    layers.Dense(512, activation='elu'),
    layers.Dropout(0.5),
    layers.Dense(1)
])

regularizer_histories['dropout'] = compile_and_fit(dropout_model, "regularizers/dropout")
Model: "sequential_5"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense_19 (Dense)            (None, 512)               14848     
                                                                 
 dropout (Dropout)           (None, 512)               0         
                                                                 
 dense_20 (Dense)            (None, 512)               262656    
                                                                 
 dropout_1 (Dropout)         (None, 512)               0         
                                                                 
 dense_21 (Dense)            (None, 512)               262656    
                                                                 
 dropout_2 (Dropout)         (None, 512)               0         
                                                                 
 dense_22 (Dense)            (None, 512)               262656    
                                                                 
 dropout_3 (Dropout)         (None, 512)               0         
                                                                 
 dense_23 (Dense)            (None, 1)                 513       
                                                                 
=================================================================
Total params: 803,329
Trainable params: 803,329
Non-trainable params: 0
_________________________________________________________________

Epoch: 0, accuracy:0.4961,  binary_crossentropy:0.8110,  loss:0.8110,  val_accuracy:0.5330,  val_binary_crossentropy:0.6900,  val_loss:0.6900,  
....................................................................................................
Epoch: 100, accuracy:0.6557,  binary_crossentropy:0.5961,  loss:0.5961,  val_accuracy:0.6710,  val_binary_crossentropy:0.5788,  val_loss:0.5788,  
....................................................................................................
Epoch: 200, accuracy:0.6871,  binary_crossentropy:0.5622,  loss:0.5622,  val_accuracy:0.6860,  val_binary_crossentropy:0.5856,  val_loss:0.5856,  
....................................................................................................
Epoch: 300, accuracy:0.7246,  binary_crossentropy:0.5121,  loss:0.5121,  val_accuracy:0.6820,  val_binary_crossentropy:0.5927,  val_loss:0.5927,  
............
plotter.plot(regularizer_histories)
plt.ylim([0.5, 0.7])
(0.5, 0.7)

png

จากพล็อตนี้ชัดเจนแล้วว่าแนวทางการทำให้เป็นมาตรฐานทั้งสองนี้ช่วยปรับปรุงพฤติกรรมของโมเดล "Large" แต่สิ่งนี้ก็ยังไม่สามารถเอาชนะแม้แต่เส้นฐานที่ "Tiny" ได้

ต่อไปลองทั้งสองอย่างรวมกันแล้วดูว่าดีขึ้นหรือไม่

รวม L2 + การออกกลางคัน

combined_model = tf.keras.Sequential([
    layers.Dense(512, kernel_regularizer=regularizers.l2(0.0001),
                 activation='elu', input_shape=(FEATURES,)),
    layers.Dropout(0.5),
    layers.Dense(512, kernel_regularizer=regularizers.l2(0.0001),
                 activation='elu'),
    layers.Dropout(0.5),
    layers.Dense(512, kernel_regularizer=regularizers.l2(0.0001),
                 activation='elu'),
    layers.Dropout(0.5),
    layers.Dense(512, kernel_regularizer=regularizers.l2(0.0001),
                 activation='elu'),
    layers.Dropout(0.5),
    layers.Dense(1)
])

regularizer_histories['combined'] = compile_and_fit(combined_model, "regularizers/combined")
Model: "sequential_6"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense_24 (Dense)            (None, 512)               14848     
                                                                 
 dropout_4 (Dropout)         (None, 512)               0         
                                                                 
 dense_25 (Dense)            (None, 512)               262656    
                                                                 
 dropout_5 (Dropout)         (None, 512)               0         
                                                                 
 dense_26 (Dense)            (None, 512)               262656    
                                                                 
 dropout_6 (Dropout)         (None, 512)               0         
                                                                 
 dense_27 (Dense)            (None, 512)               262656    
                                                                 
 dropout_7 (Dropout)         (None, 512)               0         
                                                                 
 dense_28 (Dense)            (None, 1)                 513       
                                                                 
=================================================================
Total params: 803,329
Trainable params: 803,329
Non-trainable params: 0
_________________________________________________________________

Epoch: 0, accuracy:0.5090,  binary_crossentropy:0.8064,  loss:0.9648,  val_accuracy:0.4660,  val_binary_crossentropy:0.6877,  val_loss:0.8454,  
....................................................................................................
Epoch: 100, accuracy:0.6445,  binary_crossentropy:0.6050,  loss:0.6350,  val_accuracy:0.6630,  val_binary_crossentropy:0.5871,  val_loss:0.6169,  
....................................................................................................
Epoch: 200, accuracy:0.6660,  binary_crossentropy:0.5932,  loss:0.6186,  val_accuracy:0.6880,  val_binary_crossentropy:0.5722,  val_loss:0.5975,  
....................................................................................................
Epoch: 300, accuracy:0.6697,  binary_crossentropy:0.5818,  loss:0.6100,  val_accuracy:0.6900,  val_binary_crossentropy:0.5614,  val_loss:0.5895,  
....................................................................................................
Epoch: 400, accuracy:0.6749,  binary_crossentropy:0.5742,  loss:0.6046,  val_accuracy:0.6870,  val_binary_crossentropy:0.5576,  val_loss:0.5881,  
....................................................................................................
Epoch: 500, accuracy:0.6854,  binary_crossentropy:0.5703,  loss:0.6029,  val_accuracy:0.6970,  val_binary_crossentropy:0.5458,  val_loss:0.5784,  
....................................................................................................
Epoch: 600, accuracy:0.6806,  binary_crossentropy:0.5673,  loss:0.6015,  val_accuracy:0.6980,  val_binary_crossentropy:0.5453,  val_loss:0.5795,  
....................................................................................................
Epoch: 700, accuracy:0.6937,  binary_crossentropy:0.5583,  loss:0.5938,  val_accuracy:0.6870,  val_binary_crossentropy:0.5477,  val_loss:0.5832,  
....................................................................................................
Epoch: 800, accuracy:0.6911,  binary_crossentropy:0.5576,  loss:0.5947,  val_accuracy:0.7000,  val_binary_crossentropy:0.5446,  val_loss:0.5817,  
.......................
plotter.plot(regularizer_histories)
plt.ylim([0.5, 0.7])
(0.5, 0.7)

png

โมเดลที่มีการทำให้เป็นมาตรฐาน "Combined" นี้เห็นได้ชัดว่าเป็นโมเดลที่ดีที่สุด

ดูใน TensorBoard

โมเดลเหล่านี้ยังบันทึกบันทึก TensorBoard

ในการเปิดดูเทนเซอร์บอร์ดที่ฝังไว้ภายในโน้ตบุ๊ก ให้คัดลอกสิ่งต่อไปนี้ลงในเซลล์โค้ด:

%tensorboard --logdir {logdir}/regularizers

คุณสามารถดู ผลลัพธ์ของการรัน สมุดบันทึกนี้ครั้งก่อนได้ที่ TensorDoard.dev

รวมอยู่ใน <iframe> เพื่อความสะดวก:

display.IFrame(
    src="https://tensorboard.dev/experiment/fGInKDo8TXes1z7HQku9mw/#scalars&_smoothingWeight=0.97",
    width = "100%",
    height="800px")

นี้ถูกอัปโหลดด้วย:

tensorboard dev upload --logdir  {logdir}/regularizers

บทสรุป

เพื่อสรุป: ต่อไปนี้เป็นวิธีทั่วไปในการป้องกันการ overfitting ในโครงข่ายประสาทเทียม:

  • รับข้อมูลการฝึกอบรมเพิ่มเติม
  • ลดความจุของเครือข่าย
  • เพิ่มการปรับน้ำหนักให้สม่ำเสมอ
  • เพิ่มการออกกลางคัน

แนวทางสำคัญสองประการที่ไม่ได้กล่าวถึงในคู่มือนี้คือ:

  • ข้อมูลเสริม
  • การทำให้เป็นมาตรฐานแบบแบตช์

โปรดจำไว้ว่าแต่ละวิธีสามารถช่วยได้ด้วยตัวเอง แต่บ่อยครั้งที่การรวมเข้าด้วยกันอาจมีประสิทธิภาพมากกว่า

# MIT License
#
# Copyright (c) 2017 François Chollet
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.