{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":21755,"databundleVersionId":1475600,"sourceType":"competition"}],"dockerImageVersionId":30805,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# # This Python 3 environment comes with many helpful analytics libraries installed\n# # It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# # For example, here's several helpful packages to load\n\n# import numpy as np # linear algebra\n# import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# # Input data files are available in the read-only \"../input/\" directory\n# # For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\n# import os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\n# # You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# # You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session\n# import tensorflow as tf\n# from tensorflow.keras.layers import Input, Conv2D, Conv2DTranspose, LeakyReLU, ReLU, BatchNormalization, Add\n\n# def residual_block(x, filters):\n#     res = Conv2D(filters, kernel_size=3, strides=1, padding='same')(x)\n#     res = BatchNormalization()(res)\n#     res = ReLU()(res)\n#     res = Conv2D(filters, kernel_size=3, strides=1, padding='same')(res)\n#     res = BatchNormalization()(res)\n#     return Add()([x, res])  # Skip connection\n\n# def build_generator():\n#     inputs = Input(shape=(256, 256, 3))\n#     x = Conv2D(64, kernel_size=7, strides=1, padding='same')(inputs)\n#     x = BatchNormalization()(x)\n#     x = ReLU()(x)\n#     x = Conv2D(128, kernel_size=3, strides=2, padding='same')(x)\n#     x = BatchNormalization()(x)\n#     x = ReLU()(x)\n#     x = Conv2D(256, kernel_size=3, strides=2, padding='same')(x)\n#     x = BatchNormalization()(x)\n#     x = ReLU()(x)\n#     for _ in range(6):\n#         x = residual_block(x, 256)\n#     x = Conv2DTranspose(128, kernel_size=3, strides=2, padding='same')(x)\n#     x = BatchNormalization()(x)\n#     x = ReLU()(x)\n#     x = Conv2DTranspose(64, kernel_size=3, strides=2, padding='same')(x)\n#     x = BatchNormalization()(x)\n#     x = ReLU()(x)\n#     outputs = Conv2D(3, kernel_size=7, strides=1, padding='same', activation='tanh')(x)\n#     return tf.keras.Model(inputs, outputs)\n\n# def build_discriminator():\n#     inputs = Input(shape=(256, 256, 3))\n#     x = Conv2D(64, kernel_size=4, strides=2, padding='same')(inputs)\n#     x = LeakyReLU(alpha=0.2)(x)\n#     x = Conv2D(128, kernel_size=4, strides=2, padding='same')(x)\n#     x = BatchNormalization()(x)\n#     x = LeakyReLU(alpha=0.2)(x)\n#     x = Conv2D(256, kernel_size=4, strides=2, padding='same')(x)\n#     x = BatchNormalization()(x)\n#     x = LeakyReLU(alpha=0.2)(x)\n#     x = Conv2D(512, kernel_size=4, strides=1, padding='same')(x)\n#     x = BatchNormalization()(x)\n#     x = LeakyReLU(alpha=0.2)(x)\n#     outputs = Conv2D(1, kernel_size=4, strides=1, padding='same')(x)\n#     return tf.keras.Model(inputs, outputs)\n\n# generator_g = build_generator()\n# generator_f = build_generator()\n# discriminator_a = build_discriminator()\n# discriminator_b = build_discriminator()\n\n\n# loss_object = tf.keras.losses.BinaryCrossentropy(from_logits=True)\n# def generator_loss(fake_output):\n#     return loss_object(tf.ones_like(fake_output), fake_output)\n\n# def discriminator_loss(real_output, fake_output):\n#     real_loss = loss_object(tf.ones_like(real_output), real_output)\n#     fake_loss = loss_object(tf.zeros_like(fake_output), fake_output)\n#     return real_loss + fake_loss\n\n# def cycle_loss(real_image, cycled_image):\n#     return tf.reduce_mean(tf.abs(real_image - cycled_image))\n\n# def identity_loss(real_image, same_image):\n#     return tf.reduce_mean(tf.abs(real_image - same_image))\n\n# generator_g_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\n# generator_f_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\n# discriminator_a_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\n# discriminator_b_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\n\n# class CycleGAN(tf.keras.Model):\n#     def __init__(self, generator_g, generator_f, discriminator_a, discriminator_b, lambda_cycle=10.0, lambda_identity=5.0):\n#         super(CycleGAN, self).__init__()\n#         self.generator_g = generator_g\n#         self.generator_f = generator_f\n#         self.discriminator_a = discriminator_a\n#         self.discriminator_b = discriminator_b\n#         self.lambda_cycle = lambda_cycle\n#         self.lambda_identity = lambda_identity\n\n#     def compile(self, gen_g_optimizer, gen_f_optimizer, disc_a_optimizer, disc_b_optimizer, gen_loss_fn, disc_loss_fn, cycle_loss_fn, identity_loss_fn):\n#         super(CycleGAN, self).compile()\n#         self.gen_g_optimizer = gen_g_optimizer\n#         self.gen_f_optimizer = gen_f_optimizer\n#         self.disc_a_optimizer = disc_a_optimizer\n#         self.disc_b_optimizer = disc_b_optimizer\n#         self.gen_loss_fn = gen_loss_fn\n#         self.disc_loss_fn = disc_loss_fn\n#         self.cycle_loss_fn = cycle_loss_fn\n#         self.identity_loss_fn = identity_loss_fn\n\n#     def train_step(self, batch_data):\n#         real_a, real_b = batch_data\n#         with tf.GradientTape(persistent=True) as tape:\n#             fake_b = self.generator_g(real_a, training=True)\n#             fake_a = self.generator_f(real_b, training=True)\n#             cycled_a = self.generator_f(fake_b, training=True)\n#             cycled_b = self.generator_g(fake_a, training=True)\n#             same_a = self.generator_f(real_a, training=True)\n#             same_b = self.generator_g(real_b, training=True)\n#             disc_real_a = self.discriminator_a(real_a, training=True)\n#             disc_real_b = self.discriminator_b(real_b, training=True)\n#             disc_fake_a = self.discriminator_a(fake_a, training=True)\n#             disc_fake_b = self.discriminator_b(fake_b, training=True)\n#             gen_g_loss = self.gen_loss_fn(disc_fake_b)\n#             gen_f_loss = self.gen_loss_fn(disc_fake_a)\n#             total_cycle_loss = self.cycle_loss_fn(real_a, cycled_a) + self.cycle_loss_fn(real_b, cycled_b)\n#             total_identity_loss = self.identity_loss_fn(real_a, same_a) + self.identity_loss_fn(real_b, same_b)\n#             total_gen_g_loss = gen_g_loss + self.lambda_cycle * total_cycle_loss + self.lambda_identity * total_identity_loss\n#             total_gen_f_loss = gen_f_loss + self.lambda_cycle * total_cycle_loss + self.lambda_identity * total_identity_loss\n#             disc_a_loss = self.disc_loss_fn(disc_real_a, disc_fake_a)\n#             disc_b_loss = self.disc_loss_fn(disc_real_b, disc_fake_b)\n#         gen_g_gradients = tape.gradient(total_gen_g_loss, self.generator_g.trainable_variables)\n#         gen_f_gradients = tape.gradient(total_gen_f_loss, self.generator_f.trainable_variables)\n#         disc_a_gradients = tape.gradient(disc_a_loss, self.discriminator_a.trainable_variables)\n#         disc_b_gradients = tape.gradient(disc_b_loss, self.discriminator_b.trainable_variables)\n#         self.gen_g_optimizer.apply_gradients(zip(gen_g_gradients, self.generator_g.trainable_variables))\n#         self.gen_f_optimizer.apply_gradients(zip(gen_f_gradients, self.generator_f.trainable_variables))\n#         self.disc_a_optimizer.apply_gradients(zip(disc_a_gradients, self.discriminator_a.trainable_variables))\n#         self.disc_b_optimizer.apply_gradients(zip(disc_b_gradients, self.discriminator_b.trainable_variables))\n#         return {\"gen_g_loss\": total_gen_g_loss, \"gen_f_loss\": total_gen_f_loss, \"disc_a_loss\": disc_a_loss, \"disc_b_loss\": disc_b_loss}\n\n# # Tạo mô hình CycleGAN\n# cyclegan = CycleGAN(generator_g, generator_f, discriminator_a, discriminator_b)\n\n# # Compile với các optimizer và hàm mất mát\n# cyclegan.compile(\n#     gen_g_optimizer=generator_g_optimizer,\n#     gen_f_optimizer=generator_f_optimizer,\n#     disc_a_optimizer=discriminator_a_optimizer,\n#     disc_b_optimizer=discriminator_b_optimizer,\n#     gen_loss_fn=generator_loss,\n#     disc_loss_fn=discriminator_loss,\n#     cycle_loss_fn=cycle_loss,\n#     identity_loss_fn=identity_loss\n# )\n\n# # Huấn luyện mô hình với tập dữ liệu (ví dụ dataset đã[_{{{CITATION{{{_1{](https://github.com/PDEUXA/AIF_CYCLEGAN/tree/a1323925e54c09ad99e4f09321f16e230d6e404e/main.py)\n\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-10-02T08:29:58.873641Z","iopub.execute_input":"2025-10-02T08:29:58.873882Z","iopub.status.idle":"2025-10-02T08:29:58.928107Z","shell.execute_reply.started":"2025-10-02T08:29:58.873857Z","shell.execute_reply":"2025-10-02T08:29:58.927551Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport tensorflow as tf\nfrom tensorflow.keras.layers import Input, Conv2D, Conv2DTranspose, LeakyReLU, ReLU, BatchNormalization, Add\nimport os\nfrom tensorflow.keras.preprocessing.image import load_img, img_to_array\n\n# Khám phá các tệp dữ liệu\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-02T08:29:58.929921Z","iopub.execute_input":"2025-10-02T08:29:58.930252Z","iopub.status.idle":"2025-10-02T08:30:30.718280Z","shell.execute_reply.started":"2025-10-02T08:29:58.930217Z","shell.execute_reply":"2025-10-02T08:30:30.717384Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import time\nimport numpy as np\nimport tensorflow as tf\nimport matplotlib.pyplot as plt\nfrom tensorflow.keras.preprocessing.image import load_img, img_to_array\nimport os\n\n# Kích thước ảnh 256x256\nIMG_SIZE = (256, 256)\n\ndef load_and_preprocess_image(filepath, img_size=IMG_SIZE):\n    filepath = filepath.numpy().decode('utf-8')\n    img = load_img(filepath, target_size=img_size)\n    img_array = img_to_array(img)\n    img_array = (img_array / 127.5) - 1.0\n    return img_array\n\ndef load_dataset(directory, img_size=IMG_SIZE):\n    filepaths = [os.path.join(directory, filename) for filename in os.listdir(directory)]\n    dataset = tf.data.Dataset.from_tensor_slices(filepaths)\n    dataset = dataset.map(lambda x: tf.py_function(func=load_and_preprocess_image, inp=[x], Tout=tf.float32))\n    return dataset\n\nmonet_dataset = load_dataset('/kaggle/input/gan-getting-started/monet_jpg', img_size=IMG_SIZE)\nphoto_dataset = load_dataset('/kaggle/input/gan-getting-started/photo_jpg', img_size=IMG_SIZE)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-02T08:30:30.719745Z","iopub.execute_input":"2025-10-02T08:30:30.720231Z","iopub.status.idle":"2025-10-02T08:30:31.754401Z","shell.execute_reply.started":"2025-10-02T08:30:30.720203Z","shell.execute_reply":"2025-10-02T08:30:31.753492Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.layers import Input, Conv2D, Conv2DTranspose, LeakyReLU, ReLU, BatchNormalization, Add\n\ndef residual_block(x, filters):\n    res = Conv2D(filters, kernel_size=3, strides=1, padding='same')(x)\n    res = BatchNormalization()(res)\n    res = ReLU()(res)\n    res = Conv2D(filters, kernel_size=3, strides=1, padding='same')(res)\n    res = BatchNormalization()(res)\n    return Add()([x, res])  # Skip connection\n\ndef build_generator():\n    inputs = Input(shape=(256, 256, 3))  # Kích thước đầu vào 256x256\n    x = Conv2D(64, kernel_size=7, strides=1, padding='same')(inputs)\n    x = BatchNormalization()(x)\n    x = ReLU()(x)\n    x = Conv2D(128, kernel_size=3, strides=2, padding='same')(x)\n    x = BatchNormalization()(x)\n    x = ReLU()(x)\n    x = Conv2D(256, kernel_size=3, strides=2, padding='same')(x)\n    x = BatchNormalization()(x)\n    x = ReLU()(x)\n    for _ in range(6):\n        x = residual_block(x, 256)\n    x = Conv2DTranspose(128, kernel_size=3, strides=2, padding='same')(x)\n    x = BatchNormalization()(x)\n    x = ReLU()(x)\n    x = Conv2DTranspose(64, kernel_size=3, strides=2, padding='same')(x)\n    x = BatchNormalization()(x)\n    x = ReLU()(x)\n    outputs = Conv2D(3, kernel_size=7, strides=1, padding='same', activation='tanh')(x)\n    return tf.keras.Model(inputs, outputs)\n\ndef build_discriminator():\n    inputs = Input(shape=(256, 256, 3))  # Kích thước đầu vào 256x256\n    x = Conv2D(64, kernel_size=4, strides=2, padding='same')(inputs)\n    x = LeakyReLU(negative_slope=0.2)(x)\n    x = Conv2D(128, kernel_size=4, strides=2, padding='same')(x)\n    x = BatchNormalization()(x)\n    x = LeakyReLU(negative_slope=0.2)(x)\n    x = Conv2D(256, kernel_size=4, strides=2, padding='same')(x)\n    x = BatchNormalization()(x)\n    x = LeakyReLU(negative_slope=0.2)(x)\n    outputs = Conv2D(1, kernel_size=4, strides=1, padding='same')(x)\n    return tf.keras.Model(inputs, outputs)\n\n\ngenerator_g = build_generator()\ngenerator_f = build_generator()\ndiscriminator_a = build_discriminator()\ndiscriminator_b = build_discriminator()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-02T08:30:31.756335Z","iopub.execute_input":"2025-10-02T08:30:31.756622Z","iopub.status.idle":"2025-10-02T08:30:32.367195Z","shell.execute_reply.started":"2025-10-02T08:30:31.756591Z","shell.execute_reply":"2025-10-02T08:30:32.366490Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Định nghĩa hàm mất mát và tối ưu hóa\nloss_object = tf.keras.losses.BinaryCrossentropy(from_logits=True)\n\ndef generator_loss(fake_output):\n    return loss_object(tf.ones_like(fake_output), fake_output)\n\ndef discriminator_loss(real_output, fake_output):\n    real_loss = loss_object(tf.ones_like(real_output), real_output)\n    fake_loss = loss_object(tf.zeros_like(fake_output), fake_output)\n    return real_loss + fake_loss\n\ndef cycle_loss(real_image, cycled_image):\n    real_image = tf.cast(real_image, tf.float32)  # Chuyển đổi về float32\n    cycled_image = tf.cast(cycled_image, tf.float32)  # Chuyển đổi về float32\n    return tf.reduce_mean(tf.abs(real_image - cycled_image))\n\ndef identity_loss(real_image, same_image):\n    real_image = tf.cast(real_image, tf.float32)  # Chuyển đổi về float32\n    same_image = tf.cast(same_image, tf.float32)  # Chuyển đổi về float32\n    return tf.reduce_mean(tf.abs(real_image - same_image))\n\n\ngenerator_g_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\ngenerator_f_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\ndiscriminator_a_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\ndiscriminator_b_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\n\n# Định nghĩa class CycleGAN\nimport matplotlib.pyplot as plt\n\nclass CycleGAN(tf.keras.Model):\n    def __init__(self, generator_g, generator_f, discriminator_a, discriminator_b, lambda_cycle=10.0, lambda_identity=5.0):\n        super(CycleGAN, self).__init__()\n        self.generator_g = generator_g\n        self.generator_f = generator_f\n        self.discriminator_a = discriminator_a\n        self.discriminator_b = discriminator_b\n        self.lambda_cycle = lambda_cycle\n        self.lambda_identity = lambda_identity\n\n    def compile(self, gen_g_optimizer, gen_f_optimizer, disc_a_optimizer, disc_b_optimizer, gen_loss_fn, disc_loss_fn, cycle_loss_fn, identity_loss_fn):\n        super(CycleGAN, self).compile()\n        self.gen_g_optimizer = gen_g_optimizer\n        self.gen_f_optimizer = gen_f_optimizer\n        self.disc_a_optimizer = disc_a_optimizer\n        self.disc_b_optimizer = disc_b_optimizer\n        self.gen_loss_fn = gen_loss_fn\n        self.disc_loss_fn = disc_loss_fn\n        self.cycle_loss_fn = cycle_loss_fn\n        self.identity_loss_fn = identity_loss_fn\n\n        self.gen_g_losses = []\n        self.gen_f_losses = []\n        self.disc_a_losses = []\n        self.disc_b_losses = []\n        self.cycle_losses = []\n        self.identity_losses = []\n\n    def train_step(self, batch_data):\n        real_a, real_b = batch_data\n        with tf.GradientTape(persistent=True) as tape:\n            fake_b = self.generator_g(real_a, training=True)\n            fake_a = self.generator_f(real_b, training=True)\n            cycled_a = self.generator_f(fake_b, training=True)\n            cycled_b = self.generator_g(fake_a, training=True)\n            same_a = self.generator_f(real_a, training=True)\n            same_b = self.generator_g(real_b, training=True)\n            disc_real_a = self.discriminator_a(real_a, training=True)\n            disc_real_b = self.discriminator_b(real_b, training=True)\n            disc_fake_a = self.discriminator_a(fake_a, training=True)\n            disc_fake_b = self.discriminator_b(fake_b, training=True)\n            \n            gen_g_loss = self.gen_loss_fn(disc_fake_b)\n            gen_f_loss = self.gen_loss_fn(disc_fake_a)\n            cycle_loss = self.cycle_loss_fn(real_a, cycled_a) + self.cycle_loss_fn(real_b, cycled_b)\n            identity_loss = self.identity_loss_fn(real_a, same_a) + self.identity_loss_fn(real_b, same_b)\n            total_gen_g_loss = gen_g_loss + self.lambda_cycle * cycle_loss + self.lambda_identity * identity_loss\n            total_gen_f_loss = gen_f_loss + self.lambda_cycle * cycle_loss + self.lambda_identity * identity_loss\n            disc_a_loss = self.disc_loss_fn(disc_real_a, disc_fake_a)\n            disc_b_loss = self.disc_loss_fn(disc_real_b, disc_fake_b)\n        \n        gen_g_gradients = tape.gradient(total_gen_g_loss, self.generator_g.trainable_variables)\n        gen_f_gradients = tape.gradient(total_gen_f_loss, self.generator_f.trainable_variables)\n        disc_a_gradients = tape.gradient(disc_a_loss, self.discriminator_a.trainable_variables)\n        disc_b_gradients = tape.gradient(disc_b_loss, self.discriminator_b.trainable_variables)\n\n        self.gen_g_optimizer.apply_gradients(zip(gen_g_gradients, self.generator_g.trainable_variables))\n        self.gen_f_optimizer.apply_gradients(zip(gen_f_gradients, self.generator_f.trainable_variables))\n        self.disc_a_optimizer.apply_gradients(zip(disc_a_gradients, self.discriminator_a.trainable_variables))\n        self.disc_b_optimizer.apply_gradients(zip(disc_b_gradients, self.discriminator_b.trainable_variables))\n\n        self.gen_g_losses.append(total_gen_g_loss.numpy())\n        self.gen_f_losses.append(total_gen_f_loss.numpy())\n        self.disc_a_losses.append(disc_a_loss.numpy())\n        self.disc_b_losses.append(disc_b_loss.numpy())\n        self.cycle_losses.append(cycle_loss.numpy())\n        self.identity_losses.append(identity_loss.numpy())\n        \n        return {\n            \"gen_g_loss\": total_gen_g_loss,\n            \"gen_f_loss\": total_gen_f_loss,\n            \"disc_a_loss\": disc_a_loss,\n            \"disc_b_loss\": disc_b_loss,\n            \"cycle_loss\": cycle_loss,\n            \"identity_loss\": identity_loss\n        }\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-02T08:30:32.368347Z","iopub.execute_input":"2025-10-02T08:30:32.368643Z","iopub.status.idle":"2025-10-02T08:30:32.394417Z","shell.execute_reply.started":"2025-10-02T08:30:32.368616Z","shell.execute_reply":"2025-10-02T08:30:32.393706Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# Tạo mô hình CycleGAN\ncyclegan = CycleGAN(generator_g, generator_f, discriminator_a, discriminator_b)\n\n# Compile với các optimizer và hàm mất mát\ncyclegan.compile(\n    gen_g_optimizer=generator_g_optimizer,\n    gen_f_optimizer=generator_f_optimizer,\n    disc_a_optimizer=discriminator_a_optimizer,\n    disc_b_optimizer=discriminator_b_optimizer,\n    gen_loss_fn=generator_loss,\n    disc_loss_fn=discriminator_loss,\n    cycle_loss_fn=cycle_loss,\n    identity_loss_fn=identity_loss\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-02T08:30:32.395397Z","iopub.execute_input":"2025-10-02T08:30:32.395689Z","iopub.status.idle":"2025-10-02T08:30:32.410173Z","shell.execute_reply.started":"2025-10-02T08:30:32.395665Z","shell.execute_reply":"2025-10-02T08:30:32.409361Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n\nBUFFER_SIZE = 800\nBATCH_SIZE = 1  # Tăng kích thước batch để giảm số lượng batch cần thiết\n\ndataset = tf.data.Dataset.zip((photo_dataset, monet_dataset))\ntrain_dataset = dataset.shuffle(BUFFER_SIZE).batch(BATCH_SIZE)\n\nfrom tensorflow.keras import mixed_precision\nmixed_precision.set_global_policy('mixed_float16')\nlr = 0.0001\n# Hàm scheduling\ndef scheduler(epoch, lr):\n    if epoch < 5:\n        return lr\n    elif epoch < 10:\n        return lr * 0.1\n    elif epoch < 15:\n        return lr * 0.01\n    else:\n        return lr * 0.001\n\nlr_scheduler = tf.keras.callbacks.LearningRateScheduler(scheduler)\nearly_stopping = tf.keras.callbacks.EarlyStopping(monitor='loss', patience=5)\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-02T08:30:32.411084Z","iopub.execute_input":"2025-10-02T08:30:32.411348Z","iopub.status.idle":"2025-10-02T08:30:32.427836Z","shell.execute_reply.started":"2025-10-02T08:30:32.411324Z","shell.execute_reply":"2025-10-02T08:30:32.427181Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Kiểm tra một batch dữ liệu\nfor photo, monet in train_dataset.take(1):\n    print(f'Photo shape: {photo.shape}, Monet shape: {monet.shape}')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-02T08:30:32.428868Z","iopub.execute_input":"2025-10-02T08:30:32.429175Z","iopub.status.idle":"2025-10-02T08:30:37.730699Z","shell.execute_reply.started":"2025-10-02T08:30:32.429134Z","shell.execute_reply":"2025-10-02T08:30:37.729745Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import time\nimport numpy as np\nimport tensorflow as tf\nimport matplotlib.pyplot as plt\nfrom tensorflow.keras.preprocessing.image import load_img, img_to_array\nimport os\nimport zipfile\n\n\nfrom tensorflow.keras import mixed_precision\nmixed_precision.set_global_policy('mixed_float16')\n\nEPOCHS = 1\n\nfor epoch in range(EPOCHS):\n    start_time = time.time()  # Ghi lại thời gian bắt đầu của epoch\n\n    for batch in train_dataset:\n        metrics = cyclegan.train_step(batch)\n        \n    end_time = time.time()\n    epoch_duration = end_time - start_time\n\n    # Hiển thị tiến trình huấn luyện sau mỗi epoch\n    print(f'Epoch: {epoch + 1}/{EPOCHS}, Time: {epoch_duration:.2f} seconds')\n    print(f\"  gen_g_loss: {metrics['gen_g_loss']:.4f}, gen_f_loss: {metrics['gen_f_loss']:.4f}\")\n    print(f\"  disc_a_loss: {metrics['disc_a_loss']:.4f}, disc_b_loss: {metrics['disc_b_loss']:.4f}\")\n    print(f\"  cycle_loss: {metrics['cycle_loss']:.4f}, identity_loss: {metrics['identity_loss']:.4f}\")\n    \n    # Lưu lại mô hình sau mỗi epoch nếu cần thiết\n    cyclegan.save_weights(f'cyclegan_epoch_{epoch}.weights.h5')\n\n# Bạn cũng có thể lưu mô hình cuối cùng\ncyclegan.save_weights('cyclegan_final.weights.h5')\n\nplt.figure(figsize=(12, 8))\n\nplt.subplot(2, 2, 1)\nplt.plot(cyclegan.gen_g_losses, label='Generator G Loss')\nplt.plot(cyclegan.gen_f_losses, label='Generator F Loss')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.legend()\n\nplt.subplot(2, 2, 2)\nplt.plot(cyclegan.disc_a_losses, label='Discriminator A Loss')\nplt.plot(cyclegan.disc_b_losses, label='Discriminator B Loss')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.legend()\n\nplt.subplot(2, 2, 3)\nplt.plot(cyclegan.cycle_losses, label='Cycle Consistency Loss')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.legend()\n\nplt.subplot(2, 2, 4)\nplt.plot(cyclegan.identity_losses, label='Identity Loss')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.legend()\n\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-02T08:30:37.732849Z","iopub.execute_input":"2025-10-02T08:30:37.733114Z","execution_failed":"2025-10-02T08:35:13.831Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# Định nghĩa lại photo_dataset\nphoto_dataset = load_dataset('/kaggle/input/gan-getting-started/photo_jpg', img_size=IMG_SIZE)\n\n# Khởi tạo danh sách ảnh thực tế từ photo_dataset\nphoto_images = []\nfor img in photo_dataset.take(7028):  # Lấy 7028 ảnh từ tập dữ liệu ảnh thực tế\n    photo_images.append(img.numpy())\n\ndef generate_images(model, test_input):\n    prediction = model(test_input, training=False)\n    return prediction\n\n# Tạo thư mục tạm để lưu ảnh nếu chưa có\noutput_dir = 'monet_images'\nos.makedirs(output_dir, exist_ok=True)\n\n# Sinh ảnh phong cách Monet và lưu chúng dưới dạng jpg\nfor i, photo in enumerate(photo_images):\n    generated_monet = generate_images(generator_g, np.expand_dims(photo, axis=0))\n    img = (generated_monet[0] + 1) * 127.5  # Chuyển đổi ảnh về khoảng [0, 255]\n    img = img.numpy().astype(np.uint8)\n    img_path = os.path.join(output_dir, f'monet_image_{i+1}.jpg')\n    plt.imsave(img_path, img)\n\n# Nén các ảnh vào tệp zip\nzip_filename = '/kaggle/working/images.zip'\nwith zipfile.ZipFile(zip_filename, 'w') as zipf:\n    for root, dirs, files in os.walk(output_dir):\n        for file in files:\n            zipf.write(os.path.join(root, file), os.path.relpath(os.path.join(root, file), output_dir))\n\nprint(f\"Đã tạo và nén {len(photo_images)} ảnh vào tệp {zip_filename}\")\n\n","metadata":{"trusted":true,"execution":{"execution_failed":"2025-10-02T08:35:13.831Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}