مشاهده در TensorFlow.org | در Google Colab اجرا شود | مشاهده منبع در GitHub | دانلود دفترچه یادداشت |
این آموزش نحوه ساخت و آموزش یک شبکه متخاصم مولد شرطی (cGAN) به نام pix2pix را نشان میدهد که نقشهبرداری را از تصاویر ورودی به تصاویر خروجی میآموزد، همانطور که در ترجمه تصویر به تصویر با شبکههای متخاصم شرطی توسط Isola و همکاران توضیح داده شده است. (2017). pix2pix یک برنامه خاص نیست - میتوان آن را برای طیف گستردهای از وظایف، از جمله ترکیب عکسها از نقشههای برچسب، تولید عکسهای رنگی از تصاویر سیاه و سفید، تبدیل عکسهای Google Maps به تصاویر هوایی، و حتی تبدیل طرحها به عکس اعمال کرد.
در این مثال، شبکه شما با استفاده از پایگاه داده نمای CMP ارائه شده توسط مرکز درک ماشین در دانشگاه فنی چک در پراگ ، تصاویری از نمای ساختمان تولید می کند. برای کوتاه نگه داشتن آن، از یک کپی از پیش پردازش شده این مجموعه داده که توسط نویسندگان pix2pix ایجاد شده است استفاده خواهید کرد.
در pix2pix cGAN، تصاویر ورودی را شرط میکنید و تصاویر خروجی مربوطه را تولید میکنید. cGAN ها برای اولین بار در شبکه های متخاصم مولد مشروط پیشنهاد شدند (میرزا و اوسیندرو، 2014)
معماری شبکه شما شامل موارد زیر خواهد بود:
- یک ژنراتور با معماری مبتنی بر U-Net .
- یک تمایز که توسط یک طبقهبندی کننده PatchGAN کانولوشن ارائه میشود (پیشنهاد شده در مقاله pix2pix ).
توجه داشته باشید که هر دوره می تواند حدود 15 ثانیه روی یک واحد گرافیکی V100 طول بکشد.
در زیر چند نمونه از خروجی تولید شده توسط pix2pix cGAN پس از آموزش برای 200 دوره در مجموعه داده نماها (80 هزار مرحله) آورده شده است.
TensorFlow و کتابخانه های دیگر را وارد کنید
import tensorflow as tf
import os
import pathlib
import time
import datetime
from matplotlib import pyplot as plt
from IPython import display
مجموعه داده را بارگیری کنید
داده های پایگاه داده نمای CMP (30 مگابایت) را دانلود کنید. مجموعه داده های اضافی در قالب یکسان در اینجا موجود است. در Colab می توانید مجموعه داده های دیگری را از منوی کشویی انتخاب کنید. توجه داشته باشید که برخی از مجموعه داده های دیگر به طور قابل توجهی بزرگتر هستند ( edges2handbags
8 گیگابایت است).
dataset_name = "facades"
_URL = f'http://efrosgans.eecs.berkeley.edu/pix2pix/datasets/{dataset_name}.tar.gz'
path_to_zip = tf.keras.utils.get_file(
fname=f"{dataset_name}.tar.gz",
origin=_URL,
extract=True)
path_to_zip = pathlib.Path(path_to_zip)
PATH = path_to_zip.parent/dataset_name
Downloading data from http://efrosgans.eecs.berkeley.edu/pix2pix/datasets/facades.tar.gz 30171136/30168306 [==============================] - 19s 1us/step 30179328/30168306 [==============================] - 19s 1us/step
list(PATH.parent.iterdir())
[PosixPath('/home/kbuilder/.keras/datasets/facades.tar.gz'), PosixPath('/home/kbuilder/.keras/datasets/YellowLabradorLooking_new.jpg'), PosixPath('/home/kbuilder/.keras/datasets/facades'), PosixPath('/home/kbuilder/.keras/datasets/mnist.npz')]
هر تصویر اصلی در اندازه 256 x 512
شامل دو تصویر 256 x 256
است:
sample_image = tf.io.read_file(str(PATH / 'train/1.jpg'))
sample_image = tf.io.decode_jpeg(sample_image)
print(sample_image.shape)
(256, 512, 3)
plt.figure()
plt.imshow(sample_image)
<matplotlib.image.AxesImage at 0x7f35a3653c90>
شما باید تصاویر واقعی نمای ساختمان را از تصاویر برچسب معماری جدا کنید - که همه آنها در اندازه 256 x 256
خواهند بود.
تابعی را تعریف کنید که فایل های تصویری را بارگیری می کند و دو تانسور تصویر را خروجی می دهد:
def load(image_file):
# Read and decode an image file to a uint8 tensor
image = tf.io.read_file(image_file)
image = tf.io.decode_jpeg(image)
# Split each image tensor into two tensors:
# - one with a real building facade image
# - one with an architecture label image
w = tf.shape(image)[1]
w = w // 2
input_image = image[:, w:, :]
real_image = image[:, :w, :]
# Convert both images to float32 tensors
input_image = tf.cast(input_image, tf.float32)
real_image = tf.cast(real_image, tf.float32)
return input_image, real_image
نمونه ای از تصاویر ورودی (تصویر برچسب معماری) و واقعی (عکس نمای ساختمان) را ترسیم کنید:
inp, re = load(str(PATH / 'train/100.jpg'))
# Casting to int for matplotlib to display the images
plt.figure()
plt.imshow(inp / 255.0)
plt.figure()
plt.imshow(re / 255.0)
<matplotlib.image.AxesImage at 0x7f35981a4910>
همانطور که در مقاله pix2pix توضیح داده شد، برای پیش پردازش مجموعه آموزشی باید از لرزش تصادفی و آینه کاری استفاده کنید.
چندین تابع را تعریف کنید که:
- اندازه هر تصویر
256 x 256
را به ارتفاع و عرض بزرگتر تغییر دهید -286 x 286
. - به طور تصادفی آن را به
256 x 256
برش دهید. - به طور تصادفی تصویر را به صورت افقی برگردانید، یعنی از چپ به راست (آینه کاری تصادفی).
- تصاویر را در محدوده
[-1, 1]
عادی کنید.
# The facade training set consist of 400 images
BUFFER_SIZE = 400
# The batch size of 1 produced better results for the U-Net in the original pix2pix experiment
BATCH_SIZE = 1
# Each image is 256x256 in size
IMG_WIDTH = 256
IMG_HEIGHT = 256
def resize(input_image, real_image, height, width):
input_image = tf.image.resize(input_image, [height, width],
method=tf.image.ResizeMethod.NEAREST_NEIGHBOR)
real_image = tf.image.resize(real_image, [height, width],
method=tf.image.ResizeMethod.NEAREST_NEIGHBOR)
return input_image, real_image
def random_crop(input_image, real_image):
stacked_image = tf.stack([input_image, real_image], axis=0)
cropped_image = tf.image.random_crop(
stacked_image, size=[2, IMG_HEIGHT, IMG_WIDTH, 3])
return cropped_image[0], cropped_image[1]
# Normalizing the images to [-1, 1]
def normalize(input_image, real_image):
input_image = (input_image / 127.5) - 1
real_image = (real_image / 127.5) - 1
return input_image, real_image
@tf.function()
def random_jitter(input_image, real_image):
# Resizing to 286x286
input_image, real_image = resize(input_image, real_image, 286, 286)
# Random cropping back to 256x256
input_image, real_image = random_crop(input_image, real_image)
if tf.random.uniform(()) > 0.5:
# Random mirroring
input_image = tf.image.flip_left_right(input_image)
real_image = tf.image.flip_left_right(real_image)
return input_image, real_image
می توانید برخی از خروجی های از پیش پردازش شده را بررسی کنید:
plt.figure(figsize=(6, 6))
for i in range(4):
rj_inp, rj_re = random_jitter(inp, re)
plt.subplot(2, 2, i + 1)
plt.imshow(rj_inp / 255.0)
plt.axis('off')
plt.show()
پس از بررسی اینکه بارگذاری و پیش پردازش کار می کند، اجازه دهید چند تابع کمکی را تعریف کنیم که مجموعه های آموزشی و آزمایشی را بارگیری و پیش پردازش می کند:
def load_image_train(image_file):
input_image, real_image = load(image_file)
input_image, real_image = random_jitter(input_image, real_image)
input_image, real_image = normalize(input_image, real_image)
return input_image, real_image
def load_image_test(image_file):
input_image, real_image = load(image_file)
input_image, real_image = resize(input_image, real_image,
IMG_HEIGHT, IMG_WIDTH)
input_image, real_image = normalize(input_image, real_image)
return input_image, real_image
با tf.data
یک خط لوله ورودی بسازید
train_dataset = tf.data.Dataset.list_files(str(PATH / 'train/*.jpg'))
train_dataset = train_dataset.map(load_image_train,
num_parallel_calls=tf.data.AUTOTUNE)
train_dataset = train_dataset.shuffle(BUFFER_SIZE)
train_dataset = train_dataset.batch(BATCH_SIZE)
try:
test_dataset = tf.data.Dataset.list_files(str(PATH / 'test/*.jpg'))
except tf.errors.InvalidArgumentError:
test_dataset = tf.data.Dataset.list_files(str(PATH / 'val/*.jpg'))
test_dataset = test_dataset.map(load_image_test)
test_dataset = test_dataset.batch(BATCH_SIZE)
ژنراتور را بسازید
مولد pix2pix cGAN شما یک U-Net اصلاح شده است. U-Net از یک رمزگذار (downsampler) و رمزگشا (upsampler) تشکیل شده است. (شما می توانید در آموزش تقسیم بندی تصویر و وب سایت پروژه U-Net در مورد آن اطلاعات بیشتری کسب کنید.)
- هر بلوک در رمزگذار عبارت است از: Convolution -> Batch normalization -> Leaky ReLU
- هر بلوک در رمزگشا عبارت است از: کانولوشن انتقال داده شده -> نرمال سازی دسته ای -> حذف (در 3 بلوک اول اعمال می شود) -> ReLU
- اتصالات پرش بین رمزگذار و رمزگشا وجود دارد (مانند U-Net).
نمونهبرگیر (رمزگذار) را تعریف کنید:
OUTPUT_CHANNELS = 3
def downsample(filters, size, apply_batchnorm=True):
initializer = tf.random_normal_initializer(0., 0.02)
result = tf.keras.Sequential()
result.add(
tf.keras.layers.Conv2D(filters, size, strides=2, padding='same',
kernel_initializer=initializer, use_bias=False))
if apply_batchnorm:
result.add(tf.keras.layers.BatchNormalization())
result.add(tf.keras.layers.LeakyReLU())
return result
down_model = downsample(3, 4)
down_result = down_model(tf.expand_dims(inp, 0))
print (down_result.shape)
(1, 128, 128, 3)
نمونهبردار (رمزگشا) را تعریف کنید:
def upsample(filters, size, apply_dropout=False):
initializer = tf.random_normal_initializer(0., 0.02)
result = tf.keras.Sequential()
result.add(
tf.keras.layers.Conv2DTranspose(filters, size, strides=2,
padding='same',
kernel_initializer=initializer,
use_bias=False))
result.add(tf.keras.layers.BatchNormalization())
if apply_dropout:
result.add(tf.keras.layers.Dropout(0.5))
result.add(tf.keras.layers.ReLU())
return result
up_model = upsample(3, 4)
up_result = up_model(down_result)
print (up_result.shape)
(1, 256, 256, 3)
مولد را با نمونه برداری پایین و نمونه گیری بالا تعریف کنید:
def Generator():
inputs = tf.keras.layers.Input(shape=[256, 256, 3])
down_stack = [
downsample(64, 4, apply_batchnorm=False), # (batch_size, 128, 128, 64)
downsample(128, 4), # (batch_size, 64, 64, 128)
downsample(256, 4), # (batch_size, 32, 32, 256)
downsample(512, 4), # (batch_size, 16, 16, 512)
downsample(512, 4), # (batch_size, 8, 8, 512)
downsample(512, 4), # (batch_size, 4, 4, 512)
downsample(512, 4), # (batch_size, 2, 2, 512)
downsample(512, 4), # (batch_size, 1, 1, 512)
]
up_stack = [
upsample(512, 4, apply_dropout=True), # (batch_size, 2, 2, 1024)
upsample(512, 4, apply_dropout=True), # (batch_size, 4, 4, 1024)
upsample(512, 4, apply_dropout=True), # (batch_size, 8, 8, 1024)
upsample(512, 4), # (batch_size, 16, 16, 1024)
upsample(256, 4), # (batch_size, 32, 32, 512)
upsample(128, 4), # (batch_size, 64, 64, 256)
upsample(64, 4), # (batch_size, 128, 128, 128)
]
initializer = tf.random_normal_initializer(0., 0.02)
last = tf.keras.layers.Conv2DTranspose(OUTPUT_CHANNELS, 4,
strides=2,
padding='same',
kernel_initializer=initializer,
activation='tanh') # (batch_size, 256, 256, 3)
x = inputs
# Downsampling through the model
skips = []
for down in down_stack:
x = down(x)
skips.append(x)
skips = reversed(skips[:-1])
# Upsampling and establishing the skip connections
for up, skip in zip(up_stack, skips):
x = up(x)
x = tf.keras.layers.Concatenate()([x, skip])
x = last(x)
return tf.keras.Model(inputs=inputs, outputs=x)
معماری مدل ژنراتور را تجسم کنید:
generator = Generator()
tf.keras.utils.plot_model(generator, show_shapes=True, dpi=64)
ژنراتور را تست کنید:
gen_output = generator(inp[tf.newaxis, ...], training=False)
plt.imshow(gen_output[0, ...])
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers). <matplotlib.image.AxesImage at 0x7f35cfd20610>
تلفات ژنراتور را تعریف کنید
GAN ها اتلافی را یاد می گیرند که با داده ها سازگار است، در حالی که cGAN ها اتلاف ساختار یافته ای را می آموزند که ساختار احتمالی را که با خروجی شبکه و تصویر هدف متفاوت است جریمه می کند، همانطور که در مقاله pix2pix توضیح داده شده است.
- تلفات مولد یک افت آنتروپی متقاطع سیگموئیدی از تصاویر تولید شده و آرایه ای از تصاویر است.
- مقاله pix2pix همچنین از دست دادن L1 را ذکر می کند که یک MAE (میانگین خطای مطلق) بین تصویر تولید شده و تصویر هدف است.
- این اجازه می دهد تا تصویر تولید شده از نظر ساختاری شبیه به تصویر هدف شود.
- فرمول محاسبه تلفات کل ژنراتور
gan_loss + LAMBDA * l1_loss
است که در آنLAMBDA = 100
است. این مقدار توسط نویسندگان مقاله تعیین شده است.
LAMBDA = 100
loss_object = tf.keras.losses.BinaryCrossentropy(from_logits=True)
def generator_loss(disc_generated_output, gen_output, target):
gan_loss = loss_object(tf.ones_like(disc_generated_output), disc_generated_output)
# Mean absolute error
l1_loss = tf.reduce_mean(tf.abs(target - gen_output))
total_gen_loss = gan_loss + (LAMBDA * l1_loss)
return total_gen_loss, gan_loss, l1_loss
روش آموزش برای ژنراتور به شرح زیر است:
تمایز کننده را بسازید
تمایز کننده در pix2pix cGAN یک طبقهبندی کننده PatchGAN کانولوشنی است - همانطور که در مقاله pix2pix توضیح داده شده است، سعی میکند تشخیص دهد که آیا هر وصله تصویر واقعی است یا نه.
- هر بلوک در تشخیصگر عبارت است از: Convolution -> Batch normalization -> Leaky ReLU.
- شکل خروجی بعد از آخرین لایه
(batch_size, 30, 30, 1)
است. - هر وصله تصویر
30 x 30
از خروجی، بخش70 x 70
تصویر ورودی را طبقه بندی می کند. - تفکیک کننده 2 ورودی دریافت می کند:
- تصویر ورودی و تصویر هدف که باید به عنوان واقعی طبقه بندی شود.
- تصویر ورودی و تصویر تولید شده (خروجی ژنراتور) که باید به عنوان جعلی طبقه بندی شود.
- از
tf.concat([inp, tar], axis=-1)
برای به هم پیوستن این 2 ورودی استفاده کنید.
بیایید متمایز کننده را تعریف کنیم:
def Discriminator():
initializer = tf.random_normal_initializer(0., 0.02)
inp = tf.keras.layers.Input(shape=[256, 256, 3], name='input_image')
tar = tf.keras.layers.Input(shape=[256, 256, 3], name='target_image')
x = tf.keras.layers.concatenate([inp, tar]) # (batch_size, 256, 256, channels*2)
down1 = downsample(64, 4, False)(x) # (batch_size, 128, 128, 64)
down2 = downsample(128, 4)(down1) # (batch_size, 64, 64, 128)
down3 = downsample(256, 4)(down2) # (batch_size, 32, 32, 256)
zero_pad1 = tf.keras.layers.ZeroPadding2D()(down3) # (batch_size, 34, 34, 256)
conv = tf.keras.layers.Conv2D(512, 4, strides=1,
kernel_initializer=initializer,
use_bias=False)(zero_pad1) # (batch_size, 31, 31, 512)
batchnorm1 = tf.keras.layers.BatchNormalization()(conv)
leaky_relu = tf.keras.layers.LeakyReLU()(batchnorm1)
zero_pad2 = tf.keras.layers.ZeroPadding2D()(leaky_relu) # (batch_size, 33, 33, 512)
last = tf.keras.layers.Conv2D(1, 4, strides=1,
kernel_initializer=initializer)(zero_pad2) # (batch_size, 30, 30, 1)
return tf.keras.Model(inputs=[inp, tar], outputs=last)
معماری مدل تفکیک کننده را تجسم کنید:
discriminator = Discriminator()
tf.keras.utils.plot_model(discriminator, show_shapes=True, dpi=64)
تشخیص دهنده را آزمایش کنید:
disc_out = discriminator([inp[tf.newaxis, ...], gen_output], training=False)
plt.imshow(disc_out[0, ..., -1], vmin=-20, vmax=20, cmap='RdBu_r')
plt.colorbar()
<matplotlib.colorbar.Colorbar at 0x7f35cec82c50>
ضرر تمایز را تعریف کنید
- تابع
discriminator_loss
2 ورودی می گیرد: تصاویر واقعی و تصاویر تولید شده . -
real_loss
یک افت آنتروپی متقاطع سیگموید از تصاویر واقعی و آرایه ای از تصاویر است (زیرا اینها تصاویر واقعی هستند) . -
generated_loss
یک افت آنتروپی متقاطع سیگموئیدی از تصاویر تولید شده و آرایه ای از صفر است (زیرا این تصاویر جعلی هستند) . -
total_loss
مجموعreal_loss
وgenerated_loss
است.
def discriminator_loss(disc_real_output, disc_generated_output):
real_loss = loss_object(tf.ones_like(disc_real_output), disc_real_output)
generated_loss = loss_object(tf.zeros_like(disc_generated_output), disc_generated_output)
total_disc_loss = real_loss + generated_loss
return total_disc_loss
روش آموزش برای متمایز کننده در زیر نشان داده شده است.
برای کسب اطلاعات بیشتر در مورد معماری و هایپرپارامترها می توانید به مقاله pix2pix مراجعه کنید.
بهینه سازها و یک بازرسی محافظ را تعریف کنید
generator_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)
discriminator_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)
checkpoint_dir = './training_checkpoints'
checkpoint_prefix = os.path.join(checkpoint_dir, "ckpt")
checkpoint = tf.train.Checkpoint(generator_optimizer=generator_optimizer,
discriminator_optimizer=discriminator_optimizer,
generator=generator,
discriminator=discriminator)
تولید تصاویر
تابعی بنویسید تا در حین آموزش برخی از تصاویر را ترسیم کند.
- تصاویر را از مجموعه آزمایشی به ژنراتور منتقل کنید.
- سپس ژنراتور تصویر ورودی را به خروجی ترجمه می کند.
- آخرین مرحله این است که پیش بینی ها و voila را ترسیم کنید!
def generate_images(model, test_input, tar):
prediction = model(test_input, training=True)
plt.figure(figsize=(15, 15))
display_list = [test_input[0], tar[0], prediction[0]]
title = ['Input Image', 'Ground Truth', 'Predicted Image']
for i in range(3):
plt.subplot(1, 3, i+1)
plt.title(title[i])
# Getting the pixel values in the [0, 1] range to plot.
plt.imshow(display_list[i] * 0.5 + 0.5)
plt.axis('off')
plt.show()
تست تابع:
for example_input, example_target in test_dataset.take(1):
generate_images(generator, example_input, example_target)
آموزش
- برای هر نمونه ورودی یک خروجی تولید می کند.
- متمایز کننده
input_image
و تصویر تولید شده را به عنوان اولین ورودی دریافت می کند. ورودی دومinput_image
وtarget_image
است. - در مرحله بعد، مولد و تلفات تفکیک کننده را محاسبه کنید.
- سپس، گرادیانهای تلفات را با توجه به متغیرهای (ورودیهای) مولد و تفکیککننده محاسبه کرده و آنها را برای بهینهساز اعمال کنید.
- در نهایت، تلفات را به TensorBoard وارد کنید.
log_dir="logs/"
summary_writer = tf.summary.create_file_writer(
log_dir + "fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S"))
@tf.function
def train_step(input_image, target, step):
with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:
gen_output = generator(input_image, training=True)
disc_real_output = discriminator([input_image, target], training=True)
disc_generated_output = discriminator([input_image, gen_output], training=True)
gen_total_loss, gen_gan_loss, gen_l1_loss = generator_loss(disc_generated_output, gen_output, target)
disc_loss = discriminator_loss(disc_real_output, disc_generated_output)
generator_gradients = gen_tape.gradient(gen_total_loss,
generator.trainable_variables)
discriminator_gradients = disc_tape.gradient(disc_loss,
discriminator.trainable_variables)
generator_optimizer.apply_gradients(zip(generator_gradients,
generator.trainable_variables))
discriminator_optimizer.apply_gradients(zip(discriminator_gradients,
discriminator.trainable_variables))
with summary_writer.as_default():
tf.summary.scalar('gen_total_loss', gen_total_loss, step=step//1000)
tf.summary.scalar('gen_gan_loss', gen_gan_loss, step=step//1000)
tf.summary.scalar('gen_l1_loss', gen_l1_loss, step=step//1000)
tf.summary.scalar('disc_loss', disc_loss, step=step//1000)
حلقه آموزش واقعی از آنجایی که این آموزش می تواند بیش از یک مجموعه داده را اجرا کند، و مجموعه داده ها از نظر اندازه بسیار متفاوت هستند، حلقه آموزشی به گونه ای تنظیم شده است که به جای دوره ها، در مراحل کار کند.
- در تعداد مراحل تکرار می شود.
- هر 10 مرحله یک نقطه (
.
) چاپ کنید. - هر 1 هزار مرحله: صفحه نمایش را پاک کنید و
generate_images
را اجرا کنید تا پیشرفت را نشان دهید. - هر 5 هزار قدم: یک ایست بازرسی را ذخیره کنید.
def fit(train_ds, test_ds, steps):
example_input, example_target = next(iter(test_ds.take(1)))
start = time.time()
for step, (input_image, target) in train_ds.repeat().take(steps).enumerate():
if (step) % 1000 == 0:
display.clear_output(wait=True)
if step != 0:
print(f'Time taken for 1000 steps: {time.time()-start:.2f} sec\n')
start = time.time()
generate_images(generator, example_input, example_target)
print(f"Step: {step//1000}k")
train_step(input_image, target, step)
# Training step
if (step+1) % 10 == 0:
print('.', end='', flush=True)
# Save (checkpoint) the model every 5k steps
if (step + 1) % 5000 == 0:
checkpoint.save(file_prefix=checkpoint_prefix)
این حلقه آموزشی گزارش هایی را ذخیره می کند که می توانید در TensorBoard برای نظارت بر پیشرفت آموزش مشاهده کنید.
اگر روی یک ماشین محلی کار می کنید، یک فرآیند TensorBoard جداگانه راه اندازی می کنید. هنگام کار در یک نوت بوک، قبل از شروع آموزش، بیننده را برای نظارت با TensorBoard راه اندازی کنید.
برای راه اندازی بیننده موارد زیر را در یک سلول کد جایگذاری کنید:
%load_ext tensorboard
%tensorboard --logdir {log_dir}
در نهایت حلقه آموزشی را اجرا کنید:
fit(train_dataset, test_dataset, steps=40000)
Time taken for 1000 steps: 36.53 sec
Step: 39k ....................................................................................................
اگر میخواهید نتایج TensorBoard را به صورت عمومی به اشتراک بگذارید، میتوانید با کپی کردن موارد زیر در یک سلول کد، گزارشها را در TensorBoard.dev آپلود کنید.
tensorboard dev upload --logdir {log_dir}
می توانید نتایج اجرای قبلی این نوت بوک را در TensorBoard.dev مشاهده کنید.
TensorBoard.dev یک تجربه مدیریت شده برای میزبانی، ردیابی و به اشتراک گذاری آزمایش های ML با همه است.
همچنین میتواند با استفاده از <iframe>
به صورت درون خطی قرار گیرد:
display.IFrame(
src="https://tensorboard.dev/experiment/lZ0C6FONROaUMfjYkVyJqw",
width="100%",
height="1000px")
تفسیر گزارشها هنگام آموزش GAN (یا cGAN مانند pix2pix) در مقایسه با طبقهبندی ساده یا مدل رگرسیون ظریفتر است. چیزهایی که باید به دنبال آن باشید:
- بررسی کنید که نه مولد و نه مدل تفکیک کننده "برنده" شده باشد. اگر
gen_gan_loss
یاdisc_loss
بسیار کم شود، نشانگر آن است که این مدل بر دیگری تسلط دارد و شما با موفقیت مدل ترکیبی را آموزش نمیدهید. - مقدار
log(2) = 0.69
نقطه مرجع خوبی برای این تلفات است، زیرا نشان دهنده گیجی 2 است - متمایزکننده به طور متوسط در مورد دو گزینه به همان اندازه نامشخص است. - برای
disc_loss
، مقدار کمتر از0.69
به این معنی است که تشخیص دهنده در مجموعه ترکیبی تصاویر واقعی و تولید شده بهتر از تصادفی عمل می کند. - برای
gen_gan_loss
، مقدار زیر0.69
به این معنی است که ژنراتور در فریب دادن متمایزکننده بهتر از تصادفی عمل می کند. - با پیشرفت آموزش،
gen_l1_loss
باید کاهش یابد.
آخرین بازرسی را بازیابی کنید و شبکه را آزمایش کنید
ls {checkpoint_dir}
checkpoint ckpt-5.data-00000-of-00001 ckpt-1.data-00000-of-00001 ckpt-5.index ckpt-1.index ckpt-6.data-00000-of-00001 ckpt-2.data-00000-of-00001 ckpt-6.index ckpt-2.index ckpt-7.data-00000-of-00001 ckpt-3.data-00000-of-00001 ckpt-7.index ckpt-3.index ckpt-8.data-00000-of-00001 ckpt-4.data-00000-of-00001 ckpt-8.index ckpt-4.index
# Restoring the latest checkpoint in checkpoint_dir
checkpoint.restore(tf.train.latest_checkpoint(checkpoint_dir))
<tensorflow.python.training.tracking.util.CheckpointLoadStatus at 0x7f35cfd6b8d0>
با استفاده از مجموعه آزمایشی تعدادی تصویر ایجاد کنید
# Run the trained model on a few examples from the test set
for inp, tar in test_dataset.take(5):
generate_images(generator, inp, tar)