Bantuan melindungi Great Barrier Reef dengan TensorFlow pada Kaggle Bergabung Tantangan

Pakaian berlebih dan pakaian dalam

Lihat di TensorFlow.org Jalankan di Google Colab Lihat sumber di GitHub Unduh buku catatan

Seperti biasa, kode dalam contoh ini akan menggunakan tf.keras API, yang dapat Anda mempelajari lebih lanjut tentang di TensorFlow Keras panduan .

Dalam kedua examples- sebelumnya teks mengklasifikasikan dan memprediksi efisiensi bahan bakar - kita melihat bahwa akurasi model kami pada data validasi akan mencapai puncaknya setelah pelatihan untuk sejumlah zaman, dan kemudian akan stagnan atau mulai menurun.

Dengan kata lain, model kami akan overfit untuk data pelatihan. Mempelajari cara menangani overfitting itu penting. Meskipun sering mungkin untuk mencapai akurasi yang tinggi pada set pelatihan, apa yang kita inginkan adalah untuk mengembangkan model yang menggeneralisasi dengan baik untuk satu set pengujian (atau data mereka belum pernah melihat sebelumnya).

Kebalikan dari overfitting adalah underfitting. Underfitting terjadi ketika masih ada ruang untuk perbaikan pada data kereta api. Hal ini dapat terjadi karena beberapa alasan: Jika model tidak cukup kuat, terlalu diatur, atau tidak cukup lama dilatih. Ini berarti jaringan belum mempelajari pola yang relevan dalam data pelatihan.

Jika Anda berlatih terlalu lama, model akan mulai menyesuaikan dan mempelajari pola dari data pelatihan yang tidak digeneralisasi ke data pengujian. Kita perlu mencapai keseimbangan. Memahami cara melatih untuk jumlah epoch yang sesuai seperti yang akan kita jelajahi di bawah ini adalah keterampilan yang berguna.

Untuk mencegah overfitting, solusi terbaik adalah menggunakan data pelatihan yang lebih lengkap. Dataset harus mencakup berbagai input yang diharapkan dapat ditangani oleh model. Data tambahan mungkin hanya berguna jika mencakup kasus-kasus baru dan menarik.

Model yang dilatih pada data yang lebih lengkap secara alami akan menggeneralisasi lebih baik. Ketika itu tidak mungkin lagi, solusi terbaik berikutnya adalah menggunakan teknik seperti regularisasi. Ini menempatkan batasan pada kuantitas dan jenis informasi yang dapat disimpan oleh model Anda. Jika jaringan hanya mampu menghafal sejumlah kecil pola, proses optimasi akan memaksanya untuk fokus pada pola yang paling menonjol, yang memiliki peluang lebih baik untuk menggeneralisasi dengan baik.

Dalam buku catatan ini, kita akan mengeksplorasi beberapa teknik regularisasi umum, dan menggunakannya untuk memperbaiki model klasifikasi.

Mempersiapkan

Sebelum memulai, impor paket yang diperlukan:

import tensorflow as tf

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

print(tf.__version__)
2.5.0
!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)

Kumpulan Data Higgs

Tujuan dari tutorial ini bukan untuk melakukan fisika partikel, jadi jangan terpaku pada detail dataset. Ini berisi 11.000.000 contoh, masing-masing dengan 28 fitur, dan label kelas biner.

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 [==============================] - 148s 0us/step
FEATURES = 28

The tf.data.experimental.CsvDataset kelas dapat digunakan untuk membaca catatan csv langsung dari file gzip tanpa langkah dekompresi menengah.

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

Kelas pembaca csv itu mengembalikan daftar skalar untuk setiap catatan. Fungsi berikut mengemas ulang daftar skalar tersebut menjadi pasangan (feature_vector, label).

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

TensorFlow paling efisien saat beroperasi pada kumpulan data yang besar.

Jadi, bukannya repacking setiap baris secara individual membuat baru Dataset yang mengambil batch 10000-contoh, menerapkan pack_row fungsi untuk setiap batch, dan kemudian membagi batch cadangan ke dalam catatan individu:

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

