Öğrenmeyi ve ince ayarı aktarın

TensorFlow.org'da görüntüleyin Google Colab'da çalıştırın Kaynağı GitHub'da görüntüleyin Not defterini indir

Kurmak

import numpy as np
import tensorflow as tf
from tensorflow import keras

Tanıtım

Aktarım öğrenme bir problem üzerinde öğrenilen özelliklerini alarak ve yeni, benzer problem üzerinde onları yararlanarak oluşmaktadır. Örneğin, rakunları tanımlamayı öğrenmiş bir modelin özellikleri, tanukileri tanımlamaya yönelik bir modeli başlatmak için faydalı olabilir.

Aktarım öğrenimi genellikle, veri kümenizin tam ölçekli bir modeli sıfırdan eğitmek için çok az veriye sahip olduğu görevler için yapılır.

Derin öğrenme bağlamında transfer öğreniminin en yaygın enkarnasyonu aşağıdaki iş akışıdır:

  1. Önceden eğitilmiş bir modelden katmanlar alın.
  2. Gelecekteki eğitim turlarında içerdikleri herhangi bir bilgiyi yok etmemek için onları dondurun.
  3. Dondurulmuş katmanların üzerine yeni, eğitilebilir katmanlar ekleyin. Eski özellikleri yeni bir veri kümesi üzerinde tahminlere dönüştürmeyi öğrenecekler.
  4. Veri kümenizdeki yeni katmanları eğitin.

Bir son, isteğe bağlı bir adımdır, (bunun veya bir kısmını) tüm yukarıda elde edilen modelin çözülürken oluşan ince ayar, ve çok düşük bir öğrenme oranı ile yeni veri üzerine yeniden eğitim olduğunu. Bu, önceden eğitilmiş özellikleri aşamalı olarak yeni verilere uyarlayarak potansiyel olarak anlamlı iyileştirmeler sağlayabilir.

İlk olarak, Keras üzerinde gidecek trainable en aktarım öğrenme ve ince ayar iş akışlarını temelini detaylı olarak API.

Ardından, ImageNet veri kümesinde önceden eğitilmiş bir model alarak ve onu Kaggle "kediler vs köpekler" sınıflandırma veri kümesinde yeniden eğiterek tipik iş akışını göstereceğiz.

Bu uyarlanmıştır Python ile Derin Öğrenme ve 2016 blog post "çok az veri kullanarak güçlü bir resim sınıflandırma modellerini oluşturmak" .

Donma katmanları: anlama trainable niteliğini

Katmanlar ve modeller üç ağırlık özelliğine sahiptir:

  • weights tabakanın tüm ağırlıkları değişken listesi aşağıdadır.
  • trainable_weights (gradyan asıllı üzerinden) güncellenmesi içindir olanlar eğitim sırasında kaybını en aza indirmek için listesidir.
  • non_trainable_weights eğitilecek anlamına gelmez olanlar listesi aşağıdadır. Tipik olarak, ileri geçiş sırasında model tarafından güncellenirler.

Örnek: Dense tabaka 2 eğitilebilen ağırlığa sahiptir (çekirdek ve önyargı)

layer = keras.layers.Dense(3)
layer.build((None, 4))  # Create the weights

print("weights:", len(layer.weights))
print("trainable_weights:", len(layer.trainable_weights))
print("non_trainable_weights:", len(layer.non_trainable_weights))
weights: 2
trainable_weights: 2
non_trainable_weights: 0

Genel olarak, tüm ağırlıklar eğitilebilir ağırlıklardır. Yalnızca yerleşik olmayan eğitilebilir ağırlıkları vardır katmanda olduğu BatchNormalization katmanı. Eğitim sırasında girdilerinin ortalamasını ve varyansını takip etmek için eğitilemez ağırlıklar kullanır. Kendi özel katmanlarında olmayan eğitilebilir ağırlıkları kullanmak görmek öğrenmek için sıfırdan yeni katmanlar yazma rehberi .

Örnek: BatchNormalization tabaka 2 eğitilebilen ağırlıkları ve 2-olmayan eğitilebilen tartılacak

layer = keras.layers.BatchNormalization()
layer.build((None, 4))  # Create the weights

print("weights:", len(layer.weights))
print("trainable_weights:", len(layer.trainable_weights))
print("non_trainable_weights:", len(layer.non_trainable_weights))
weights: 4
trainable_weights: 2
non_trainable_weights: 2

