مشاهده در TensorFlow.org | در Google Colab اجرا شود | مشاهده منبع در GitHub | دانلود دفترچه یادداشت |
برپایی
import numpy as np
import tensorflow as tf
from tensorflow import keras
معرفی
آموزش انتقال شامل گرفتن ویژگی های به دست بر روی یک مشکل، و استفاده از آنها را در یک جدید، مشکل مشابه. به عنوان مثال، ویژگیهای مدلی که شناسایی راکونها را آموخته است، ممکن است برای راهاندازی مدلی برای شناسایی تانوکیها مفید باشد.
یادگیری انتقال معمولاً برای کارهایی انجام میشود که مجموعه دادههای شما دادههای بسیار کمی برای آموزش یک مدل در مقیاس کامل از ابتدا دارد.
رایج ترین تجسم یادگیری انتقالی در زمینه یادگیری عمیق، گردش کار زیر است:
- لایه ها را از یک مدل آموزش دیده قبلی بگیرید.
- آنها را فریز کنید تا از تخریب هر یک از اطلاعات موجود در دوره های آموزشی بعدی جلوگیری کنید.
- چند لایه جدید و قابل آموزش روی لایه های منجمد اضافه کنید. آنها یاد خواهند گرفت که ویژگی های قدیمی را به پیش بینی در یک مجموعه داده جدید تبدیل کنند.
- لایه های جدید در مجموعه داده خود را آموزش دهید.
تاریخ و زمان آخرین، مرحله اختیاری، ریز تنظیم، که متشکل از آزاد کردن کل مدل بالا به دست آمده (یا بخشی از آن)، و دوباره آموزش آن را در داده های جدید با نرخ یادگیری بسیار کم است. این به طور بالقوه می تواند با تطبیق تدریجی ویژگی های از پیش آموزش دیده با داده های جدید، به پیشرفت های معناداری دست یابد.
اول، ما را بیش از Keras رفتن trainable
API در جزئیات، که زیربنای ترین آموزش انتقال و ریز تنظیم گردش.
سپس، با استفاده از یک مدل از قبل آموزشدیده شده در مجموعه داده ImageNet، و آموزش مجدد آن در مجموعه دادههای طبقهبندی «گربهها در مقابل سگها» Kaggle، گردش کار معمولی را نشان میدهیم.
این است که از اقتباس یادگیری عمیق با پایتون و 2016 پست وبلاگ "ساخت مدل های قدرتمند طبقه بندی تصویر با استفاده از داده های بسیار اندکی" .
لایه های انجماد: درک trainable
ویژگی
لایه ها و مدل ها دارای سه ویژگی وزنی هستند:
-
weights
لیستی از تمام متغیرهای وزن لایه است. -
trainable_weights
لیست کسانی هستند که به معنای به روز می شود (از طریق گرادیان نزولی) برای به حداقل رساندن از دست دادن در طول آموزش است. -
non_trainable_weights
لیست کسانی هستند که به معنای نه به آموزش است. به طور معمول آنها توسط مدل در طول پاس رو به جلو به روز می شوند.
به عنوان مثال: Dense
لایه دارای 2 وزنه تربیت شدنی (هسته و تعصب)
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
به طور کلی همه وزنه ها وزنه های قابل تمرین هستند. تنها ساخته شده در لایه است که وزن غیر تربیت شدنی است BatchNormalization
لایه. از وزنه های غیر قابل تمرین برای پیگیری میانگین و واریانس ورودی های خود در طول تمرین استفاده می کند. برای آشنایی با نحوه استفاده از وزن غیر تربیت شدنی در لایه های سفارشی خود را، را ببینید راهنمایی برای نوشتن لایه جدید، از ابتدا .
به عنوان مثال: BatchNormalization
لایه دارای 2 وزنه تربیت شدنی و 2 وزن غیر تربیت شدنی
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
لایه ها و مدل های نیز از ویژگی های یک خصوصیت boolean trainable
. مقدار آن قابل تغییر است. تنظیم layer.trainable
به False
حرکت می کند تمام وزن لایه را از تربیت شدنی به غیر تربیت شدنی این است که به نام "انجماد" لایه: دولت از یک لایه یخ زده خواهد شد در طول آموزش به روز رسانی (خواه در هنگام آموزش با fit()
و یا در هنگام آموزش با هر حلقه های سفارشی که متکی trainable_weights
به درخواست به روز رسانی شیب).
به عنوان مثال: تنظیم trainable
به 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
هنگامی که یک وزنه قابل تمرین غیر قابل تمرین می شود، ارزش آن دیگر در طول تمرین به روز نمی شود.
# 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
آیا اشتباه نیست layer.trainable
ویژگی با این استدلال training
در layer.__call__()
(که کنترل میکند که آیا لایه باید پاس رو به جلو خود را در حالت استنتاج یا حالت آموزش اجرا). برای اطلاعات بیشتر، نگاه کنید به Keras پرسش و پاسخ .
تنظیم بازگشتی از trainable
ویژگی
اگر شما در راه trainable = False
بر روی یک مدل و یا در هر لایه است که زیر لایه، همه کودکان لایه تبدیل غیر تربیت شدنی است.
مثال:
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
گردش کار انتقال-یادگیری معمولی
این ما را به چگونگی پیادهسازی یک گردش کار یادگیری انتقال معمولی در Keras راهنمایی میکند:
- یک مدل پایه را نمونه برداری کنید و وزنه های از پیش آموزش دیده را در آن قرار دهید.
- مسدود کردن تمام لایه ها در مدل پایه با تنظیم
trainable = False
. - یک مدل جدید در بالای خروجی یک (یا چند) لایه از مدل پایه ایجاد کنید.
- مدل جدید خود را بر روی مجموعه داده جدید خود آموزش دهید.
توجه داشته باشید که یک گردش کار جایگزین و سبک تر نیز می تواند باشد:
- یک مدل پایه را نمونه برداری کنید و وزنه های از پیش آموزش دیده را در آن قرار دهید.
- مجموعه داده جدید خود را از طریق آن اجرا کنید و خروجی یک (یا چند) لایه را از مدل پایه ضبط کنید. این استخراج ویژگی به نام.
- از آن خروجی به عنوان داده ورودی برای یک مدل جدید و کوچکتر استفاده کنید.
مزیت کلیدی گردش کار دوم این است که شما مدل پایه را فقط یک بار بر روی داده های خود اجرا می کنید، نه یک بار در هر دوره آموزشی. بنابراین بسیار سریعتر و ارزان تر است.
با این حال، یک مشکل در جریان کار دوم این است که به شما اجازه نمیدهد دادههای ورودی مدل جدید خود را به صورت پویا در طول آموزش تغییر دهید، که برای مثال هنگام انجام افزایش دادهها مورد نیاز است. یادگیری انتقال معمولاً برای وظایفی استفاده میشود که مجموعه داده جدید شما دادههای بسیار کمی برای آموزش یک مدل در مقیاس کامل از ابتدا دارد، و در چنین سناریوهایی افزایش دادهها بسیار مهم است. بنابراین در ادامه به اولین گردش کار خواهیم پرداخت.
در اینجا اولین گردش کار در Keras به نظر می رسد:
ابتدا یک مدل پایه با وزنه های از پیش آموزش دیده نمونه سازی کنید.
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.
سپس مدل پایه را فریز کنید.
base_model.trainable = False
یک مدل جدید در بالا ایجاد کنید.
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)
مدل را بر روی داده های جدید آموزش دهید.
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=...)
تنظیم دقیق
هنگامی که مدل شما بر روی داده های جدید همگرا شد، می توانید سعی کنید تمام یا بخشی از مدل پایه را از حالت انجماد خارج کنید و کل مدل را با نرخ یادگیری بسیار پایین دوباره آموزش دهید.
این آخرین مرحله اختیاری است که به طور بالقوه می تواند به شما پیشرفت های تدریجی بدهد. همچنین می تواند به طور بالقوه منجر به بیش از حد برازش سریع شود - این را در نظر داشته باشید.
بسیار مهم است که تنها انجام این مرحله پس از مدل با لایه های منجمد شده است به همگرایی آموزش داده است. اگر لایههای آموزشپذیر اولیهسازیشده بهطور تصادفی را با لایههای آموزشپذیری که ویژگیهای از پیش آموزش داده شده را در خود جای دادهاند، ترکیب کنید، لایههایی که بهطور تصادفی راهاندازی شدهاند، بهروزرسانیهای گرادیان بسیار بزرگی را در طول آموزش ایجاد میکنند که ویژگیهای از پیش آموزشدیدهشده شما را از بین میبرد.
همچنین استفاده از نرخ یادگیری بسیار پایین در این مرحله بسیار مهم است، زیرا شما در حال آموزش یک مدل بسیار بزرگتر از دوره اول آموزش، بر روی مجموعه داده ای هستید که معمولاً بسیار کوچک است. در نتیجه، اگر بهروزرسانیهای وزن زیادی را اعمال کنید، خیلی سریع در معرض خطر بیش از حد قرار گرفتن هستید. در اینجا، شما فقط می خواهید وزنه های از پیش تمرین شده را به صورت افزایشی بازخوانی کنید.
نحوه اجرای تنظیم دقیق کل مدل پایه به این صورت است:
# 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=...)
نکته مهم در مورد compile()
و trainable
تماس compile()
بر روی یک مدل است به معنای "توقف" رفتار آن مدل. این به معنی این که trainable
مقادیر ویژگی در زمان مدل وارد شده است باید در تمام طول عمر که مدل حفظ شده است، تا زمانی که compile
است به نام دوباره. از این رو، اگر شما هر گونه تغییر trainable
ارزش، به پاسخ مطمئن شوید compile()
دوباره در مدل خود را برای تغییرات خود را به در نظر گرفته شود.
نکات مهم در مورد BatchNormalization
لایه
بسیاری از مدل های تصویر حاوی BatchNormalization
لایه. آن لایه در هر تعداد قابل تصور یک مورد خاص است. در اینجا چند نکته وجود دارد که باید در نظر داشته باشید.
-
BatchNormalization
شامل 2 وزن غیر تربیت شدنی که از در طول آموزش به روز شد. اینها متغیرهایی هستند که میانگین و واریانس ورودی ها را ردیابی می کنند. - هنگامی که به شما در تنظیم
bn_layer.trainable = False
ازBatchNormalization
لایه در حالت استنتاج اجرا خواهد شد، و آمار میانگین و واریانس آن به روز رسانی کنید. این مورد برای لایه های دیگر به طور کلی، به عنوان trainability وزن و استنتاج / حالت آموزش دو مفهوم متعامد هستند . اما این دو در مورد گره خورده استBatchNormalization
لایه. - هنگامی که شما یک مدل است که شامل آزادسازی
BatchNormalization
لایه به منظور انجام ریز تنظیم، شما باید حفظBatchNormalization
لایه در حالت استنتاج با عبورtraining=False
در هنگام فراخوانی مدل پایه. در غیر این صورت، بهروزرسانیهای اعمالشده برای وزنههای غیرقابل آموزش، بهطور ناگهانی آنچه را که مدل آموخته، از بین میبرد.
در مثال سرتاسری در انتهای این راهنما این الگو را در عمل مشاهده خواهید کرد.
انتقال یادگیری و تنظیم دقیق با یک حلقه آموزشی سفارشی
اگر به جای fit()
، شما با استفاده از خود حلقه آموزش سطح پایین خود را، اقامت گردش کار اساسا همان. شما باید مراقب باشید به تنها به حساب لیست model.trainable_weights
در هنگام استفاده از به روز رسانی شیب:
# 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))
به همین ترتیب برای تنظیم دقیق.
یک مثال سرتاسر: تنظیم دقیق مدل طبقهبندی تصویر در مجموعه دادههای گربه در مقابل سگ
برای تثبیت این مفاهیم، بیایید شما را از طریق یک مثال یادگیری و تنظیم دقیق انتقال پایان به انتها آشنا کنیم. ما مدل Xception را که از قبل در ImageNet آموزش داده شده است بارگذاری می کنیم و از آن در مجموعه داده های طبقه بندی Kaggle "گربه ها در برابر سگ ها" استفاده می کنیم.
گرفتن داده ها
ابتدا، بیایید مجموعه داده های گربه ها در مقابل سگ ها را با استفاده از TFDS واکشی کنیم. اگر شما مجموعه داده های خود را، شما احتمالا می خواهید به استفاده از ابزار tf.keras.preprocessing.image_dataset_from_directory
برای تولید مجموعه داده با برچسب مشابه اشیاء از مجموعه ای از تصاویر بر روی دیسک ثبت شده را به پوشه طبقه خاص.
یادگیری انتقالی هنگام کار با مجموعه داده های بسیار کوچک بسیار مفید است. برای کوچک نگه داشتن مجموعه داده های خود، از 40 درصد داده های آموزشی اصلی (25000 تصویر) برای آموزش، 10 درصد برای اعتبارسنجی و 10 درصد برای آزمایش استفاده خواهیم کرد.
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
اینها 9 تصویر اول در مجموعه داده آموزشی هستند -- همانطور که می بینید، همه آنها اندازه های متفاوتی دارند.
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")
همچنین می توانیم ببینیم که برچسب 1 "سگ" و برچسب 0 "گربه" است.
استاندارد کردن داده ها
تصاویر خام ما اندازه های مختلفی دارند. علاوه بر این، هر پیکسل از 3 مقدار صحیح بین 0 تا 255 (مقادیر سطح RGB) تشکیل شده است. این برای تغذیه شبکه عصبی مناسب نیست. ما باید 2 کار را انجام دهیم:
- استاندارد کردن به اندازه تصویر ثابت. ما 150x150 را انتخاب می کنیم.
- مقادیر پیکسل عادی بین -1 و 1. ما این با استفاده از یک انجام
Normalization
لایه را به عنوان بخشی از مدل خود را.
به طور کلی، توسعه مدلهایی که دادههای خام را به عنوان ورودی میگیرند، در مقابل مدلهایی که دادههای از قبل پردازش شده را دریافت میکنند، عمل خوبی است. دلیل آن این است که، اگر مدل شما انتظار داده های از پیش پردازش شده را دارد، هر زمان که مدل خود را برای استفاده از آن در جای دیگری (در یک مرورگر وب، در یک برنامه تلفن همراه) صادر می کنید، باید دقیقا همان خط لوله پیش پردازش را دوباره پیاده سازی کنید. این خیلی زود مشکل ساز می شود. بنابراین قبل از ضربه زدن به مدل باید کمترین پیش پردازش ممکن را انجام دهیم.
در اینجا، تغییر اندازه تصویر را در خط لوله داده انجام خواهیم داد (زیرا یک شبکه عصبی عمیق تنها میتواند دستهای از دادهها را پردازش کند)، و زمانی که آن را ایجاد میکنیم، مقیاس ارزش ورودی را به عنوان بخشی از مدل انجام میدهیم.
بیایید اندازه تصاویر را به 150x150 تغییر دهیم:
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))
علاوه بر این، بیایید داده ها را دسته بندی کنیم و از کش و واکشی اولیه برای بهینه سازی سرعت بارگذاری استفاده کنیم.
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)
با استفاده از افزایش تصادفی داده ها
زمانی که مجموعه داده تصویری بزرگی ندارید، معرفی مصنوعی تنوع نمونه با اعمال تبدیلهای تصادفی و در عین حال واقعی به تصاویر آموزشی، مانند چرخش افقی تصادفی یا چرخشهای تصادفی کوچک، تمرین خوبی است. این کمک می کند تا مدل را در معرض جنبه های مختلف داده های آموزشی قرار دهد و در عین حال سرعت بیش از حد برازش را کاهش دهد.
from tensorflow import keras
from tensorflow.keras import layers
data_augmentation = keras.Sequential(
[layers.RandomFlip("horizontal"), layers.RandomRotation(0.1),]
)
بیایید تجسم کنیم که اولین تصویر از اولین دسته پس از تبدیلهای تصادفی مختلف چگونه به نظر میرسد:
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.
یک مدل بسازید
حالا بیایید مدلی بسازیم که از طرحی که قبلا توضیح دادیم پیروی کند.
توجه داشته باشید که:
- ما اضافه کردن یک
Rescaling
لایه را به مقادیر ورودی مقیاس (در ابتدا در[0, 255]
وسیعی) به[-1, 1]
محدوده. - ما اضافه کردن یک
Dropout
لایه قبل از لایه طبقه بندی، برای تنظیم. - ما مطمئن شوید که به تصویب
training=False
در هنگام فراخوانی مدل پایه، به طوری که آن را در حالت استنتاج اجرا می شود، به طوری که آمار batchnorm انجام به روز نمی حتی پس از ما مدل پایه برای ریز تنظیم را آزاد.
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 _________________________________________________________________
لایه بالایی را آموزش دهید
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>
یک دور تنظیم دقیق کل مدل را انجام دهید
در نهایت، بیایید مدل پایه را از حالت فریز خارج کنیم و کل مدل را با نرخ یادگیری کم آموزش دهیم.
نکته مهم، اگر چه مدل پایه تربیت شدنی می شود، آن است که هنوز در حالت استنتاج در حال اجرا از ما گذشت training=False
هنگام فراخوانی آن زمانی که ما مدل ساخته شده است. این بدان معنی است که لایه های نرمال سازی دسته ای در داخل، آمار دسته ای خود را به روز نمی کنند. اگر این کار را می کردند، بازنمایی هایی را که مدل تاکنون آموخته بود، ویران می کردند.
# 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 دوره، تنظیم دقیق پیشرفت خوبی در اینجا به ما می دهد.