Silahkan lihat pada beberapa catatan dari ini baru packed_ds .

Fitur-fiturnya tidak dinormalisasi dengan sempurna, tetapi ini cukup untuk tutorial ini.

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

Agar tutorial ini relatif singkat, gunakan hanya 1000 sampel pertama untuk validasi, dan 10.000 berikutnya untuk pelatihan:

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

The Dataset.skip dan Dataset.take metode membuat ini mudah.

Pada saat yang sama, menggunakan Dataset.cache metode untuk memastikan bahwa loader tidak perlu membaca kembali data dari file pada setiap zaman:

validate_ds = packed_ds.take(N_VALIDATION).cache()
train_ds = packed_ds.skip(N_VALIDATION).take(N_TRAIN).cache()
train_ds
<CacheDataset shapes: ((28,), ()), types: (tf.float32, tf.float32)>

Kumpulan data ini mengembalikan contoh individual. Gunakan .batch metode untuk membuat batch ukuran yang sesuai untuk pelatihan. Sebelum batching juga ingat untuk .shuffle dan .repeat training set.

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

Mendemonstrasikan overfitting

Cara paling sederhana untuk mencegah overfitting adalah memulai dengan model kecil: Model dengan sejumlah kecil parameter yang dapat dipelajari (yang ditentukan oleh jumlah lapisan dan jumlah unit per lapisan). Dalam pembelajaran mendalam, jumlah parameter yang dapat dipelajari dalam suatu model sering disebut sebagai "kapasitas" model.

Secara intuitif, model dengan lebih banyak parameter akan memiliki lebih banyak "kapasitas menghafal" dan oleh karena itu akan dapat dengan mudah mempelajari pemetaan seperti kamus yang sempurna antara sampel pelatihan dan targetnya, pemetaan tanpa kekuatan generalisasi apa pun, tetapi ini tidak akan berguna saat membuat prediksi pada data yang sebelumnya tidak terlihat.

Ingatlah selalu hal ini: model pembelajaran mendalam cenderung bagus dalam menyesuaikan dengan data pelatihan, tetapi tantangan sebenarnya adalah generalisasi, tidak pas.

Di sisi lain, jika jaringan memiliki sumber daya memori yang terbatas, ia tidak akan dapat mempelajari pemetaan dengan mudah. Untuk meminimalkan kerugiannya, ia harus mempelajari representasi terkompresi yang memiliki lebih banyak kekuatan prediktif. Pada saat yang sama, jika Anda membuat model Anda terlalu kecil, itu akan mengalami kesulitan untuk menyesuaikan dengan data pelatihan. Ada keseimbangan antara "kapasitas terlalu banyak" dan "kapasitas tidak cukup".

Sayangnya, tidak ada formula ajaib untuk menentukan ukuran atau arsitektur model yang tepat (dalam hal jumlah lapisan, atau ukuran yang tepat untuk setiap lapisan). Anda harus bereksperimen menggunakan serangkaian arsitektur yang berbeda.

Untuk menemukan ukuran model yang sesuai, yang terbaik adalah memulai dengan lapisan dan parameter yang relatif sedikit, kemudian mulai meningkatkan ukuran lapisan atau menambahkan lapisan baru sampai Anda melihat hasil yang semakin berkurang pada hilangnya validasi.

Mulailah dengan model sederhana hanya menggunakan layers.Dense sebagai dasar, kemudian membuat versi yang lebih besar, dan membandingkan mereka.

Prosedur pelatihan

Banyak model berlatih lebih baik jika Anda secara bertahap mengurangi kecepatan belajar selama pelatihan. Gunakan optimizers.schedules untuk mengurangi tingkat pembelajaran dari waktu ke waktu:

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)

Kode di atas set yang schedules.InverseTimeDecay untuk hyperbolically menurunkan tingkat belajar untuk 1/2 dari tingkat dasar pada 1000 zaman, 1/3 pada 2000 zaman dan sebagainya.

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