Katmanlar ve modeller de bir boolean nitelik özelliği trainable . Değeri değiştirilebilir. Ayar layer.trainable için False olmayan eğitilebilir için hamle eğitilebilir tüm katmanın ağırlıklarını. Bu "dondurma" katmanı olarak adlandırılır: donmuş tabakanın devlet eğitimi sırasında güncelleştirilmiş olmayacak (ya zaman ile antrenman fit() veya dayanan herhangi bir özel döngü ile eğitim trainable_weights degrade güncelleştirmeleri uygulamak için).

Örnek: ayar trainable için False

layer = keras.layers.Dense(3)
layer.build((None, 4))  # Create the weights
layer.trainable = False  # Freeze the layer

print("weights:", len(layer.weights))
print("trainable_weights:", len(layer.trainable_weights))
print("non_trainable_weights:", len(layer.non_trainable_weights))
weights: 2
trainable_weights: 0
non_trainable_weights: 2

Eğitilebilir bir ağırlık eğitilemez hale geldiğinde, değeri artık eğitim sırasında güncellenmez.

# Make a model with 2 layers
layer1 = keras.layers.Dense(3, activation="relu")
layer2 = keras.layers.Dense(3, activation="sigmoid")
model = keras.Sequential([keras.Input(shape=(3,)), layer1, layer2])

# Freeze the first layer
layer1.trainable = False

# Keep a copy of the weights of layer1 for later reference
initial_layer1_weights_values = layer1.get_weights()

# Train the model
model.compile(optimizer="adam", loss="mse")
model.fit(np.random.random((2, 3)), np.random.random((2, 3)))

# Check that the weights of layer1 have not changed during training
final_layer1_weights_values = layer1.get_weights()
np.testing.assert_allclose(
    initial_layer1_weights_values[0], final_layer1_weights_values[0]
)
np.testing.assert_allclose(
    initial_layer1_weights_values[1], final_layer1_weights_values[1]
)
1/1 [==============================] - 1s 640ms/step - loss: 0.0945

Karıştırmayın layer.trainable argüman ile öznitelik training içinde layer.__call__() (ki katman çıkarım modunda veya eğitim modunda onun ileri pas çalıştırılması gerekip gerekmediğini kontroller). Daha fazla bilgi için, bkz Keras SSS .

Yinelemeli ayar trainable özniteliği

Eğer ayarlarsanız trainable = False bir model üzerinde veya alt katmanları olan herhangi bir katman üzerinde, tüm çocukların katmanları sıra dışı eğitilebilir olur.

Örnek:

inner_model = keras.Sequential(
    [
        keras.Input(shape=(3,)),
        keras.layers.Dense(3, activation="relu"),
        keras.layers.Dense(3, activation="relu"),
    ]
)

model = keras.Sequential(
    [keras.Input(shape=(3,)), inner_model, keras.layers.Dense(3, activation="sigmoid"),]
)

model.trainable = False  # Freeze the outer model

assert inner_model.trainable == False  # All layers in `model` are now frozen
assert inner_model.layers[0].trainable == False  # `trainable` is propagated recursively

Tipik transfer-öğrenme iş akışı

Bu bizi Keras'ta tipik bir transfer öğrenme iş akışının nasıl uygulanabileceğine götürür:

  1. Bir temel model oluşturun ve buna önceden eğitilmiş ağırlıklar yükleyin.
  2. Ayarlayarak baz modelinde tüm katmanları dondur trainable = False .
  3. Temel modelden bir (veya birkaç) katmanın çıktısının üzerine yeni bir model oluşturun.
  4. Yeni modelinizi yeni veri kümenizde eğitin.

Alternatif, daha hafif bir iş akışının da olabileceğini unutmayın:

  1. Bir temel model oluşturun ve buna önceden eğitilmiş ağırlıklar yükleyin.
  2. Yeni veri kümenizi bunun üzerinden çalıştırın ve temel modelden bir (veya birkaç) katmanın çıktısını kaydedin. Bu özellik çıkarma denir.
  3. Bu çıktıyı yeni, daha küçük bir model için girdi verileri olarak kullanın.

Bu ikinci iş akışının önemli bir avantajı, temel modeli eğitim dönemi başına bir kez yerine verilerinizde yalnızca bir kez çalıştırmanızdır. Yani çok daha hızlı ve daha ucuz.

Ancak bu ikinci iş akışıyla ilgili bir sorun, örneğin veri artırma yaparken gerekli olan eğitim sırasında yeni modelinizin giriş verilerini dinamik olarak değiştirmenize izin vermemesidir. Aktarım öğrenimi genellikle, yeni veri kümenizde sıfırdan tam ölçekli bir model eğitmek için çok az veriye sahip olduğunda ve bu tür senaryolarda veri büyütme çok önemli olduğunda görevler için kullanılır. Bundan sonra, ilk iş akışına odaklanacağız.

Keras'ta ilk iş akışı şöyle görünür:

İlk olarak, önceden eğitilmiş ağırlıklarla bir temel model oluşturun.

base_model = keras.applications.Xception(
    weights='imagenet',  # Load weights pre-trained on ImageNet.
    input_shape=(150, 150, 3),
    include_top=False)  # Do not include the ImageNet classifier at the top.

Ardından, temel modeli dondurun.

base_model.trainable = False

Üstte yeni bir model oluşturun.

inputs = keras.Input(shape=(150, 150, 3))
# We make sure that the base_model is running in inference mode here,
# by passing `training=False`. This is important for fine-tuning, as you will
# learn in a few paragraphs.
x = base_model(inputs, training=False)
# Convert features of shape `base_model.output_shape[1:]` to vectors
x = keras.layers.GlobalAveragePooling2D()(x)
# A Dense classifier with a single unit (binary classification)
outputs = keras.layers.Dense(1)(x)
model = keras.Model(inputs, outputs)

Modeli yeni verilerle eğitin.

model.compile(optimizer=keras.optimizers.Adam(),
              loss=keras.losses.BinaryCrossentropy(from_logits=True),
              metrics=[keras.metrics.BinaryAccuracy()])
model.fit(new_dataset, epochs=20, callbacks=..., validation_data=...)

İnce ayar

Modeliniz yeni veriler üzerinde birleştiğinde, temel modelin tamamını veya bir kısmını çözmeyi deneyebilir ve tüm modeli uçtan uca çok düşük bir öğrenme oranıyla yeniden eğitebilirsiniz.

Bu, potansiyel olarak size artımlı iyileştirmeler sağlayabilecek isteğe bağlı bir son adımdır. Ayrıca potansiyel olarak hızlı bir şekilde fazla takmaya neden olabilir - bunu aklınızda bulundurun.

Donmuş katmanlarla modeli yakınsaması için eğitilmiş sonra sadece bu adımı yapmak için çok önemlidir. Rastgele başlatılmış eğitilebilir katmanları önceden eğitilmiş özellikleri tutan eğitilebilir katmanlarla karıştırırsanız, rastgele başlatılmış katmanlar eğitim sırasında çok büyük gradyan güncellemelerine neden olur ve bu da önceden eğitilmiş özelliklerinizi yok eder.

Bu aşamada çok düşük bir öğrenme oranı kullanmak da çok önemlidir, çünkü genellikle çok küçük olan bir veri kümesi üzerinde ilk eğitim turundan çok daha büyük bir model eğitiyorsunuz. Sonuç olarak, büyük ağırlık güncellemeleri uygularsanız çok hızlı bir şekilde fazla takma riskiniz vardır. Burada, yalnızca önceden eğitilmiş ağırlıkları kademeli olarak yeniden uyarlamak istiyorsunuz.

Tüm temel modelin ince ayarını şu şekilde uygulayabilirsiniz:

# Unfreeze the base model
base_model.trainable = True

# It's important to recompile your model after you make any changes
# to the `trainable` attribute of any inner layer, so that your changes
# are take into account
model.compile(optimizer=keras.optimizers.Adam(1e-5),  # Very low learning rate
              loss=keras.losses.BinaryCrossentropy(from_logits=True),
              metrics=[keras.metrics.BinaryAccuracy()])

# Train end-to-end. Be careful to stop before you overfit!
model.fit(new_dataset, epochs=10, callbacks=..., validation_data=...)

İlgili önemli not compile() ve trainable

Arayan compile() amaçlanan bir model üzerinde bu modelin davranışını "dondurmak". Bu ima trainable kadar modeli derlenmiş bir anda nitelik değerleri, o modelin ömrü boyunca muhafaza edilmelidir compile yeniden adlandırılır. Eğer herhangi bir değişiklik yaparsanız Dolayısıyla, trainable değeri, çağrı emin olun compile() yaptığınız değişiklikler dikkate alınacak için model üzerinde tekrar.

İlgili önemli notlar BatchNormalization tabakasının

Birçok görüntü modelleri içeriyor BatchNormalization katmanları. Bu katman, akla gelebilecek her sayıda özel bir durumdur. İşte akılda tutulması gereken birkaç şey.

  • BatchNormalization eğitim sırasında güncellenmelerini 2 olmayan eğitilebilir ağırlığını verir. Bunlar, girdilerin ortalamasını ve varyansını izleyen değişkenlerdir.
  • Ayarladığınızda bn_layer.trainable = False , BatchNormalization katman çıkarım modunda çalışır ve onun ortalama ve varyans istatistiklerini güncelleme olmayacaktır. Bu şekilde genel olarak diğer katmanları için durum böyle değildir ağırlık trainability & çıkarım / eğitim modları iki dikey kavramlardır . Fakat iki durumunda bağlıdır BatchNormalization tabakasının.
  • Eğer içeren bir model unfreeze zaman BatchNormalization ince ayar yapmak için katmanları, sen tutmalı BatchNormalization geçirerek çıkarım modunda katmanları training=False baz modeli çağrılırken. Aksi takdirde, eğitilebilir olmayan ağırlıklara uygulanan güncellemeler, modelin öğrendiklerini bir anda yok edecektir.

Bu kılavuzun sonundaki uçtan uca örnekte bu kalıbı çalışırken göreceksiniz.

Özel bir eğitim döngüsüyle öğrenimi ve ince ayarı aktarın

Yerine ise fit() , kendi alt düzey eğitim döngü kullanırken, iş akışı kalır temelde aynı. Sadece dikkate liste almak için dikkatli olmalıdır model.trainable_weights degrade güncellemelerini uygularken:

# Create base model
base_model = keras.applications.Xception(
    weights='imagenet',
    input_shape=(150, 150, 3),
    include_top=False)
# Freeze base model
base_model.trainable = False

# Create new model on top.
inputs = keras.Input(shape=(150, 150, 3))
x = base_model(inputs, training=False)
x = keras.layers.GlobalAveragePooling2D()(x)
outputs = keras.layers.Dense(1)(x)
model = keras.Model(inputs, outputs)

loss_fn = keras.losses.BinaryCrossentropy(from_logits=True)
optimizer = keras.optimizers.Adam()

# Iterate over the batches of a dataset.
for inputs, targets in new_dataset:
    # Open a GradientTape.
    with tf.GradientTape() as tape:
        # Forward pass.
        predictions = model(inputs)
        # Compute the loss value for this batch.
        loss_value = loss_fn(targets, predictions)

    # Get gradients of loss wrt the *trainable* weights.
    gradients = tape.gradient(loss_value, model.trainable_weights)
    # Update the weights of the model.
    optimizer.apply_gradients(zip(gradients, model.trainable_weights))

Aynı şekilde ince ayar için.

Uçtan uca bir örnek: kedilere karşı köpekler veri kümesinde bir görüntü sınıflandırma modelinde ince ayar yapma

Bu kavramları sağlamlaştırmak için, somut bir uçtan uca aktarım öğrenimi ve ince ayar örneğinde size yol gösterelim. ImageNet üzerinde önceden eğitilmiş Xception modelini yükleyeceğiz ve bunu Kaggle "cats vs. Dog" sınıflandırma veri setinde kullanacağız.

verileri alma

İlk olarak, TFDS kullanarak kedilere karşı köpekler veri setini getirelim. Kendi veri kümesi varsa, muhtemelen yarar kullanmak isteyeceksiniz tf.keras.preprocessing.image_dataset_from_directory benzer etiketli veri kümesi sınıfa özel klasörler halinde açılan diskteki görüntülerin bir dizi nesneleri oluşturmak için.

Aktarım öğrenimi en çok çok küçük veri kümeleriyle çalışırken yararlıdır. Veri kümemizi küçük tutmak için orijinal eğitim verilerinin %40'ını (25.000 görüntü) eğitim için, %10'unu doğrulama için ve %10'unu test için kullanacağız.

import tensorflow_datasets as tfds

tfds.disable_progress_bar()

train_ds, validation_ds, test_ds = tfds.load(
    "cats_vs_dogs",
    # Reserve 10% for validation and 10% for test
    split=["train[:40%]", "train[40%:50%]", "train[50%:60%]"],
    as_supervised=True,  # Include labels
)

print("Number of training samples: %d" % tf.data.experimental.cardinality(train_ds))
print(
    "Number of validation samples: %d" % tf.data.experimental.cardinality(validation_ds)
)
print("Number of test samples: %d" % tf.data.experimental.cardinality(test_ds))
Number of training samples: 9305
Number of validation samples: 2326
Number of test samples: 2326

Bunlar eğitim veri setindeki ilk 9 görüntü -- gördüğünüz gibi hepsi farklı boyutlarda.

import matplotlib.pyplot as plt

plt.figure(figsize=(10, 10))
for i, (image, label) in enumerate(train_ds.take(9)):
    ax = plt.subplot(3, 3, i + 1)
    plt.imshow(image)
    plt.title(int(label))
    plt.axis("off")

png

Ayrıca etiket 1'in "köpek" ve etiket 0'ın "kedi" olduğunu görebiliriz.

Verileri standartlaştırma

Ham görsellerimiz çeşitli boyutlara sahiptir. Ayrıca her piksel 0 ile 255 arasında (RGB seviye değerleri) 3 tamsayı değerinden oluşmaktadır. Bu, bir sinir ağını beslemek için pek uygun değil. 2 şey yapmamız gerekiyor:

  • Sabit bir görüntü boyutuna standartlaştırın. 150x150 seçiyoruz.
  • Normale piksel değerleri arasındaki -1 ve 1. Biz kullanarak yapacağım Normalization modelinin kendisinin bir parçası olarak katmanını.

Genel olarak, önceden işlenmiş verileri alan modellerin aksine, ham verileri girdi olarak alan modeller geliştirmek iyi bir uygulamadır. Bunun nedeni, modeliniz önceden işlenmiş veriler bekliyorsa, modelinizi başka bir yerde (bir web tarayıcısında, bir mobil uygulamada) kullanmak için dışa aktardığınızda, aynı ön işleme hattını yeniden uygulamanız gerekir. Bu çok çabuk çok zorlaşıyor. Bu nedenle, modele ulaşmadan önce mümkün olan en az miktarda ön işleme yapmalıyız.

Burada, veri hattında görüntü yeniden boyutlandırma yapacağız (çünkü derin bir sinir ağı yalnızca bitişik veri gruplarını işleyebilir) ve onu oluşturduğumuzda, modelin bir parçası olarak girdi değeri ölçeklendirmesini yapacağız.

Resimleri 150x150 olarak yeniden boyutlandıralım:

size = (150, 150)

train_ds = train_ds.map(lambda x, y: (tf.image.resize(x, size), y))
validation_ds = validation_ds.map(lambda x, y: (tf.image.resize(x, size), y))
test_ds = test_ds.map(lambda x, y: (tf.image.resize(x, size), y))

Ayrıca, verileri toplu hale getirelim ve yükleme hızını optimize etmek için önbelleğe alma ve önceden getirmeyi kullanalım.

batch_size = 32

train_ds = train_ds.cache().batch(batch_size).prefetch(buffer_size=10)
validation_ds = validation_ds.cache().batch(batch_size).prefetch(buffer_size=10)
test_ds = test_ds.cache().batch(batch_size).prefetch(buffer_size=10)

Rastgele veri artırmayı kullanma

Büyük bir görüntü veri kümeniz olmadığında, eğitim görüntülerine rastgele yatay çevirme veya küçük rastgele döndürmeler gibi rastgele ancak gerçekçi dönüşümler uygulayarak örnek çeşitliliğini yapay olarak tanıtmak iyi bir uygulamadır. Bu, fazla uydurmayı yavaşlatırken modeli eğitim verilerinin farklı yönlerine maruz bırakmaya yardımcı olur.

from tensorflow import keras
from tensorflow.keras import layers

data_augmentation = keras.Sequential(
    [layers.RandomFlip("horizontal"), layers.RandomRotation(0.1),]
)

