{ "cells": [ { "cell_type": "markdown", "id": "e25e43bd", "metadata": {}, "source": [ "## MODEL TRAINING" ] }, { "cell_type": "code", "execution_count": 1, "id": "4b632063", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "0ec2b3fd7ede4583bf8671e0e41d07dd", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Output()" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n" ], "text/plain": [] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# ct_liver_seg.ipynb\n",
"# train a semantic segmentation model to predict the liver & tumor region in CT volume\n",
"#\n",
"# author : xiao deng\n",
"# date : 20210613\n",
"# platform: Macbook pro 14\n",
"\n",
"import os\n",
"import random\n",
"\n",
"import numpy as np\n",
"from scipy.ndimage import zoom\n",
"from rich.progress import track\n",
"import matplotlib.pyplot as plt\n",
"\n",
"\n",
"# 1) Load CT scans and corresponding masks\n",
"# file name format: {series_uid}_{slice_index}.npy\n",
"# series ids: 0~49, 50 CT scans in total\n",
"ct_dir = 'images'\n",
"mask_dir = 'labels'\n",
"file_names = os.listdir(ct_dir)\n",
"\n",
"images = {}\n",
"masks = {}\n",
"for file_name in track(file_names, 'Load & preprocess data ...'):\n",
" series_uid = int(file_name[:3])\n",
" slice_index = int(file_name[4:7])\n",
" \n",
" # 2) CT image preprocessing\n",
" # Load image\n",
" image = np.load(f'{ct_dir}/{file_name}')\n",
" mask = np.load(f'{mask_dir}/{file_name}')\n",
" \n",
" # Resizing\n",
" # image size: 512*512 -> 256*256\n",
" image = zoom(image, 0.5, mode='nearest')\n",
" mask = zoom(mask, 0.5, mode='nearest')\n",
" image = image.astype('float32')\n",
" \n",
" # Split and binarize masks\n",
" liver_mask = np.where(mask > 0, 1, 0).astype('float32')\n",
" tumor_mask = np.where(mask > 1, 1, 0).astype('float32')\n",
" mask = np.zeros((256, 256, 2), dtype='float32')\n",
" mask[:, :, 0] = liver_mask\n",
" mask[:, :, 1] = tumor_mask\n",
" \n",
" # CT windowing (Liver window adjustment)\n",
" # ref: https://radiopaedia.org/articles/windowing-ct\n",
" liver_wind_upper_bound = 180\n",
" liver_wind_lower_bound = -120\n",
" image[image > liver_wind_upper_bound] = liver_wind_upper_bound\n",
" image[image < liver_wind_lower_bound] = liver_wind_lower_bound\n",
" \n",
" # Min-max normalization\n",
" image = (image - liver_wind_lower_bound) / (liver_wind_upper_bound - liver_wind_lower_bound)\n",
" \n",
" if series_uid not in images:\n",
" images[series_uid] = []\n",
" masks[series_uid] = []\n",
" images[series_uid].append(image)\n",
" masks[series_uid].append(mask)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "5e5fb92d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"train series uids: [43, 1, 28, 14, 36, 12, 0, 27, 47, 7, 33, 34, 20, 49, 5, 38, 11, 23, 40, 15, 10, 21, 46, 3, 9, 4, 41, 42, 39, 17, 29, 45, 6, 35, 18, 8, 44, 13, 37, 22]\n",
"valid series uids: [30, 19, 25, 31, 32, 16, 2, 26, 48, 24]\n",
"\n",
"train_x shape: (1160, 256, 256, 1)\n",
"train_y shape: (1160, 256, 256, 2)\n",
"valid_x shape: (290, 256, 256, 1)\n",
"valid_y shape: (290, 256, 256, 2)\n",
"Metal device set to: Apple M1 Pro\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"2022-06-15 12:33:14.407365: I tensorflow/core/common_runtime/pluggable_device/pluggable_device_factory.cc:305] Could not identify NUMA node of platform GPU ID 0, defaulting to 0. Your kernel may not have been built with NUMA support.\n",
"2022-06-15 12:33:14.407462: I tensorflow/core/common_runtime/pluggable_device/pluggable_device_factory.cc:271] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 0 MB memory) -> physical PluggableDevice (device: 0, name: METAL, pci bus id: