{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import torch\nimport pandas as pd\n\nfrom tensorflow.keras.models import *\nfrom tensorflow.keras.layers import *\nfrom tensorflow.keras.optimizers import *\nfrom tensorflow.keras.callbacks import ModelCheckpoint\nfrom tensorflow.keras import backend as keras\n#from tensorflow import keras\nfrom PIL import Image\nfrom tensorflow.keras import backend as K\n\n# for path related functionalities\nimport os\n# for array operations\nimport numpy as np\n# tensorflow framework\nimport tensorflow as tf\n# keras API for deep learning\nfrom tensorflow import keras\n# for image visulaizations\nimport matplotlib.pyplot as plt\n# for legends and other supporting functionalities\nimport matplotlib as mpl\n# for viewing iteration status\nfrom tqdm import tqdm\nimport wandb\nimport random","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-06-09T07:30:38.901130Z","iopub.execute_input":"2023-06-09T07:30:38.901471Z","iopub.status.idle":"2023-06-09T07:30:52.206227Z","shell.execute_reply.started":"2023-06-09T07:30:38.901443Z","shell.execute_reply":"2023-06-09T07:30:52.205164Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# CONSTANT","metadata":{}},{"cell_type":"code","source":"img_size=(512,512)\nIMAGE_WIDTH = 512\nIMAGE_HEIGHT = 512\n\nTRAIN_DIR = '/kaggle/input/bkai-igh-neopolyp/train/train/'\nTRAIN_MASK_DIR = '/kaggle/input/bkai-igh-neopolyp/train_gt/train_gt/'\nTEST_DIR = '/kaggle/input/bkai-igh-neopolyp/test/test/'\n\nDEVICE = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n\nN_CLASS = 3\n\nnumber_image_train = 1000 # max  = 1000","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:30:52.207824Z","iopub.execute_input":"2023-06-09T07:30:52.208087Z","iopub.status.idle":"2023-06-09T07:30:52.214359Z","shell.execute_reply.started":"2023-06-09T07:30:52.208064Z","shell.execute_reply":"2023-06-09T07:30:52.213387Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# GET IMAGE","metadata":{}},{"cell_type":"markdown","source":"## get path","metadata":{}},{"cell_type":"code","source":"# a list to collect paths of 1000 images\nimage_path = []\nfor root, dirs, files in os.walk(TRAIN_DIR):\n    # iterate over 1000 images\n    for file in files:\n        # create path\n        path = os.path.join(root,file)\n        # add path to list\n        image_path.append(path)\nlen(image_path)","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:30:52.215551Z","iopub.execute_input":"2023-06-09T07:30:52.216167Z","iopub.status.idle":"2023-06-09T07:30:53.838678Z","shell.execute_reply.started":"2023-06-09T07:30:52.216139Z","shell.execute_reply":"2023-06-09T07:30:53.837786Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# a list to collect paths of 1000 masks\nmask_path = []\nfor root, dirs, files in os.walk(TRAIN_MASK_DIR):\n    #iterate over 1000 masks\n    for file in files:\n        # obtain the path\n        path = os.path.join(root,file)\n        # add path to the list\n        mask_path.append(path)\nlen(mask_path)","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:30:53.839880Z","iopub.execute_input":"2023-06-09T07:30:53.840295Z","iopub.status.idle":"2023-06-09T07:30:55.347042Z","shell.execute_reply.started":"2023-06-09T07:30:53.840272Z","shell.execute_reply":"2023-06-09T07:30:55.346260Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Get list images - chanel = 3","metadata":{}},{"cell_type":"code","source":"%%time\n# create a list to store images\nimages = []\n# iterate over 1000 image paths\nfor path in tqdm(image_path[:number_image_train]):\n    # read file\n    file = tf.io.read_file(path)\n    # decode png file into a tensor\n    image = tf.image.decode_png(file, channels=3, dtype=tf.uint8)\n    # append to the list\n    images.append(image)","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:30:55.349253Z","iopub.execute_input":"2023-06-09T07:30:55.349730Z","iopub.status.idle":"2023-06-09T07:31:14.346191Z","shell.execute_reply.started":"2023-06-09T07:30:55.349706Z","shell.execute_reply":"2023-06-09T07:31:14.345249Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Get list mask - chanel = 1","metadata":{}},{"cell_type":"code","source":"# Lấy giá trị lớn nhất tại mỗi điểm ảnh In ra giá trị lớn nhất\ndef label_mask(mask):\n    image_arr = mask.numpy()\n    \n    A = mask[:, :, 0]  # Kênh màu đỏ\n    B = mask[:, :, 1]  # Kênh màu xanh lá cây\n    C = mask[:, :, 2]  # Kênh màu xanh dương\n    \n    # Tạo một mảng mới với giá trị lớn nhất từng vị trí của A, B, C\n    max_values = np.maximum(np.maximum(A, B), C)\n\n    # Khởi tạo mảng kết quả với kích thước tương tự và các giá trị ban đầu là 0\n    result = np.zeros_like(max_values)\n\n    # Gán giá trị tương ứng theo từng mảng\n    result[max_values == A] = 1\n    result[max_values == B] = 2\n    result[max_values == C] = 0\n    \n    tensor = tf.constant(result)\n    return tensor","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:31:14.347522Z","iopub.execute_input":"2023-06-09T07:31:14.347897Z","iopub.status.idle":"2023-06-09T07:31:14.355231Z","shell.execute_reply.started":"2023-06-09T07:31:14.347869Z","shell.execute_reply":"2023-06-09T07:31:14.354201Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\n# create a list to store masks\nmasks = []\nencoded_masks = []\n# iterate over 1000 mask paths\nfor path in tqdm(mask_path[:number_image_train]):\n    # read the file\n    file = tf.io.read_file(path)\n    # decode png file into a tensor\n    mask = tf.image.decode_jpeg(file, channels=3)\n    encoded_mask = label_mask(mask)\n    encoded_mask = tf.expand_dims(encoded_mask, axis=2) \n    encoded_mask = tf.constant(encoded_mask)\n\n    # append mask to the list\n    masks.append(mask)\n    encoded_masks.append(encoded_mask)","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:31:14.356398Z","iopub.execute_input":"2023-06-09T07:31:14.357458Z","iopub.status.idle":"2023-06-09T07:31:38.341290Z","shell.execute_reply.started":"2023-06-09T07:31:14.357407Z","shell.execute_reply":"2023-06-09T07:31:38.340255Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.imshow(random.choice(encoded_masks))\nprint(encoded_masks[4].shape)\nplt.colorbar()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:31:38.343120Z","iopub.execute_input":"2023-06-09T07:31:38.343780Z","iopub.status.idle":"2023-06-09T07:31:38.666515Z","shell.execute_reply.started":"2023-06-09T07:31:38.343740Z","shell.execute_reply":"2023-06-09T07:31:38.665538Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# BUILD MODEL","metadata":{}},{"cell_type":"code","source":"def double_conv_block(x, n_filters):\n    # Conv2D then ReLU activation\n    x = layers.Conv2D(n_filters, 3, padding = \"same\", activation = \"relu\", kernel_initializer = \"he_normal\")(x)\n    # Conv2D then ReLU activation\n    x = layers.Conv2D(n_filters, 3, padding = \"same\", activation = \"relu\", kernel_initializer = \"he_normal\")(x)\n    \n    return x","metadata":{"execution":{"iopub.status.busy":"2023-06-10T06:28:52.398033Z","iopub.execute_input":"2023-06-10T06:28:52.398454Z","iopub.status.idle":"2023-06-10T06:28:52.405781Z","shell.execute_reply.started":"2023-06-10T06:28:52.398423Z","shell.execute_reply":"2023-06-10T06:28:52.404387Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def downsample_block(x, n_filters):\n    f = double_conv_block(x, n_filters)\n    p = layers.MaxPool2D(2)(f)\n    p = layers.Dropout(0.3)(p)\n    return f, p\n\ndef upsample_block(x, conv_features, n_filters):\n    # upsample\n    x = layers.Conv2DTranspose(n_filters, 3, 2, padding=\"same\")(x)\n    # concatenate\n    x = layers.concatenate([x, conv_features])\n    # dropout\n    x = layers.Dropout(0.3)(x)\n    # Conv2D twice with ReLU activation\n    x = double_conv_block(x, n_filters)\n    return x","metadata":{"execution":{"iopub.status.busy":"2023-06-10T06:28:54.180138Z","iopub.execute_input":"2023-06-10T06:28:54.180511Z","iopub.status.idle":"2023-06-10T06:28:54.187929Z","shell.execute_reply.started":"2023-06-10T06:28:54.180483Z","shell.execute_reply":"2023-06-10T06:28:54.185407Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_unet_model(pretrained_weights=None, input_size(512,512,3), n_class=3):\n    # 3 class = Ác tính + lành tính + backgound\n    \n     # inputs\n    inputs = layers.Input(shape=input_size)\n\n    # encoder: contracting path - downsample\n    # 1 - downsample\n    f1, p1 = downsample_block(inputs, 64)\n    # 2 - downsample\n    f2, p2 = downsample_block(p1, 128)\n    # 3 - downsample\n    f3, p3 = downsample_block(p2, 256)\n    # 4 - downsample\n    f4, p4 = downsample_block(p3, 512)\n\n    # 5 - bottleneck\n    bottleneck = double_conv_block(p4, 1024)\n\n    # decoder: expanding path - upsample\n    # 6 - upsample\n    u6 = upsample_block(bottleneck, f4, 512)\n    # 7 - upsample\n    u7 = upsample_block(u6, f3, 256)\n    # 8 - upsample\n    u8 = upsample_block(u7, f2, 128)\n    # 9 - upsample\n    u9 = upsample_block(u8, f1, 64)\n\n    # outputs\n    outputs = layers.Conv2D(n_class, 1, padding=\"same\", activation = \"softmax\")(u9)\n\n    # unet model with Keras Functional API\n    unet_model = tf.keras.Model(inputs, outputs, name=\"U-Net\")\n    \n    if(pretrained_weights):\n        model.load_weights(pretrained_weights)\n\n    return unet_model","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:31:38.668348Z","iopub.execute_input":"2023-06-09T07:31:38.668942Z","iopub.status.idle":"2023-06-09T07:31:38.979139Z","shell.execute_reply.started":"2023-06-09T07:31:38.668879Z","shell.execute_reply":"2023-06-09T07:31:38.977444Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Step 2: Initialize the model. Train from scratch!\nmodel = build_unet_model()\n# model.summary()","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:31:38.997521Z","iopub.execute_input":"2023-06-09T07:31:38.998839Z","iopub.status.idle":"2023-06-09T07:31:39.489359Z","shell.execute_reply.started":"2023-06-09T07:31:38.998802Z","shell.execute_reply":"2023-06-09T07:31:39.488033Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# keras.utils.plot_model(model, show_shapes=True)","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:31:39.491351Z","iopub.execute_input":"2023-06-09T07:31:39.491817Z","iopub.status.idle":"2023-06-09T07:31:39.496718Z","shell.execute_reply.started":"2023-06-09T07:31:39.491778Z","shell.execute_reply":"2023-06-09T07:31:39.495902Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Resize","metadata":{}},{"cell_type":"code","source":"def resize_image(image):\n    # scale the image\n    image = tf.cast(image, tf.float32)\n    image = image / 255.0\n    # resize image\n    image = tf.image.resize(image, (512,512))\n    return image\n\ndef resize_mask(mask):\n    # resize the mask\n    mask = tf.image.resize(mask, (512,512))\n    mask = tf.cast(mask, tf.uint8)\n    return mask    ","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:31:39.497925Z","iopub.execute_input":"2023-06-09T07:31:39.498229Z","iopub.status.idle":"2023-06-09T07:31:39.512445Z","shell.execute_reply.started":"2023-06-09T07:31:39.498203Z","shell.execute_reply":"2023-06-09T07:31:39.511374Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"encoded_masks[0].shape, images[0].shape","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:31:39.517077Z","iopub.execute_input":"2023-06-09T07:31:39.518142Z","iopub.status.idle":"2023-06-09T07:31:39.532009Z","shell.execute_reply.started":"2023-06-09T07:31:39.518097Z","shell.execute_reply":"2023-06-09T07:31:39.530722Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nX = [resize_image(i) for i in images]\ny = [resize_mask(m) for m in encoded_masks]\nlen(X), len(y)","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:31:39.533262Z","iopub.execute_input":"2023-06-09T07:31:39.533655Z","iopub.status.idle":"2023-06-09T07:31:48.570375Z","shell.execute_reply.started":"2023-06-09T07:31:39.533626Z","shell.execute_reply":"2023-06-09T07:31:48.569255Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images[0].dtype, encoded_masks[0].dtype, X[0].dtype, y[0].dtype","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:31:48.571491Z","iopub.execute_input":"2023-06-09T07:31:48.571845Z","iopub.status.idle":"2023-06-09T07:31:48.578889Z","shell.execute_reply.started":"2023-06-09T07:31:48.571822Z","shell.execute_reply":"2023-06-09T07:31:48.577813Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y[0].shape, X[0].shape","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:31:48.580266Z","iopub.execute_input":"2023-06-09T07:31:48.580906Z","iopub.status.idle":"2023-06-09T07:31:48.593044Z","shell.execute_reply.started":"2023-06-09T07:31:48.580871Z","shell.execute_reply":"2023-06-09T07:31:48.591852Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plot an image\nplt.subplot(1,2,1)\nplt.imshow(X[0])\nplt.colorbar()\n\n#plot a mask\nplt.subplot(1,2,2)\nplt.imshow(y[0], cmap='jet')\nplt.colorbar()\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:31:48.594660Z","iopub.execute_input":"2023-06-09T07:31:48.595046Z","iopub.status.idle":"2023-06-09T07:31:49.057247Z","shell.execute_reply.started":"2023-06-09T07:31:48.595010Z","shell.execute_reply":"2023-06-09T07:31:49.055973Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n# split data into 80/20 ratio\ntrain_X, val_X,train_y, val_y = train_test_split(X, y, test_size=0.2, \n                                                      random_state=0\n                                                     )\n# develop tf Dataset objects\ntrain_X = tf.data.Dataset.from_tensor_slices(train_X)\nval_X = tf.data.Dataset.from_tensor_slices(val_X)\n\ntrain_y = tf.data.Dataset.from_tensor_slices(train_y)\nval_y = tf.data.Dataset.from_tensor_slices(val_y)\n\n# verify the shapes and data types\ntrain_X.element_spec, train_y.element_spec, val_X.element_spec, val_y.element_spec","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:31:49.058802Z","iopub.execute_input":"2023-06-09T07:31:49.059341Z","iopub.status.idle":"2023-06-09T07:31:50.827784Z","shell.execute_reply.started":"2023-06-09T07:31:49.059287Z","shell.execute_reply":"2023-06-09T07:31:50.826596Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# zip images and masks\ntrain = tf.data.Dataset.zip((train_X, train_y))\nval = tf.data.Dataset.zip((val_X, val_y))","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:31:50.829177Z","iopub.execute_input":"2023-06-09T07:31:50.829509Z","iopub.status.idle":"2023-06-09T07:31:50.844311Z","shell.execute_reply.started":"2023-06-09T07:31:50.829482Z","shell.execute_reply":"2023-06-09T07:31:50.842809Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BATCH_SIZE = 16\nNUM_EPOCHS = 10\nNUM_WORKERS = 4\nLEARNING_RATE = 0.001 # 1e - 4\n\nAT = tf.data.AUTOTUNE\nBUFFER = 1000\n\nSTEPS_PER_EPOCH = 800//BATCH_SIZE\nVALIDATION_STEPS = 200//BATCH_SIZE","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:31:50.845925Z","iopub.execute_input":"2023-06-09T07:31:50.846244Z","iopub.status.idle":"2023-06-09T07:31:50.853120Z","shell.execute_reply.started":"2023-06-09T07:31:50.846222Z","shell.execute_reply":"2023-06-09T07:31:50.852313Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = train.cache().shuffle(BUFFER).batch(BATCH_SIZE).repeat()\ntrain = train.prefetch(buffer_size=AT)\nval = val.batch(BATCH_SIZE)","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:31:50.854006Z","iopub.execute_input":"2023-06-09T07:31:50.854368Z","iopub.status.idle":"2023-06-09T07:31:50.890622Z","shell.execute_reply.started":"2023-06-09T07:31:50.854336Z","shell.execute_reply":"2023-06-09T07:31:50.889073Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def Compile_Model():\n    model.compile(loss=keras.losses.SparseCategoricalCrossentropy(from_logits=False),\n            optimizer=keras.optimizers.RMSprop(lr=0.001),\n            metrics=['accuracy']) \n\ndef Compile_Model_v2():\n    model.compile(loss='categorical_crossentropy',\n            optimizer='adam',\n            metrics=['accuracy'])\n\nCompile_Model()","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:31:50.891851Z","iopub.execute_input":"2023-06-09T07:31:50.892140Z","iopub.status.idle":"2023-06-09T07:31:50.915766Z","shell.execute_reply.started":"2023-06-09T07:31:50.892115Z","shell.execute_reply":"2023-06-09T07:31:50.914515Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.callbacks import ModelCheckpoint\n\nfilepath = 'model-ep{epoch:03d}-loss{loss:.3f}.h5'\ncheckpoint = ModelCheckpoint(filepath, monitor='val_loss', verbose=1, save_best_only=True, mode='min')","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:31:50.917027Z","iopub.execute_input":"2023-06-09T07:31:50.917342Z","iopub.status.idle":"2023-06-09T07:31:50.925074Z","shell.execute_reply.started":"2023-06-09T07:31:50.917315Z","shell.execute_reply":"2023-06-09T07:31:50.923714Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training and Fine-tuning\n","metadata":{}},{"cell_type":"code","source":"%%time\nhist_1 = model.fit(train,\n                   validation_data=val,\n                   epochs=NUM_EPOCHS,\n                   batch_size = BATCH_SIZE,\n                   workers=NUM_WORKERS,\n                   verbose=1,\n                   steps_per_epoch=STEPS_PER_EPOCH,\n                   validation_steps=STEPS_PER_EPOCH,\n                   callbacks=[checkpoint])","metadata":{"execution":{"iopub.status.busy":"2023-06-09T07:31:50.926427Z","iopub.execute_input":"2023-06-09T07:31:50.927368Z","iopub.status.idle":"2023-06-09T14:27:43.733210Z","shell.execute_reply.started":"2023-06-09T07:31:50.927331Z","shell.execute_reply":"2023-06-09T14:27:43.643346Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save('save_model')","metadata":{"execution":{"iopub.status.busy":"2023-06-09T15:22:26.011837Z","iopub.execute_input":"2023-06-09T15:22:26.012719Z","iopub.status.idle":"2023-06-09T15:22:34.658666Z","shell.execute_reply.started":"2023-06-09T15:22:26.012593Z","shell.execute_reply":"2023-06-09T15:22:34.656638Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Predictions","metadata":{}},{"cell_type":"code","source":"# for img, mask in val:\n#     for index, image in enumerate(mask):\n#         print(index, image.shape)\n#         plt.subplot(1,2,1+index)\n#         plt.imshow(image)\n        \n# plt.show()\n","metadata":{"execution":{"iopub.status.busy":"2023-06-09T14:27:50.783597Z","iopub.execute_input":"2023-06-09T14:27:50.785389Z","iopub.status.idle":"2023-06-09T14:27:50.792616Z","shell.execute_reply.started":"2023-06-09T14:27:50.785319Z","shell.execute_reply":"2023-06-09T14:27:50.790908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# select a validation data batch\nNORM = mpl.colors.Normalize(vmin=0, vmax=58)\n\nimg, mask = next(iter(val))\n# make prediction\npred = model.predict(img)\nplt.figure(figsize=(20,28))\n\nk = 0\nfor i in pred:\n    # plot the predicted mask\n    plt.subplot(4,3,1+k*3)\n    i = tf.argmax(i, axis=-1)\n    plt.imshow(i,cmap='jet', norm=NORM\n              )\n    plt.axis('off')\n    plt.title('Prediction')\n    \n    # plot the groundtruth mask\n    plt.subplot(4,3,2+k*3)\n    plt.imshow(mask[k], cmap='jet', norm=NORM)\n    plt.axis('off')\n    plt.title('Ground Truth')\n    \n    # plot the actual image\n    plt.subplot(4,3,3+k*3)\n    plt.imshow(img[k])\n    plt.axis('off')\n    plt.title('Actual Image')\n    k += 1\n    if k == 4: break\nplt.suptitle('Predition After 50 Epochs (No Fine-tuning)', color='red', size=20)  \nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-09T15:52:59.160046Z","iopub.execute_input":"2023-06-09T15:52:59.160526Z","iopub.status.idle":"2023-06-09T15:53:21.518797Z","shell.execute_reply.started":"2023-06-09T15:52:59.160487Z","shell.execute_reply":"2023-06-09T15:53:21.517692Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history_1 = hist_1.history\nacc=history_1['accuracy']\nval_acc = history_1['val_accuracy']\n\n\nplt.plot(acc[:150], '-', label='Training')\nplt.plot(val_acc[:150], '--', label='Validation')\nplt.plot([50,50],[0.7,1.0], '--g', label='Fine-Tuning')\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\nplt.ylim([0.7,1.0])\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-09T15:53:21.520848Z","iopub.execute_input":"2023-06-09T15:53:21.521434Z","iopub.status.idle":"2023-06-09T15:53:21.754540Z","shell.execute_reply.started":"2023-06-09T15:53:21.521405Z","shell.execute_reply":"2023-06-09T15:53:21.753544Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# NOTE\n- Đang có vấn đề với hàm softmax khi xuất ra - trả về kết quả xác xuất \n- mà ở dưới lại dùng hàm loss ","metadata":{}}]}