Çeşitli rastgele dönüşümlerden sonra ilk grubun ilk görüntüsünün nasıl göründüğünü görselleştirelim:

import numpy as np

for images, labels in train_ds.take(1):
    plt.figure(figsize=(10, 10))
    first_image = images[0]
    for i in range(9):
        ax = plt.subplot(3, 3, i + 1)
        augmented_image = data_augmentation(
            tf.expand_dims(first_image, 0), training=True
        )
        plt.imshow(augmented_image[0].numpy().astype("int32"))
        plt.title(int(labels[0]))
        plt.axis("off")
2021-09-01 18:45:34.772284: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.

png

Bir model yapmak

Şimdi daha önce açıkladığımız planı takip eden bir model oluşturalım.

Bunu not et:

  • Bir ekleme Rescaling (başlangıçta ölçek girdi değerlerine katman [0, 255] aralığında) [-1, 1] aralığında.
  • Biz eklemek Dropout regularization, sınıflandırma tabakasının önce katmanı.
  • Biz geçmek emin training=False o batchnorm istatistikleri biz ince ayar için baz modeli önündeki engeli sonra bile güncellenmiş alamadım bu yüzden, çıkarsama modunda çalışır böylece, baz modeli çağrılırken.
base_model = keras.applications.Xception(
    weights="imagenet",  # Load weights pre-trained on ImageNet.
    input_shape=(150, 150, 3),
    include_top=False,
)  # Do not include the ImageNet classifier at the top.

# Freeze the base_model
base_model.trainable = False

# Create new model on top
inputs = keras.Input(shape=(150, 150, 3))
x = data_augmentation(inputs)  # Apply random data augmentation

# Pre-trained Xception weights requires that input be scaled
# from (0, 255) to a range of (-1., +1.), the rescaling layer
# outputs: `(inputs * scale) + offset`
scale_layer = keras.layers.Rescaling(scale=1 / 127.5, offset=-1)
x = scale_layer(x)

# The base model contains batchnorm layers. We want to keep them in inference mode
# when we unfreeze the base model for fine-tuning, so we make sure that the
# base_model is running in inference mode here.
x = base_model(x, training=False)
x = keras.layers.GlobalAveragePooling2D()(x)
x = keras.layers.Dropout(0.2)(x)  # Regularize with dropout
outputs = keras.layers.Dense(1)(x)
model = keras.Model(inputs, outputs)

model.summary()
Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/xception/xception_weights_tf_dim_ordering_tf_kernels_notop.h5
83689472/83683744 [==============================] - 2s 0us/step
83697664/83683744 [==============================] - 2s 0us/step
Model: "model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_5 (InputLayer)         [(None, 150, 150, 3)]     0         
_________________________________________________________________
sequential_3 (Sequential)    (None, 150, 150, 3)       0         
_________________________________________________________________
rescaling (Rescaling)        (None, 150, 150, 3)       0         
_________________________________________________________________
xception (Functional)        (None, 5, 5, 2048)        20861480  
_________________________________________________________________
global_average_pooling2d (Gl (None, 2048)              0         
_________________________________________________________________
dropout (Dropout)            (None, 2048)              0         
_________________________________________________________________
dense_7 (Dense)              (None, 1)                 2049      
=================================================================
Total params: 20,863,529
Trainable params: 2,049
Non-trainable params: 20,861,480
_________________________________________________________________

Üst katmanı eğitin

model.compile(
    optimizer=keras.optimizers.Adam(),
    loss=keras.losses.BinaryCrossentropy(from_logits=True),
    metrics=[keras.metrics.BinaryAccuracy()],
)

epochs = 20
model.fit(train_ds, epochs=epochs, validation_data=validation_ds)
Epoch 1/20
151/291 [==============>...............] - ETA: 3s - loss: 0.1979 - binary_accuracy: 0.9096
Corrupt JPEG data: 65 extraneous bytes before marker 0xd9
268/291 [==========================>...] - ETA: 1s - loss: 0.1663 - binary_accuracy: 0.9269
Corrupt JPEG data: 239 extraneous bytes before marker 0xd9
282/291 [============================>.] - ETA: 0s - loss: 0.1628 - binary_accuracy: 0.9284
Corrupt JPEG data: 1153 extraneous bytes before marker 0xd9
Corrupt JPEG data: 228 extraneous bytes before marker 0xd9
291/291 [==============================] - ETA: 0s - loss: 0.1620 - binary_accuracy: 0.9286
Corrupt JPEG data: 2226 extraneous bytes before marker 0xd9
291/291 [==============================] - 29s 63ms/step - loss: 0.1620 - binary_accuracy: 0.9286 - val_loss: 0.0814 - val_binary_accuracy: 0.9686
Epoch 2/20
291/291 [==============================] - 8s 29ms/step - loss: 0.1178 - binary_accuracy: 0.9511 - val_loss: 0.0785 - val_binary_accuracy: 0.9695
Epoch 3/20
291/291 [==============================] - 9s 30ms/step - loss: 0.1121 - binary_accuracy: 0.9536 - val_loss: 0.0748 - val_binary_accuracy: 0.9712
Epoch 4/20
291/291 [==============================] - 9s 29ms/step - loss: 0.1082 - binary_accuracy: 0.9554 - val_loss: 0.0754 - val_binary_accuracy: 0.9703
Epoch 5/20
291/291 [==============================] - 8s 29ms/step - loss: 0.1034 - binary_accuracy: 0.9570 - val_loss: 0.0721 - val_binary_accuracy: 0.9725
Epoch 6/20
291/291 [==============================] - 8s 29ms/step - loss: 0.0975 - binary_accuracy: 0.9602 - val_loss: 0.0748 - val_binary_accuracy: 0.9699
Epoch 7/20
291/291 [==============================] - 9s 29ms/step - loss: 0.0989 - binary_accuracy: 0.9595 - val_loss: 0.0732 - val_binary_accuracy: 0.9716
Epoch 8/20
291/291 [==============================] - 8s 29ms/step - loss: 0.1027 - binary_accuracy: 0.9566 - val_loss: 0.0787 - val_binary_accuracy: 0.9678
Epoch 9/20
291/291 [==============================] - 8s 29ms/step - loss: 0.0959 - binary_accuracy: 0.9614 - val_loss: 0.0734 - val_binary_accuracy: 0.9729
Epoch 10/20
291/291 [==============================] - 8s 29ms/step - loss: 0.0995 - binary_accuracy: 0.9588 - val_loss: 0.0717 - val_binary_accuracy: 0.9721
Epoch 11/20
291/291 [==============================] - 8s 29ms/step - loss: 0.0957 - binary_accuracy: 0.9612 - val_loss: 0.0731 - val_binary_accuracy: 0.9725
Epoch 12/20
291/291 [==============================] - 8s 29ms/step - loss: 0.0936 - binary_accuracy: 0.9622 - val_loss: 0.0751 - val_binary_accuracy: 0.9716
Epoch 13/20
291/291 [==============================] - 8s 29ms/step - loss: 0.0965 - binary_accuracy: 0.9610 - val_loss: 0.0821 - val_binary_accuracy: 0.9695
Epoch 14/20
291/291 [==============================] - 8s 29ms/step - loss: 0.0939 - binary_accuracy: 0.9618 - val_loss: 0.0742 - val_binary_accuracy: 0.9712
Epoch 15/20
291/291 [==============================] - 8s 29ms/step - loss: 0.0974 - binary_accuracy: 0.9585 - val_loss: 0.0771 - val_binary_accuracy: 0.9712
Epoch 16/20
291/291 [==============================] - 8s 29ms/step - loss: 0.0947 - binary_accuracy: 0.9621 - val_loss: 0.0823 - val_binary_accuracy: 0.9699
Epoch 17/20
291/291 [==============================] - 8s 29ms/step - loss: 0.0947 - binary_accuracy: 0.9625 - val_loss: 0.0718 - val_binary_accuracy: 0.9708
Epoch 18/20
291/291 [==============================] - 8s 29ms/step - loss: 0.0928 - binary_accuracy: 0.9616 - val_loss: 0.0738 - val_binary_accuracy: 0.9716
Epoch 19/20
291/291 [==============================] - 8s 29ms/step - loss: 0.0922 - binary_accuracy: 0.9644 - val_loss: 0.0743 - val_binary_accuracy: 0.9716
Epoch 20/20
291/291 [==============================] - 8s 29ms/step - loss: 0.0885 - binary_accuracy: 0.9635 - val_loss: 0.0745 - val_binary_accuracy: 0.9695
<keras.callbacks.History at 0x7f849a3b2950>

Tüm modelde bir tur ince ayar yapın

Son olarak, temel modeli çözelim ve tüm modeli düşük bir öğrenme oranıyla uçtan uca eğitelim.

Baz modeli eğitilebilir hale rağmen biz öldükten sonra da önemlisi, yine çıkarım modunda çalışırken training=False biz modeli inşa ettiğinde bunu çağrılırken. Bu, içindeki toplu normalleştirme katmanlarının toplu istatistiklerini güncellemeyeceği anlamına gelir. Yaparlarsa, model tarafından şimdiye kadar öğrenilen temsilleri alt üst edeceklerdi.

# Unfreeze the base_model. Note that it keeps running in inference mode
# since we passed `training=False` when calling it. This means that
# the batchnorm layers will not update their batch statistics.
# This prevents the batchnorm layers from undoing all the training
# we've done so far.
base_model.trainable = True
model.summary()

model.compile(
    optimizer=keras.optimizers.Adam(1e-5),  # Low learning rate
    loss=keras.losses.BinaryCrossentropy(from_logits=True),
    metrics=[keras.metrics.BinaryAccuracy()],
)

epochs = 10
model.fit(train_ds, epochs=epochs, validation_data=validation_ds)
Model: "model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_5 (InputLayer)         [(None, 150, 150, 3)]     0         
_________________________________________________________________
sequential_3 (Sequential)    (None, 150, 150, 3)       0         
_________________________________________________________________
rescaling (Rescaling)        (None, 150, 150, 3)       0         
_________________________________________________________________
xception (Functional)        (None, 5, 5, 2048)        20861480  
_________________________________________________________________
global_average_pooling2d (Gl (None, 2048)              0         
_________________________________________________________________
dropout (Dropout)            (None, 2048)              0         
_________________________________________________________________
dense_7 (Dense)              (None, 1)                 2049      
=================================================================
Total params: 20,863,529
Trainable params: 20,809,001
Non-trainable params: 54,528
_________________________________________________________________
Epoch 1/10
291/291 [==============================] - 43s 131ms/step - loss: 0.0802 - binary_accuracy: 0.9692 - val_loss: 0.0580 - val_binary_accuracy: 0.9764
Epoch 2/10
291/291 [==============================] - 37s 128ms/step - loss: 0.0542 - binary_accuracy: 0.9792 - val_loss: 0.0529 - val_binary_accuracy: 0.9764
Epoch 3/10
291/291 [==============================] - 37s 128ms/step - loss: 0.0400 - binary_accuracy: 0.9832 - val_loss: 0.0510 - val_binary_accuracy: 0.9798
Epoch 4/10
291/291 [==============================] - 37s 128ms/step - loss: 0.0313 - binary_accuracy: 0.9879 - val_loss: 0.0505 - val_binary_accuracy: 0.9819
Epoch 5/10
291/291 [==============================] - 37s 128ms/step - loss: 0.0272 - binary_accuracy: 0.9904 - val_loss: 0.0485 - val_binary_accuracy: 0.9807
Epoch 6/10
291/291 [==============================] - 37s 128ms/step - loss: 0.0284 - binary_accuracy: 0.9901 - val_loss: 0.0497 - val_binary_accuracy: 0.9824
Epoch 7/10
291/291 [==============================] - 37s 127ms/step - loss: 0.0198 - binary_accuracy: 0.9937 - val_loss: 0.0530 - val_binary_accuracy: 0.9802
Epoch 8/10
291/291 [==============================] - 37s 127ms/step - loss: 0.0173 - binary_accuracy: 0.9930 - val_loss: 0.0572 - val_binary_accuracy: 0.9819
Epoch 9/10
291/291 [==============================] - 37s 127ms/step - loss: 0.0113 - binary_accuracy: 0.9958 - val_loss: 0.0555 - val_binary_accuracy: 0.9837
Epoch 10/10
291/291 [==============================] - 37s 127ms/step - loss: 0.0091 - binary_accuracy: 0.9966 - val_loss: 0.0596 - val_binary_accuracy: 0.9832
<keras.callbacks.History at 0x7f83982d4cd0>

10 çağdan sonra, ince ayar bize burada güzel bir gelişme kazandırıyor.