Setiap model dalam tutorial ini akan menggunakan konfigurasi pelatihan yang sama. Jadi atur ini dengan cara yang dapat digunakan kembali, dimulai dengan daftar panggilan balik.

Pelatihan untuk tutorial ini berjalan untuk banyak waktu singkat. Untuk mengurangi penebangan kebisingan menggunakan tfdocs.EpochDots yang hanya mencetak . untuk setiap zaman, dan satu set metrik lengkap setiap 100 zaman.

Berikutnya meliputi callbacks.EarlyStopping untuk menghindari panjang dan tidak perlu kali pelatihan. Perhatikan bahwa callback ini diatur untuk memantau val_binary_crossentropy , bukan val_loss . Perbedaan ini akan menjadi penting nantinya.

Gunakan callbacks.TensorBoard untuk menghasilkan TensorBoard log untuk pelatihan.

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

Demikian pula masing-masing model akan menggunakan sama Model.compile dan Model.fit pengaturan:

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

Model mungil

Mulailah dengan melatih model:

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
_________________________________________________________________
WARNING:tensorflow:Callback method `on_train_batch_begin` is slow compared to the batch time (batch time: 0.0031s vs `on_train_batch_begin` time: 0.0346s). Check your callbacks.
WARNING:tensorflow:Callback method `on_train_batch_end` is slow compared to the batch time (batch time: 0.0031s vs `on_train_batch_end` time: 0.0125s). Check your callbacks.

Epoch: 0, accuracy:0.5093,  binary_crossentropy:0.7681,  loss:0.7681,  val_accuracy:0.5000,  val_binary_crossentropy:0.7207,  val_loss:0.7207,  
....................................................................................................
Epoch: 100, accuracy:0.6058,  binary_crossentropy:0.6244,  loss:0.6244,  val_accuracy:0.5700,  val_binary_crossentropy:0.6322,  val_loss:0.6322,  
....................................................................................................
Epoch: 200, accuracy:0.6220,  binary_crossentropy:0.6124,  loss:0.6124,  val_accuracy:0.5990,  val_binary_crossentropy:0.6202,  val_loss:0.6202,  
....................................................................................................
Epoch: 300, accuracy:0.6388,  binary_crossentropy:0.6045,  loss:0.6045,  val_accuracy:0.6150,  val_binary_crossentropy:0.6114,  val_loss:0.6114,  
....................................................................................................
Epoch: 400, accuracy:0.6475,  binary_crossentropy:0.5976,  loss:0.5976,  val_accuracy:0.6270,  val_binary_crossentropy:0.6012,  val_loss:0.6012,  
....................................................................................................
Epoch: 500, accuracy:0.6579,  binary_crossentropy:0.5917,  loss:0.5917,  val_accuracy:0.6390,  val_binary_crossentropy:0.5929,  val_loss:0.5929,  
....................................................................................................
Epoch: 600, accuracy:0.6662,  binary_crossentropy:0.5878,  loss:0.5878,  val_accuracy:0.6410,  val_binary_crossentropy:0.5890,  val_loss:0.5890,  
....................................................................................................
Epoch: 700, accuracy:0.6664,  binary_crossentropy:0.5847,  loss:0.5847,  val_accuracy:0.6670,  val_binary_crossentropy:0.5865,  val_loss:0.5865,  
....................................................................................................
Epoch: 800, accuracy:0.6709,  binary_crossentropy:0.5822,  loss:0.5822,  val_accuracy:0.6460,  val_binary_crossentropy:0.5896,  val_loss:0.5896,  
....................................................................................................
Epoch: 900, accuracy:0.6772,  binary_crossentropy:0.5793,  loss:0.5793,  val_accuracy:0.6540,  val_binary_crossentropy:0.5880,  val_loss:0.5880,  
...................

Sekarang periksa bagaimana model melakukannya:

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

Model kecil

Untuk melihat apakah Anda dapat mengalahkan kinerja model kecil, latih beberapa model yang lebih besar secara bertahap.

Coba dua lapisan tersembunyi dengan masing-masing 16 unit:

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
_________________________________________________________________
WARNING:tensorflow:Callback method `on_train_batch_begin` is slow compared to the batch time (batch time: 0.0030s vs `on_train_batch_begin` time: 0.0258s). Check your callbacks.
WARNING:tensorflow:Callback method `on_train_batch_end` is slow compared to the batch time (batch time: 0.0030s vs `on_train_batch_end` time: 0.0176s). Check your callbacks.

Epoch: 0, accuracy:0.4757,  binary_crossentropy:0.7130,  loss:0.7130,  val_accuracy:0.4630,  val_binary_crossentropy:0.7012,  val_loss:0.7012,  
....................................................................................................
Epoch: 100, accuracy:0.6295,  binary_crossentropy:0.6092,  loss:0.6092,  val_accuracy:0.6120,  val_binary_crossentropy:0.6145,  val_loss:0.6145,  
....................................................................................................
Epoch: 200, accuracy:0.6575,  binary_crossentropy:0.5879,  loss:0.5879,  val_accuracy:0.6520,  val_binary_crossentropy:0.5976,  val_loss:0.5976,  
....................................................................................................
Epoch: 300, accuracy:0.6758,  binary_crossentropy:0.5774,  loss:0.5774,  val_accuracy:0.6610,  val_binary_crossentropy:0.5958,  val_loss:0.5958,  
....................................................................................................
Epoch: 400, accuracy:0.6830,  binary_crossentropy:0.5698,  loss:0.5698,  val_accuracy:0.6690,  val_binary_crossentropy:0.5949,  val_loss:0.5949,  
....................................................................................................
Epoch: 500, accuracy:0.6873,  binary_crossentropy:0.5650,  loss:0.5650,  val_accuracy:0.6720,  val_binary_crossentropy:0.5930,  val_loss:0.5930,  
....................................................................................................
Epoch: 600, accuracy:0.6923,  binary_crossentropy:0.5600,  loss:0.5600,  val_accuracy:0.6570,  val_binary_crossentropy:0.5946,  val_loss:0.5946,  
......................................................

Model sedang

Sekarang coba 3 lapisan tersembunyi dengan masing-masing 64 unit:

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

Dan latih model menggunakan data yang sama:

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
_________________________________________________________________
WARNING:tensorflow:Callback method `on_train_batch_begin` is slow compared to the batch time (batch time: 0.0033s vs `on_train_batch_begin` time: 0.0251s). Check your callbacks.
WARNING:tensorflow:Callback method `on_train_batch_end` is slow compared to the batch time (batch time: 0.0033s vs `on_train_batch_end` time: 0.0189s). Check your callbacks.

Epoch: 0, accuracy:0.5026,  binary_crossentropy:0.6944,  loss:0.6944,  val_accuracy:0.4740,  val_binary_crossentropy:0.6830,  val_loss:0.6830,  
....................................................................................................
Epoch: 100, accuracy:0.7164,  binary_crossentropy:0.5242,  loss:0.5242,  val_accuracy:0.6490,  val_binary_crossentropy:0.6316,  val_loss:0.6316,  
....................................................................................................
Epoch: 200, accuracy:0.7919,  binary_crossentropy:0.4224,  loss:0.4224,  val_accuracy:0.6480,  val_binary_crossentropy:0.7022,  val_loss:0.7022,  
.......................................

Model besar

Sebagai latihan, Anda dapat membuat model yang lebih besar lagi, dan melihat seberapa cepat model tersebut mulai overfitting. Selanjutnya, mari tambahkan ke tolok ukur ini jaringan yang memiliki kapasitas lebih banyak, jauh lebih banyak daripada yang dijamin oleh masalah:

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

Dan, sekali lagi, latih model menggunakan data yang sama:

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
_________________________________________________________________
WARNING:tensorflow:Callback method `on_train_batch_begin` is slow compared to the batch time (batch time: 0.0033s vs `on_train_batch_begin` time: 0.0237s). Check your callbacks.
WARNING:tensorflow:Callback method `on_train_batch_end` is slow compared to the batch time (batch time: 0.0033s vs `on_train_batch_end` time: 0.0182s). Check your callbacks.

Epoch: 0, accuracy:0.5116,  binary_crossentropy:0.7680,  loss:0.7680,  val_accuracy:0.5440,  val_binary_crossentropy:0.6753,  val_loss:0.6753,  
....................................................................................................
Epoch: 100, accuracy:1.0000,  binary_crossentropy:0.0021,  loss:0.0021,  val_accuracy:0.6610,  val_binary_crossentropy:1.8058,  val_loss:1.8058,  
....................................................................................................
Epoch: 200, accuracy:1.0000,  binary_crossentropy:0.0001,  loss:0.0001,  val_accuracy:0.6500,  val_binary_crossentropy:2.4712,  val_loss:2.4712,  
.........................

Plot kerugian pelatihan dan validasi

Garis padat menunjukkan kehilangan pelatihan, dan garis putus-putus menunjukkan kehilangan validasi (ingat: kehilangan validasi yang lebih rendah menunjukkan model yang lebih baik).

Sementara membangun model yang lebih besar memberikan lebih banyak kekuatan, jika kekuatan ini tidak dibatasi entah bagaimana dapat dengan mudah overfit ke set pelatihan.

Dalam contoh ini, biasanya, hanya "Tiny" Model berhasil menghindari overfitting sama sekali, dan masing-masing model yang lebih besar overfit data lebih cepat. Hal ini menjadi sangat parah untuk "large" model yang Anda butuhkan untuk beralih plot untuk log-besaran untuk benar-benar melihat apa yang terjadi.

Ini terlihat jika Anda memplot dan membandingkan metrik validasi dengan metrik pelatihan.

  • Itu normal untuk ada perbedaan kecil.
  • Jika kedua metrik bergerak ke arah yang sama, semuanya baik-baik saja.
  • Jika metrik validasi mulai mandek sementara metrik pelatihan terus meningkat, Anda mungkin mendekati overfitting.
  • Jika metrik validasi berjalan ke arah yang salah, modelnya jelas overfitting.
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]')

png

Lihat di TensorBoard

Semua model ini menulis log TensorBoard selama pelatihan.

Buka penampil TensorBoard yang disematkan di dalam buku catatan:


# Load the TensorBoard notebook extension
%load_ext tensorboard

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

Anda dapat melihat hasil menjalankan sebelumnya dari notebook ini pada TensorBoard.dev .

TensorBoard.dev adalah pengalaman terkelola untuk menghosting, melacak, dan berbagi eksperimen ML dengan semua orang.

Ini juga termasuk dalam <iframe> untuk kenyamanan:

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

Jika Anda ingin berbagi TensorBoard hasil yang Anda dapat meng-upload log untuk TensorBoard.dev dengan menyalin berikut ke dalam sel kode.

tensorboard dev upload --logdir  {logdir}/sizes

Strategi untuk mencegah overfitting

Sebelum masuk ke isi bagian ini menyalin log pelatihan dari "Tiny" model di atas, untuk digunakan sebagai dasar untuk perbandingan.

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

Tambahkan regularisasi berat badan

Anda mungkin akrab dengan prinsip Occam's Razor: jika diberikan dua penjelasan untuk sesuatu, penjelasan yang paling mungkin benar adalah yang "paling sederhana", yang membuat asumsi paling sedikit. Ini juga berlaku untuk model yang dipelajari oleh jaringan saraf: mengingat beberapa data pelatihan dan arsitektur jaringan, ada beberapa set nilai bobot (beberapa model) yang dapat menjelaskan data, dan model yang lebih sederhana cenderung tidak terlalu cocok daripada model yang kompleks.

"Model sederhana" dalam konteks ini adalah model di mana distribusi nilai parameter memiliki entropi yang lebih sedikit (atau model dengan parameter yang lebih sedikit, seperti yang kita lihat pada bagian di atas). Jadi cara umum untuk mengurangi overfitting adalah dengan memberikan batasan pada kompleksitas jaringan dengan memaksa bobotnya hanya untuk mengambil nilai kecil, yang membuat distribusi nilai bobot lebih "teratur". Ini disebut "regularisasi bobot", dan ini dilakukan dengan menambahkan fungsi kerugian jaringan dengan biaya yang terkait dengan bobot yang besar. Biaya ini datang dalam dua rasa:

  • L1 regularisasi , di mana biaya tambahan sebanding dengan nilai absolut dari koefisien bobot (yaitu untuk apa yang disebut "L1 norma" dari bobot).

  • L2 regularisasi , di mana biaya tambahan adalah sebanding dengan kuadrat dari nilai koefisien bobot (yaitu untuk apa yang disebut squared "L2 norma" dari bobot). Regularisasi L2 juga disebut peluruhan bobot dalam konteks jaringan saraf. Jangan biarkan nama yang berbeda membingungkan Anda: penurunan berat badan secara matematis sama persis dengan regularisasi L2.

Regularisasi L1 mendorong bobot menuju tepat nol mendorong model yang jarang. Regularisasi L2 akan menghukum parameter bobot tanpa membuatnya jarang karena penalti menjadi nol untuk bobot kecil-salah satu alasan mengapa L2 lebih umum.

Dalam tf.keras , regularisasi berat ditambahkan dengan melewati contoh regularizer berat untuk lapisan sebagai argumen kata kunci. Mari kita tambahkan regularisasi berat L2 sekarang.

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
_________________________________________________________________
WARNING:tensorflow:Callback method `on_train_batch_begin` is slow compared to the batch time (batch time: 0.0038s vs `on_train_batch_begin` time: 0.0242s). Check your callbacks.
WARNING:tensorflow:Callback method `on_train_batch_end` is slow compared to the batch time (batch time: 0.0038s vs `on_train_batch_end` time: 0.0199s). Check your callbacks.

Epoch: 0, accuracy:0.5059,  binary_crossentropy:0.7720,  loss:2.2831,  val_accuracy:0.4620,  val_binary_crossentropy:0.7035,  val_loss:2.1321,  
....................................................................................................
Epoch: 100, accuracy:0.6490,  binary_crossentropy:0.5996,  loss:0.6228,  val_accuracy:0.6270,  val_binary_crossentropy:0.5898,  val_loss:0.6131,  
....................................................................................................
Epoch: 200, accuracy:0.6737,  binary_crossentropy:0.5826,  loss:0.6061,  val_accuracy:0.6680,  val_binary_crossentropy:0.5857,  val_loss:0.6096,  
....................................................................................................
Epoch: 300, accuracy:0.6842,  binary_crossentropy:0.5748,  loss:0.5993,  val_accuracy:0.6840,  val_binary_crossentropy:0.5754,  val_loss:0.5998,  
....................................................................................................
Epoch: 400, accuracy:0.6934,  binary_crossentropy:0.5620,  loss:0.5862,  val_accuracy:0.6690,  val_binary_crossentropy:0.5825,  val_loss:0.6066,  
.....................................................................................

l2(0.001) berarti bahwa setiap koefisien dalam matriks berat lapisan akan menambah 0.001 * weight_coefficient_value**2 dengan total kerugian dari jaringan.

Itulah sebabnya kami memantau binary_crossentropy langsung. Karena tidak ada komponen regularisasi ini yang tercampur.

Jadi, yang sama "Large" Model dengan L2 Melakukan penalti regularisasi jauh lebih baik:

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

png

Seperti yang Anda lihat, "L2" Model regularized sekarang jauh lebih kompetitif dengan para "Tiny" Model. Ini "L2" Model ini juga jauh lebih tahan terhadap overfitting daripada "Large" Model itu didasarkan pada walaupun memiliki jumlah yang sama parameter.

Info lebih lanjut

Ada dua hal penting yang perlu diperhatikan tentang regularisasi semacam ini.

Pertama: jika Anda menulis lingkaran pelatihan Anda sendiri, maka Anda perlu memastikan untuk meminta model untuk kerugian regularisasi nya.

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

Kedua: Implementasi ini bekerja dengan menambahkan hukuman berat kehilangan model, dan kemudian menerapkan prosedur optimasi standar setelah itu.

Ada pendekatan kedua yang hanya menjalankan pengoptimal pada kerugian mentah, dan kemudian saat menerapkan langkah yang dihitung, pengoptimal juga menerapkan beberapa peluruhan bobot. Ini "dipisahkan Berat Decay" terlihat dalam pengoptimalan seperti optimizers.FTRL dan optimizers.AdamW .

Tambahkan putus sekolah

Dropout adalah salah satu teknik regularisasi yang paling efektif dan paling umum digunakan untuk jaringan saraf, yang dikembangkan oleh Hinton dan mahasiswanya di University of Toronto.

Penjelasan intuitif untuk dropout adalah karena node individu dalam jaringan tidak dapat bergantung pada output yang lain, setiap node harus menampilkan fitur yang berguna sendiri.

Dropout, diterapkan pada sebuah layer, terdiri dari "drop out" secara acak (yaitu disetel ke nol) sejumlah fitur keluaran dari layer selama pelatihan. Katakanlah lapisan yang diberikan biasanya akan mengembalikan vektor [0.2, 0.5, 1.3, 0.8, 1.1] untuk sampel input yang diberikan selama pelatihan; setelah menerapkan dropout, vektor ini akan memiliki beberapa entri nol yang didistribusikan secara acak, misalnya [0, 0.5, 1.3, 0, 1.1].

"Tingkat putus sekolah" adalah sebagian kecil dari fitur-fitur yang dihilangkan; biasanya diatur antara 0,2 dan 0,5. Pada waktu pengujian, tidak ada unit yang dikeluarkan, dan sebaliknya nilai keluaran lapisan diperkecil dengan faktor yang sama dengan tingkat putus sekolah, untuk menyeimbangkan fakta bahwa lebih banyak unit yang aktif daripada pada waktu pelatihan.

Dalam tf.keras Anda dapat memperkenalkan putus sekolah dalam jaringan melalui lapisan Dropout, yang akan diterapkan pada output dari lapisan tepat sebelum.

Mari tambahkan dua layer Dropout di jaringan kita untuk melihat seberapa baik mereka mengurangi overfitting:

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
_________________________________________________________________
WARNING:tensorflow:Callback method `on_train_batch_begin` is slow compared to the batch time (batch time: 0.0040s vs `on_train_batch_begin` time: 0.0241s). Check your callbacks.
WARNING:tensorflow:Callback method `on_train_batch_end` is slow compared to the batch time (batch time: 0.0040s vs `on_train_batch_end` time: 0.0208s). Check your callbacks.

Epoch: 0, accuracy:0.5060,  binary_crossentropy:0.7949,  loss:0.7949,  val_accuracy:0.5140,  val_binary_crossentropy:0.6710,  val_loss:0.6710,  
....................................................................................................
Epoch: 100, accuracy:0.6623,  binary_crossentropy:0.5950,  loss:0.5950,  val_accuracy:0.6840,  val_binary_crossentropy:0.5723,  val_loss:0.5723,  
....................................................................................................
Epoch: 200, accuracy:0.6897,  binary_crossentropy:0.5559,  loss:0.5559,  val_accuracy:0.6800,  val_binary_crossentropy:0.5971,  val_loss:0.5971,  
....................................................................................................
Epoch: 300, accuracy:0.7202,  binary_crossentropy:0.5114,  loss:0.5114,  val_accuracy:0.6800,  val_binary_crossentropy:0.5984,  val_loss:0.5984,  
...............................................
plotter.plot(regularizer_histories)
plt.ylim([0.5, 0.7])
(0.5, 0.7)

png

Ini jelas dari plot ini bahwa kedua regularisasi ini mendekati meningkatkan perilaku "Large" Model. Tapi ini masih tidak mengalahkan bahkan "Tiny" dasar.

Selanjutnya coba keduanya, bersama-sama, dan lihat apakah itu lebih baik.

Gabungan L2 + putus sekolah

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
_________________________________________________________________
WARNING:tensorflow:Callback method `on_train_batch_begin` is slow compared to the batch time (batch time: 0.0040s vs `on_train_batch_begin` time: 0.0245s). Check your callbacks.
WARNING:tensorflow:Callback method `on_train_batch_end` is slow compared to the batch time (batch time: 0.0040s vs `on_train_batch_end` time: 0.0214s). Check your callbacks.

Epoch: 0, accuracy:0.5056,  binary_crossentropy:0.8201,  loss:0.9784,  val_accuracy:0.5130,  val_binary_crossentropy:0.6691,  val_loss:0.8269,  
....................................................................................................
Epoch: 100, accuracy:0.6409,  binary_crossentropy:0.6052,  loss:0.6362,  val_accuracy:0.6670,  val_binary_crossentropy:0.5831,  val_loss:0.6139,  
....................................................................................................
Epoch: 200, accuracy:0.6673,  binary_crossentropy:0.5893,  loss:0.6147,  val_accuracy:0.6880,  val_binary_crossentropy:0.5666,  val_loss:0.5920,  
....................................................................................................
Epoch: 300, accuracy:0.6724,  binary_crossentropy:0.5814,  loss:0.6092,  val_accuracy:0.6850,  val_binary_crossentropy:0.5638,  val_loss:0.5916,  
....................................................................................................
Epoch: 400, accuracy:0.6791,  binary_crossentropy:0.5764,  loss:0.6061,  val_accuracy:0.6960,  val_binary_crossentropy:0.5536,  val_loss:0.5832,  
....................................................................................................
Epoch: 500, accuracy:0.6750,  binary_crossentropy:0.5722,  loss:0.6037,  val_accuracy:0.6760,  val_binary_crossentropy:0.5583,  val_loss:0.5899,  
....................................................................................................
Epoch: 600, accuracy:0.6818,  binary_crossentropy:0.5651,  loss:0.5989,  val_accuracy:0.6940,  val_binary_crossentropy:0.5422,  val_loss:0.5761,  
....................................................................................................
Epoch: 700, accuracy:0.6882,  binary_crossentropy:0.5594,  loss:0.5943,  val_accuracy:0.6880,  val_binary_crossentropy:0.5436,  val_loss:0.5786,  
....................................................................................................
Epoch: 800, accuracy:0.6886,  binary_crossentropy:0.5567,  loss:0.5927,  val_accuracy:0.6960,  val_binary_crossentropy:0.5446,  val_loss:0.5807,  
....................................................................................................
Epoch: 900, accuracy:0.6994,  binary_crossentropy:0.5535,  loss:0.5907,  val_accuracy:0.6900,  val_binary_crossentropy:0.5463,  val_loss:0.5835,  
................................................
plotter.plot(regularizer_histories)
plt.ylim([0.5, 0.7])
(0.5, 0.7)

png

Model ini dengan "Combined" regularisasi jelas yang terbaik sejauh ini.

Lihat di TensorBoard

Model ini juga merekam log TensorBoard.

Untuk membuka penampil tensorboard tertanam di dalam buku catatan, salin kode berikut ke dalam sel kode:

%tensorboard --logdir {logdir}/regularizers

Anda dapat melihat hasil menjalankan sebelumnya dari notebook ini pada TensorDoard.dev .

Ini juga termasuk dalam <iframe> untuk kenyamanan:

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

Ini diunggah dengan:

tensorboard dev upload --logdir  {logdir}/regularizers

Kesimpulan

Untuk rekap: berikut adalah cara paling umum untuk mencegah overfitting di jaringan saraf:

  • Dapatkan lebih banyak data pelatihan.
  • Mengurangi kapasitas jaringan.
  • Tambahkan regularisasi berat badan.
  • Tambah putus sekolah.

Dua pendekatan penting yang tidak tercakup dalam panduan ini adalah:

  • data-augmentation
  • normalisasi batch

Ingatlah bahwa setiap metode dapat membantu dengan sendirinya, tetapi sering kali menggabungkannya bisa lebih efektif.

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