{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":71549,"databundleVersionId":8561470,"sourceType":"competition"}],"dockerImageVersionId":30746,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os, time, gc \nimport math\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nfrom tqdm import tqdm\nimport copy\nimport ctypes\n\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\n\nfrom tqdm import tqdm\nimport timm\nimport torch\nimport torch.nn as nn\nimport torch.functional as F\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader, TensorDataset\nimport torchvision.transforms as transforms # use pytorch data argument \nimport torchvision\nimport albumentations as A\n\nimport pydicom\nimport cv2\nimport glob\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import LabelEncoder\n\nfrom sklearn.metrics import roc_curve, auc ,roc_auc_score\nfrom sklearn.metrics import confusion_matrix, classification_report, ConfusionMatrixDisplay\n\n#system\nimport psutil\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","scrolled":true,"execution":{"iopub.status.busy":"2024-10-05T12:14:22.347932Z","iopub.execute_input":"2024-10-05T12:14:22.348297Z","iopub.status.idle":"2024-10-05T12:14:36.942497Z","shell.execute_reply.started":"2024-10-05T12:14:22.348267Z","shell.execute_reply":"2024-10-05T12:14:36.941580Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def memoryInfo():\n    memory_info = psutil.virtual_memory()\n\n    # Print the used and available memory\n    print(f\"Total Memory: {memory_info.total / (1024 ** 3):.2f} GB\")\n    print(f\"Available Memory: {memory_info.available / (1024 ** 3):.2f} GB\")\n    print(f\"Used Memory: {memory_info.used / (1024 ** 3):.2f} GB\")\n    print(f\"Percentage Used: {memory_info.percent}%\")","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:36.944274Z","iopub.execute_input":"2024-10-05T12:14:36.944880Z","iopub.status.idle":"2024-10-05T12:14:36.950385Z","shell.execute_reply.started":"2024-10-05T12:14:36.944850Z","shell.execute_reply":"2024-10-05T12:14:36.949276Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def clearMemory():\n    for _ in range(5):\n        torch.cuda.empty_cache()\n        gc.collect()\n        ctypes.CDLL(\"libc.so.6\").malloc_trim(0)\n        time.sleep(0.3)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:36.951520Z","iopub.execute_input":"2024-10-05T12:14:36.951925Z","iopub.status.idle":"2024-10-05T12:14:36.963786Z","shell.execute_reply.started":"2024-10-05T12:14:36.951899Z","shell.execute_reply":"2024-10-05T12:14:36.962662Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Configure","metadata":{}},{"cell_type":"code","source":"clearMemory()\nmemoryInfo()\n","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:36.965885Z","iopub.execute_input":"2024-10-05T12:14:36.966177Z","iopub.status.idle":"2024-10-05T12:14:39.345997Z","shell.execute_reply.started":"2024-10-05T12:14:36.966153Z","shell.execute_reply":"2024-10-05T12:14:39.345039Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CFG:\n    seed = 42\n    N_WORKERS = os.cpu_count() \n    \n    # Model Define\n    inChannel = 30 # number of Image for each input\n    nLABELS = 25 # train label (target)\n    nClasses = 75 # 3 x 25 # each label has 3 classes\n    IMGSIZE = 320 #312#512\n    test_size = 0.2\n    BATCH_SIZE = 32#16\n    USE_AMP = True\n    USE_EFFNETV1 = False #True\n    USE_EFFNETV2 = True\n    \n    \n    modelName1 = \"efficientnet_b0.ra_in1k\" #  efficientnet v1 b0\n    modelName2 = \"tf_efficientnetv2_b1.in1k\" # efficientnet v2 b1\n    modelName3 =  \"tf_efficientnet_b1.ns_jft_in1k\" #efficientnet v1 b1\n    modelName4 = \"tf_efficientnetv2_b2.in1k\" # efficientnet v2 b2  #avoid use b2 model easy GPU out of memory \n    \n    # Dataset Path Define\n    rootDir = \"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification\"\n    trainImagesDir= \"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_images\"\n    testImagesDir = \"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/test_images\"\n    \n    trainMetaDataFile = \"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train.csv\"\n    trainLabelFile = \"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_label_coordinates.csv\"\n    trainDesFile = \"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_series_descriptions.csv\"\n    testDesFile = \"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/test_series_descriptions.csv\"\n    \n    submitFile = \"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/sample_submission.csv\"\n    \n    ","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:39.347528Z","iopub.execute_input":"2024-10-05T12:14:39.348027Z","iopub.status.idle":"2024-10-05T12:14:39.356280Z","shell.execute_reply.started":"2024-10-05T12:14:39.347990Z","shell.execute_reply":"2024-10-05T12:14:39.355190Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 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","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:39.357494Z","iopub.execute_input":"2024-10-05T12:14:39.357818Z","iopub.status.idle":"2024-10-05T12:14:39.372325Z","shell.execute_reply.started":"2024-10-05T12:14:39.357793Z","shell.execute_reply":"2024-10-05T12:14:39.371504Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\ndevice","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:39.374036Z","iopub.execute_input":"2024-10-05T12:14:39.374572Z","iopub.status.idle":"2024-10-05T12:14:39.450478Z","shell.execute_reply.started":"2024-10-05T12:14:39.374528Z","shell.execute_reply":"2024-10-05T12:14:39.449306Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load Dataset","metadata":{}},{"cell_type":"code","source":"trainMetaData= pd.read_csv(CFG.trainMetaDataFile)\ntrainMetaData","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:42.401847Z","iopub.execute_input":"2024-10-05T12:14:42.402230Z","iopub.status.idle":"2024-10-05T12:14:42.491448Z","shell.execute_reply.started":"2024-10-05T12:14:42.402199Z","shell.execute_reply":"2024-10-05T12:14:42.490385Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainMetaData.isnull().sum()","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:42.706095Z","iopub.execute_input":"2024-10-05T12:14:42.707095Z","iopub.status.idle":"2024-10-05T12:14:42.724415Z","shell.execute_reply.started":"2024-10-05T12:14:42.707061Z","shell.execute_reply":"2024-10-05T12:14:42.723433Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Change the state to Label.\n\nThe dataframe contains some Nans, which we will replace with -100 so that We and function can ignore them when calculating the loss and score.","metadata":{}},{"cell_type":"code","source":"# trainMetaData =trainMetaData.fillna(-100)\ntrainMetaData =trainMetaData.dropna()\ntrainMetaData","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:43.489581Z","iopub.execute_input":"2024-10-05T12:14:43.490345Z","iopub.status.idle":"2024-10-05T12:14:43.531077Z","shell.execute_reply.started":"2024-10-05T12:14:43.490308Z","shell.execute_reply":"2024-10-05T12:14:43.530032Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainMetaData.isnull().sum()","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:43.861929Z","iopub.execute_input":"2024-10-05T12:14:43.862832Z","iopub.status.idle":"2024-10-05T12:14:43.876353Z","shell.execute_reply.started":"2024-10-05T12:14:43.862789Z","shell.execute_reply":"2024-10-05T12:14:43.875356Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Convert catergy into id Label","metadata":{}},{"cell_type":"code","source":"label2Id = {\"Normal/Mild\": 0, \"Moderate\": 1, \"Severe\": 2}\n","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:44.425315Z","iopub.execute_input":"2024-10-05T12:14:44.425694Z","iopub.status.idle":"2024-10-05T12:14:44.430283Z","shell.execute_reply.started":"2024-10-05T12:14:44.425666Z","shell.execute_reply":"2024-10-05T12:14:44.429274Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainMetaData =trainMetaData.replace(label2Id)\ntrainMetaData","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:44.719982Z","iopub.execute_input":"2024-10-05T12:14:44.720906Z","iopub.status.idle":"2024-10-05T12:14:44.791021Z","shell.execute_reply.started":"2024-10-05T12:14:44.720871Z","shell.execute_reply":"2024-10-05T12:14:44.790031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainLabel = pd.read_csv(CFG.trainLabelFile)\ntrainLabel","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:45.427012Z","iopub.execute_input":"2024-10-05T12:14:45.428170Z","iopub.status.idle":"2024-10-05T12:14:45.590696Z","shell.execute_reply.started":"2024-10-05T12:14:45.428134Z","shell.execute_reply":"2024-10-05T12:14:45.589586Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainDescript = pd.read_csv(CFG.trainDesFile)\ntrainDescript","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:45.744303Z","iopub.execute_input":"2024-10-05T12:14:45.745220Z","iopub.status.idle":"2024-10-05T12:14:45.768071Z","shell.execute_reply.started":"2024-10-05T12:14:45.745186Z","shell.execute_reply":"2024-10-05T12:14:45.766980Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"testDescript = pd.read_csv(CFG.testDesFile)\ntestDescript","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:46.064658Z","iopub.execute_input":"2024-10-05T12:14:46.065629Z","iopub.status.idle":"2024-10-05T12:14:46.083960Z","shell.execute_reply.started":"2024-10-05T12:14:46.065597Z","shell.execute_reply":"2024-10-05T12:14:46.082763Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submit = pd.read_csv(CFG.submitFile)\nsubmit","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:46.348286Z","iopub.execute_input":"2024-10-05T12:14:46.349300Z","iopub.status.idle":"2024-10-05T12:14:46.372868Z","shell.execute_reply.started":"2024-10-05T12:14:46.349263Z","shell.execute_reply":"2024-10-05T12:14:46.371798Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# EDA","metadata":{}},{"cell_type":"code","source":"# get train data study id\ntrainStudyId = trainMetaData[\"study_id\"].unique()\nlen(trainStudyId)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:46.860623Z","iopub.execute_input":"2024-10-05T12:14:46.861024Z","iopub.status.idle":"2024-10-05T12:14:46.871672Z","shell.execute_reply.started":"2024-10-05T12:14:46.860993Z","shell.execute_reply":"2024-10-05T12:14:46.870660Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainMetaData[\"study_id\"].value_counts()","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:47.087694Z","iopub.execute_input":"2024-10-05T12:14:47.088113Z","iopub.status.idle":"2024-10-05T12:14:47.101382Z","shell.execute_reply.started":"2024-10-05T12:14:47.088082Z","shell.execute_reply":"2024-10-05T12:14:47.100316Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainMetaData.isnull().sum()","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:47.422120Z","iopub.execute_input":"2024-10-05T12:14:47.423228Z","iopub.status.idle":"2024-10-05T12:14:47.432046Z","shell.execute_reply.started":"2024-10-05T12:14:47.423179Z","shell.execute_reply":"2024-10-05T12:14:47.431028Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainMetaData.columns","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:47.785773Z","iopub.execute_input":"2024-10-05T12:14:47.786658Z","iopub.status.idle":"2024-10-05T12:14:47.793097Z","shell.execute_reply.started":"2024-10-05T12:14:47.786623Z","shell.execute_reply":"2024-10-05T12:14:47.792102Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainLabel.columns","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:48.157669Z","iopub.execute_input":"2024-10-05T12:14:48.158597Z","iopub.status.idle":"2024-10-05T12:14:48.164765Z","shell.execute_reply.started":"2024-10-05T12:14:48.158560Z","shell.execute_reply":"2024-10-05T12:14:48.163790Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# get all condition List (position of )\nconditionList = trainLabel[\"condition\"].unique().tolist() \nconditionList\n\nCONDITIONS = [\n    'spinal_canal_stenosis',\n    'left_neural_foraminal_narrowing',\n    'right_neural_foraminal_narrowing',\n    'left_subarticular_stenosis',\n    'right_subarticular_stenosis'\n]","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:48.447603Z","iopub.execute_input":"2024-10-05T12:14:48.447980Z","iopub.status.idle":"2024-10-05T12:14:48.459401Z","shell.execute_reply.started":"2024-10-05T12:14:48.447951Z","shell.execute_reply":"2024-10-05T12:14:48.458393Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# get all level \nlevelList = trainLabel[\"level\"].unique().tolist() \nlevelList\n\nLEVELS = [\n    'l1_l2',\n    'l2_l3',\n    'l3_l4',\n    'l4_l5',\n    'l5_s1',\n]","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:48.825282Z","iopub.execute_input":"2024-10-05T12:14:48.825676Z","iopub.status.idle":"2024-10-05T12:14:48.834903Z","shell.execute_reply.started":"2024-10-05T12:14:48.825644Z","shell.execute_reply":"2024-10-05T12:14:48.833792Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# output prediction labels\noutLabelList = submit.columns[1:].tolist()\nprint(outLabelList)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:49.103475Z","iopub.execute_input":"2024-10-05T12:14:49.103874Z","iopub.status.idle":"2024-10-05T12:14:49.109335Z","shell.execute_reply.started":"2024-10-05T12:14:49.103843Z","shell.execute_reply":"2024-10-05T12:14:49.108208Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"seriesList = trainDescript[\"series_description\"].unique().tolist()\nseriesList","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:49.490816Z","iopub.execute_input":"2024-10-05T12:14:49.491603Z","iopub.status.idle":"2024-10-05T12:14:49.499115Z","shell.execute_reply.started":"2024-10-05T12:14:49.491570Z","shell.execute_reply":"2024-10-05T12:14:49.497996Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## group of label 0, 1, 2","metadata":{}},{"cell_type":"code","source":"countResult =trainMetaData.iloc[:, 1:].apply(pd.value_counts).transpose()\ncountResult","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:50.256789Z","iopub.execute_input":"2024-10-05T12:14:50.257170Z","iopub.status.idle":"2024-10-05T12:14:50.291667Z","shell.execute_reply.started":"2024-10-05T12:14:50.257140Z","shell.execute_reply":"2024-10-05T12:14:50.290655Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## seem the Label 0 too large number of sample, we reduce number of sample in label 0","metadata":{}},{"cell_type":"code","source":"sumLabelGroup= countResult.sum(axis=0, numeric_only=True)\nsumLabelGroup","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:51.594093Z","iopub.execute_input":"2024-10-05T12:14:51.594484Z","iopub.status.idle":"2024-10-05T12:14:51.603127Z","shell.execute_reply.started":"2024-10-05T12:14:51.594451Z","shell.execute_reply":"2024-10-05T12:14:51.602027Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sumLabelGroup.plot(kind=\"bar\", title=\"Count Number of data for each class\");","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:52.262557Z","iopub.execute_input":"2024-10-05T12:14:52.262957Z","iopub.status.idle":"2024-10-05T12:14:52.631674Z","shell.execute_reply.started":"2024-10-05T12:14:52.262927Z","shell.execute_reply":"2024-10-05T12:14:52.630754Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainMetaData[trainMetaData.iloc[:, 2] == 0]","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:52.771669Z","iopub.execute_input":"2024-10-05T12:14:52.772599Z","iopub.status.idle":"2024-10-05T12:14:52.798718Z","shell.execute_reply.started":"2024-10-05T12:14:52.772562Z","shell.execute_reply":"2024-10-05T12:14:52.797595Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## find the sum of row label , if all label is 0, sum of result also zero","metadata":{}},{"cell_type":"code","source":"sumOFLabels= trainMetaData.iloc[:, 1:].sum(axis=1, numeric_only=True)\nsumOFLabels","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:54.021678Z","iopub.execute_input":"2024-10-05T12:14:54.022594Z","iopub.status.idle":"2024-10-05T12:14:54.032663Z","shell.execute_reply.started":"2024-10-05T12:14:54.022557Z","shell.execute_reply":"2024-10-05T12:14:54.031586Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"type(sumOFLabels)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:54.635048Z","iopub.execute_input":"2024-10-05T12:14:54.635453Z","iopub.status.idle":"2024-10-05T12:14:54.641882Z","shell.execute_reply.started":"2024-10-05T12:14:54.635421Z","shell.execute_reply":"2024-10-05T12:14:54.640761Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## find row only all label 0 and only 1 label 1 and only 1 label 2","metadata":{}},{"cell_type":"code","source":"allZeroidx =list(sumOFLabels[sumOFLabels == 0].index)\nallOneidx = list(sumOFLabels[sumOFLabels == 1].index)\nallTwoidx = list(sumOFLabels[sumOFLabels == 2].index)\n# type(allZeroidx)\nlen(allZeroidx), len(allOneidx),  len(allTwoidx)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:55.769856Z","iopub.execute_input":"2024-10-05T12:14:55.770236Z","iopub.status.idle":"2024-10-05T12:14:55.782854Z","shell.execute_reply.started":"2024-10-05T12:14:55.770206Z","shell.execute_reply":"2024-10-05T12:14:55.781679Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Drop all label in zero index ","metadata":{}},{"cell_type":"code","source":"# trainMetaData.drop(index=allZeroidx , inplace=True) # drop all lable 0\n# trainMetaData.drop(index=allOneidx , inplace=True) # drop all only 1 lable 1\n# trainMetaData.drop(index=allTwoidx , inplace=True) # drop all only 1 lable 2\n# trainMetaData.reset_index(drop=True, inplace= True)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:56.984199Z","iopub.execute_input":"2024-10-05T12:14:56.984589Z","iopub.status.idle":"2024-10-05T12:14:56.989024Z","shell.execute_reply.started":"2024-10-05T12:14:56.984558Z","shell.execute_reply":"2024-10-05T12:14:56.987996Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainMetaData","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:57.481669Z","iopub.execute_input":"2024-10-05T12:14:57.482759Z","iopub.status.idle":"2024-10-05T12:14:57.508050Z","shell.execute_reply.started":"2024-10-05T12:14:57.482698Z","shell.execute_reply":"2024-10-05T12:14:57.507043Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"countResult =trainMetaData.iloc[:, 1:].apply(pd.value_counts).transpose()\ncountResult","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:57.862039Z","iopub.execute_input":"2024-10-05T12:14:57.862404Z","iopub.status.idle":"2024-10-05T12:14:57.895938Z","shell.execute_reply.started":"2024-10-05T12:14:57.862376Z","shell.execute_reply":"2024-10-05T12:14:57.894894Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sumLabelGroup= countResult.sum(axis=0, numeric_only=True)\nsumLabelGroup","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:58.439448Z","iopub.execute_input":"2024-10-05T12:14:58.439852Z","iopub.status.idle":"2024-10-05T12:14:58.448587Z","shell.execute_reply.started":"2024-10-05T12:14:58.439820Z","shell.execute_reply":"2024-10-05T12:14:58.447433Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sumOFLabels= trainMetaData.iloc[:, 1:].sum(axis=1, numeric_only=True)\nsumOFLabels","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:58.882796Z","iopub.execute_input":"2024-10-05T12:14:58.883158Z","iopub.status.idle":"2024-10-05T12:14:58.894397Z","shell.execute_reply.started":"2024-10-05T12:14:58.883130Z","shell.execute_reply":"2024-10-05T12:14:58.893202Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### plot the label distribution, seem the training dataset is imbalance \n##### most of number sample in Label 0\n##### it affect to train AI model performance\n","metadata":{}},{"cell_type":"code","source":"sumLabelGroup.plot(kind=\"bar\", title=\"Count Number of data for each class\");","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:14:59.837735Z","iopub.execute_input":"2024-10-05T12:14:59.838155Z","iopub.status.idle":"2024-10-05T12:15:00.085933Z","shell.execute_reply.started":"2024-10-05T12:14:59.838123Z","shell.execute_reply":"2024-10-05T12:15:00.084825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"totalSample = sumLabelGroup.sum()\ntotalSample","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:00.452872Z","iopub.execute_input":"2024-10-05T12:15:00.453261Z","iopub.status.idle":"2024-10-05T12:15:00.460238Z","shell.execute_reply.started":"2024-10-05T12:15:00.453231Z","shell.execute_reply":"2024-10-05T12:15:00.459269Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## calucate each class weight : \n- equation1 : 1- (num of sample in class/ total sample)\n- equation2 : n_samples / (n_classes * n_samplesj)","metadata":{}},{"cell_type":"code","source":"# classWeg0 = round(1- (sumLabelGroup.iloc[0] /totalSample), 4) #  label 0 weight  -- equation 1\nclassWeg0 = round((totalSample/(3.0 *sumLabelGroup.iloc[0])), 4)  # label 0 weight -- equation 2\nclassWeg0","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:02.207609Z","iopub.execute_input":"2024-10-05T12:15:02.208001Z","iopub.status.idle":"2024-10-05T12:15:02.215037Z","shell.execute_reply.started":"2024-10-05T12:15:02.207972Z","shell.execute_reply":"2024-10-05T12:15:02.214079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# classWeg1 = round(1- (sumLabelGroup.iloc[1] /totalSample), 4) # label 1 weight -- equation 1\nclassWeg1 = round((totalSample/(3.0 *sumLabelGroup.iloc[1])), 4)  # label 1 weight -- equation 2\nclassWeg1","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:02.695842Z","iopub.execute_input":"2024-10-05T12:15:02.696227Z","iopub.status.idle":"2024-10-05T12:15:02.703471Z","shell.execute_reply.started":"2024-10-05T12:15:02.696197Z","shell.execute_reply":"2024-10-05T12:15:02.702405Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# classWeg2 = round(1-(sumLabelGroup.iloc[2]/totalSample), 4) # label 2 weight  -- equation 1\nclassWeg2 = round((totalSample/(3.0 *sumLabelGroup.iloc[2])), 4)  # label 2 weight -- equation 2\nclassWeg2","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:03.200430Z","iopub.execute_input":"2024-10-05T12:15:03.200834Z","iopub.status.idle":"2024-10-05T12:15:03.208169Z","shell.execute_reply.started":"2024-10-05T12:15:03.200802Z","shell.execute_reply":"2024-10-05T12:15:03.207110Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Define total number class for prediction","metadata":{}},{"cell_type":"code","source":"numLabels = len(conditionList) * len(levelList) #\nnumClasses = len(outLabelList) * numLabels\n\nnumLabels, numClasses","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:04.503828Z","iopub.execute_input":"2024-10-05T12:15:04.504555Z","iopub.status.idle":"2024-10-05T12:15:04.511461Z","shell.execute_reply.started":"2024-10-05T12:15:04.504522Z","shell.execute_reply":"2024-10-05T12:15:04.510479Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainStudyId[0]","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:05.028787Z","iopub.execute_input":"2024-10-05T12:15:05.029128Z","iopub.status.idle":"2024-10-05T12:15:05.035170Z","shell.execute_reply.started":"2024-10-05T12:15:05.029104Z","shell.execute_reply":"2024-10-05T12:15:05.034204Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainDescript[trainDescript[\"study_id\"] == trainStudyId[0]]","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:05.604086Z","iopub.execute_input":"2024-10-05T12:15:05.604443Z","iopub.status.idle":"2024-10-05T12:15:05.614868Z","shell.execute_reply.started":"2024-10-05T12:15:05.604416Z","shell.execute_reply":"2024-10-05T12:15:05.613973Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainDescript[trainDescript[\"study_id\"] == trainStudyId[1]]\n","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:06.080726Z","iopub.execute_input":"2024-10-05T12:15:06.081156Z","iopub.status.idle":"2024-10-05T12:15:06.092934Z","shell.execute_reply.started":"2024-10-05T12:15:06.081126Z","shell.execute_reply":"2024-10-05T12:15:06.091754Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"studyID1Label = trainLabel[trainLabel[\"study_id\"] == trainStudyId[1]]\nstudyID1Label","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:06.744106Z","iopub.execute_input":"2024-10-05T12:15:06.744726Z","iopub.status.idle":"2024-10-05T12:15:06.763580Z","shell.execute_reply.started":"2024-10-05T12:15:06.744677Z","shell.execute_reply":"2024-10-05T12:15:06.762768Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(studyID1Label)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:07.221287Z","iopub.execute_input":"2024-10-05T12:15:07.221649Z","iopub.status.idle":"2024-10-05T12:15:07.228322Z","shell.execute_reply.started":"2024-10-05T12:15:07.221619Z","shell.execute_reply":"2024-10-05T12:15:07.227231Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"studyID1Label[\"instance_number\"].unique()","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:07.732806Z","iopub.execute_input":"2024-10-05T12:15:07.733180Z","iopub.status.idle":"2024-10-05T12:15:07.740274Z","shell.execute_reply.started":"2024-10-05T12:15:07.733151Z","shell.execute_reply":"2024-10-05T12:15:07.739276Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Show sample Image","metadata":{}},{"cell_type":"code","source":"def readDCMImageFile(path, resize=False, normalize=False):\n    dicomData = pydicom.dcmread(path)\n    img = dicomData.pixel_array # get image array\n    if normalize:\n        #Image Intensity Normalization\n        img = (img - img.min()) / (img.max() - img.min() + 1e-6) * 255\n    if resize:\n        img = cv2.resize(img, (CFG.IMGSIZE, CFG.IMGSIZE),interpolation=cv2.INTER_CUBIC)\n#     print(dicomData)\n#     print(img.shape)\n    return img\n    ","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:08.807091Z","iopub.execute_input":"2024-10-05T12:15:08.807478Z","iopub.status.idle":"2024-10-05T12:15:08.815588Z","shell.execute_reply.started":"2024-10-05T12:15:08.807448Z","shell.execute_reply":"2024-10-05T12:15:08.814500Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tempImgList = trainDescript[(trainDescript[\"study_id\"] == trainStudyId[1]) & \n                            (trainDescript[\"series_description\"] == \"Sagittal T1\")]\ntempImgList","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:09.183497Z","iopub.execute_input":"2024-10-05T12:15:09.184242Z","iopub.status.idle":"2024-10-05T12:15:09.195909Z","shell.execute_reply.started":"2024-10-05T12:15:09.184209Z","shell.execute_reply":"2024-10-05T12:15:09.194989Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tempImgList","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:09.731105Z","iopub.execute_input":"2024-10-05T12:15:09.731870Z","iopub.status.idle":"2024-10-05T12:15:09.741199Z","shell.execute_reply.started":"2024-10-05T12:15:09.731836Z","shell.execute_reply":"2024-10-05T12:15:09.740248Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# find all train image path for specific Study ID \nfor i, row in tempImgList.iterrows():\n#     print({row[\"series_id\"]})\n    imagePath = f\"\"\"{CFG.trainImagesDir}/{trainStudyId[1]}/{row[\"series_id\"]}/*.dcm\"\"\"\n#     print(imagePath)\n    imageFileList =glob.glob(imagePath) # find image file in Path\n#     print(\"image File List: \", imageFileList)\n    sortedImgFileList = sorted(imageFileList)\n    print(\"Num of files : \", len(imageFileList))\n    plt.figure(figsize=(16, 10))\n    for i in range(10):\n        plt.subplot(5, 5, i+1)\n        img = readDCMImageFile(sortedImgFileList[i], resize= True,normalize=True)\n        plt.imshow(img, cmap=\"gray\")\n        plt.axis('off')\n    \n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:10.224667Z","iopub.execute_input":"2024-10-05T12:15:10.225078Z","iopub.status.idle":"2024-10-05T12:15:11.081027Z","shell.execute_reply.started":"2024-10-05T12:15:10.225048Z","shell.execute_reply":"2024-10-05T12:15:11.080094Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img = readDCMImageFile(sortedImgFileList[0])\nplt.imshow(img , cmap=\"gray\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:11.082492Z","iopub.execute_input":"2024-10-05T12:15:11.082804Z","iopub.status.idle":"2024-10-05T12:15:11.370400Z","shell.execute_reply.started":"2024-10-05T12:15:11.082779Z","shell.execute_reply":"2024-10-05T12:15:11.369392Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## Test ","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:11.372143Z","iopub.execute_input":"2024-10-05T12:15:11.372479Z","iopub.status.idle":"2024-10-05T12:15:11.376442Z","shell.execute_reply.started":"2024-10-05T12:15:11.372451Z","shell.execute_reply":"2024-10-05T12:15:11.375588Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Data Augmentation Function","metadata":{}},{"cell_type":"code","source":"# read image used Cv2 resize ,not l\ntestTransformFuct = transforms.Compose([\n    transforms.ToTensor(), # need covert to tensor first \n    transforms.Resize((CFG.IMGSIZE, CFG.IMGSIZE)), # provide error , when resied by cv2\n#     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n    transforms.Normalize(mean=0.5, std=0.5),  # fix dcm only gray image (1 channel)\n#     transforms.ToTensor(),\n])\n\ntrainTransformFuct = transforms.Compose([\n    transforms.ToTensor(), # need covert to tensor first\n    transforms.Resize((CFG.IMGSIZE, CFG.IMGSIZE)),  # provide error , when resied by cv2\n    transforms.RandomRotation(degrees=(0, 270)),\n    transforms.RandomHorizontalFlip(p=0.5),\n    transforms.RandomVerticalFlip(p=0.5),\n#         transforms.RandomResizedCrop(size=(CFG.imgSize, CFG.imgSize), \n#                                      scale=(0.2, 0.8),\n#                                      ratio=(0.05, 0.8)),\n#         transforms.ColorJitter(brightness=(0.8,1.2), \n#                                contrast=(1)),\n#                                saturation=(0.6,1.5)),\n#                                hue=(-0.5, 0.5)),\n#         transforms.RandomAffine(degrees=(0, 180), \n#                                 translate=(0.1, 0.2), \n#                                 scale=(0.5, 1.1)),\n#         transforms.RandomGrayscale(p=0.5),\n    transforms.GaussianBlur(kernel_size=(5, 9), sigma=(0.1, 5)),\n    transforms.RandomAdjustSharpness(sharpness_factor=3.0, p=0.5),\n    transforms.RandomInvert(p=0.2),\n    transforms.Normalize(mean=0.5, std=0.5), # fix dcm only gray image (1 channel)\n#     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), \n\n])","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:12.408683Z","iopub.execute_input":"2024-10-05T12:15:12.409072Z","iopub.status.idle":"2024-10-05T12:15:12.418422Z","shell.execute_reply.started":"2024-10-05T12:15:12.409043Z","shell.execute_reply":"2024-10-05T12:15:12.417433Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Define Custom Dataset","metadata":{}},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# train/Test split ","metadata":{}},{"cell_type":"code","source":"train, val = train_test_split(trainMetaData,\n                                  test_size= CFG.test_size,\n                                  random_state= CFG.seed)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:14.124474Z","iopub.execute_input":"2024-10-05T12:15:14.124857Z","iopub.status.idle":"2024-10-05T12:15:14.133863Z","shell.execute_reply.started":"2024-10-05T12:15:14.124829Z","shell.execute_reply":"2024-10-05T12:15:14.132837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.shape , val.shape","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:14.574572Z","iopub.execute_input":"2024-10-05T12:15:14.574953Z","iopub.status.idle":"2024-10-05T12:15:14.581655Z","shell.execute_reply.started":"2024-10-05T12:15:14.574924Z","shell.execute_reply":"2024-10-05T12:15:14.580508Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# n= 30\n# step = n / 10.0 # each sample step size\n# start = n / 2.0 - 4.0 * step # \n# end = n + 0.0001","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:15.000162Z","iopub.execute_input":"2024-10-05T12:15:15.000542Z","iopub.status.idle":"2024-10-05T12:15:15.004910Z","shell.execute_reply.started":"2024-10-05T12:15:15.000507Z","shell.execute_reply":"2024-10-05T12:15:15.003980Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# step,  start, end","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:15.437712Z","iopub.execute_input":"2024-10-05T12:15:15.438137Z","iopub.status.idle":"2024-10-05T12:15:15.442416Z","shell.execute_reply.started":"2024-10-05T12:15:15.438108Z","shell.execute_reply":"2024-10-05T12:15:15.441348Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# tempList =np.arange(start, end , step)\n# tempList","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:15.891503Z","iopub.execute_input":"2024-10-05T12:15:15.891899Z","iopub.status.idle":"2024-10-05T12:15:15.896497Z","shell.execute_reply.started":"2024-10-05T12:15:15.891869Z","shell.execute_reply":"2024-10-05T12:15:15.895415Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# for j, i in enumerate(np.arange(start, end , step)):\n#     print(\"j: \", j , \", i:\", i)\n#     ind2 = max(0, int((i-0.5001).round()))\n#     print(\"ind2: \", ind2)\n    ","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:16.212525Z","iopub.execute_input":"2024-10-05T12:15:16.212918Z","iopub.status.idle":"2024-10-05T12:15:16.217381Z","shell.execute_reply.started":"2024-10-05T12:15:16.212886Z","shell.execute_reply":"2024-10-05T12:15:16.216410Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Prepare Dataset","metadata":{}},{"cell_type":"code","source":"class LumberSpineTrainDataset(Dataset):\n    def __init__(self, \n                 df , # dataframe for dataset\n                 desc, # data desciption \n                 transform , # transform function \n                 train : bool=True):\n        self.df = df\n        self.transform = transform\n        self.desc = desc\n        self.train = train # indicate it is a training dataset, with labels\n        \n    def __len__(self):\n        return(len(self.df))\n    \n    def getImgPath(self, Id, des):\n#         print(f\"Study ID: {Id}, Series Description: {des}\") # for debug\n        tempImgPD = self.desc[(self.desc['study_id'] == Id) & \n                         (self.desc[\"series_description\"] == des)]\n#         print(\"Temp Img List :\", tempImgList)\n        imageList = []\n        for i , row in tempImgPD.iterrows(): \n            if self.train:\n                imagePath = f\"\"\"{CFG.trainImagesDir}/{Id}/{row[\"series_id\"]}/*.dcm\"\"\"\n            else: # test\n                imagePath = f\"\"\"{CFG.testImagesDir}/{Id}/{row[\"series_id\"]}/*.dcm\"\"\"\n            imageFileList =glob.glob(imagePath) # find image file in Path\n            sortedImgFileList = sorted(imageFileList)\n            imageList.extend(sortedImgFileList)\n#             print(\"Num of files : \", len(sortedImgFileList))\n        \n        return imageList\n            \n            \n    def getImgArr(self, path):\n        dicomData = pydicom.dcmread(path)\n        img = dicomData.pixel_array # get image array\n        if img.dtype != np.uint8:\n            img = cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)\n        else:\n            #Image Intensity Normalization\n            img = (img - img.min()) / (img.max() - img.min() + 1e-6) * 255\n        # resize image\n        img = cv2.resize(img, (CFG.IMGSIZE, CFG.IMGSIZE),interpolation=cv2.INTER_CUBIC)\n        return img \n        \n        \n    def __getitem__(self, item):\n        x= np.zeros((CFG.IMGSIZE, CFG.IMGSIZE, CFG.inChannel), dtype=np.uint8) # \n        rowdata = self.df.iloc[item]\n        tempStudyId = rowdata['study_id'] # get study id        \n        if self.train:\n            labels = rowdata[1:].values.astype(np.int64) # get labels \n        \n        \n        # Get Sagittal T1 series\n        allImageListST1 = self.getImgPath(tempStudyId, 'Sagittal T1')\n        if len(allImageListST1) == 0:\n            print(f\"{tempStudyId} : Sagittal T1, has no images\")\n        else:\n            # draw 10 sample image for series\n#             print(f\"Lenght of files list: {len(allImageListST1)}\") # for debug\n            step = len(allImageListST1) / 10.0 # each sample step size\n            start = len(allImageListST1) / 2.0 - 4.0 * step # \n            end = len(allImageListST1) + 0.0001\n            tempRange = np.arange(start, end , step)\n            for j, i in enumerate(tempRange):\n                try:\n                    ind2 = max(0, int((i-0.5001).round())) # calculate actual index\n#                     print(f\"Index : {ind2}\")\n                    path = allImageListST1[ind2]\n#                     print(\"Image path: \", path) # for debut\n                    img = self.getImgArr(path)# get image\n#                     print(\"Image shape: \", img.shape) # expect (512, 512) gray image\n                    if self.transform: \n                        img = self.transform(img)\n                        img = img.cpu().detach().numpy() # covert back to numpy\n                    x[..., j] = img.astype(np.uint8) # write image into channel\n                except Exception as error:\n                    print(f\"failed to load on {tempStudyId}, Sagittal T1, Error: {error}\")\n                    \n        # get Sagittal T2/STIR\n        allImageListST2 = self.getImgPath(tempStudyId, 'Sagittal T2/STIR')\n        if len(allImageListST2) == 0:\n            print(f\"{tempStudyId} : Sagittal T2/STIR, has no images\")\n        else:\n            # draw 10 sample image for series\n#             print(f\"Lenght of files list: {len(allImageListST2)}\") # for debug\n            step = len(allImageListST2) / 10.0 # each sample step size\n            start = len(allImageListST2) / 2.0 - 4.0 * step # \n            end = len(allImageListST2) + 0.0001\n            tempRange = np.arange(start, end , step)\n            for j, i in enumerate(tempRange):\n                try:\n                    ind2 = max(0, int((i-0.5001).round())) # calculate actual index\n#                     print(f\"Index : {ind2}\")\n                    path = allImageListST2[ind2]\n#                     print(\"Image path: \", path) # for debut\n                    img = self.getImgArr(path)# get image\n#                     print(\"Image shape: \", img.shape) # expect (512, 512) gray image\n                    if self.transform: \n                        img = self.transform(img) # transform\n                        img = img.cpu().detach().numpy() # covert back to numpy\n                    x[..., j+10] = img.astype(np.uint8) # write image into channel\n                except Exception as error:\n                    print(f\"failed to load on {tempStudyId}, Sagittal T2/STIR, Error: {error}\")\n        \n        # get Axial T2\n        allImageListAT2 = self.getImgPath(tempStudyId, \"Axial T2\")\n        if len(allImageListAT2) == 0:\n            print(f\"{tempStudyId} : Axial T2, has no images\")\n        else:\n            # draw 10 sample image for series\n#             print(f\"Lenght of files list: {len(allImageListAT2)}\") for debug\n            step = len(allImageListAT2) / 10.0 # each sample step size\n            start = len(allImageListAT2) / 2.0 - 4.0 * step # \n            end = len(allImageListAT2) + 0.0001\n            tempRange = np.arange(start, end , step)\n            for j, i in enumerate(tempRange):\n                try:\n                    ind2 = max(0, int((i-0.5001).round())) # calculate actual index\n#                     print(f\"Index : {ind2}\")\n                    path = allImageListAT2[ind2]\n#                     print(\"Image path: \", path) # for debut\n                    img = self.getImgArr(path)# get image\n#                     print(\"Image shape: \", img.shape) # expect (512, 512) gray image\n                    if self.transform: \n                        img = self.transform(img)\n                        img = img.cpu().detach().numpy() # covert back to numpy\n                    x[..., j+20] = img.astype(np.uint8) # write image into channel\n                except Exception as error:\n                    print(f\"failed to load on {tempStudyId}, Axial T2 , Image Path: {path},  Error: {error}\")\n\n        x = x.transpose(2, 0, 1) # re-order to (channel, H, W)  \n        \n        if self.train:\n            return x, labels\n        else:\n            return x\n    ","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:16.985924Z","iopub.execute_input":"2024-10-05T12:15:16.986292Z","iopub.status.idle":"2024-10-05T12:15:17.014641Z","shell.execute_reply.started":"2024-10-05T12:15:16.986268Z","shell.execute_reply":"2024-10-05T12:15:17.013617Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class LumberSpineTestDataset(Dataset):\n    def __init__(self, \n                 desc, # data desciption,\n                 transform): # transform function \n        self.transform = transform\n        self.desc = desc\n        self.studyId = list(desc['study_id'].unique())\n        \n    def __len__(self):\n        return(len(self.studyId))\n    \n    def getImgPath(self, Id, des):\n        tempImgPD = self.desc[(self.desc['study_id'] == Id) & \n                         (self.desc[\"series_description\"] == des)]\n        imageList = []\n        for i , row in tempImgPD.iterrows(): # test\n            imagePath = f\"\"\"{CFG.testImagesDir}/{Id}/{row[\"series_id\"]}/*.dcm\"\"\"\n            imageFileList =glob.glob(imagePath) # find image file in Path\n            sortedImgFileList = sorted(imageFileList)\n            imageList.extend(sortedImgFileList)\n            \n        return imageList\n\n    def getImgArr(self, path):\n        dicomData = pydicom.dcmread(path)\n        img = dicomData.pixel_array # get image array\n        if img.dtype != np.uint8:\n            img = cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)\n        else:\n            #Image Intensity Normalization\n            img = (img - img.min()) / (img.max() - img.min() + 1e-6) * 255\n        # resize image\n        img = cv2.resize(img, (CFG.IMGSIZE, CFG.IMGSIZE),interpolation=cv2.INTER_CUBIC)\n        return img \n    \n    \n    def __getitem__(self, item):\n        x= np.zeros((CFG.IMGSIZE, CFG.IMGSIZE, CFG.inChannel), dtype=np.uint8) # \n        tempStudyId = self.studyId[item]  # get study id        \n        \n        # Get Sagittal T1 series\n        allImageListST1 = self.getImgPath(tempStudyId, 'Sagittal T1')\n        if len(allImageListST1) == 0:\n            print(f\"{tempStudyId} : Sagittal T1, has no images\")\n        else:\n            # draw 10 sample image for series\n#             print(f\"Lenght of files list: {len(allImageListST1)}\") # for debug\n            step = len(allImageListST1) / 10.0 # each sample step size\n            start = len(allImageListST1) / 2.0 - 4.0 * step # \n            end = len(allImageListST1) + 0.0001\n            tempRange = np.arange(start, end , step)\n            for j, i in enumerate(tempRange):\n                try:\n                    ind2 = max(0, int((i-0.5001).round())) # calculate actual index\n#                     print(f\"Index : {ind2}\")\n                    path = allImageListST1[ind2]\n#                     print(\"Image path: \", path) # for debut\n                    img = self.getImgArr(path)# get image\n#                     print(\"Image shape: \", img.shape) # expect (512, 512) gray image\n                    if self.transform: \n                        img = self.transform(img)\n                        img = img.cpu().detach().numpy() # covert back to numpy\n                    x[..., j] = img.astype(np.uint8) # write image into channel\n                except Exception as error:\n                    print(f\"failed to load on {tempStudyId}, Sagittal T1, Error: {error}\")\n                    \n        # get Sagittal T2/STIR\n        allImageListST2 = self.getImgPath(tempStudyId, 'Sagittal T2/STIR')\n        if len(allImageListST2) == 0:\n            print(f\"{tempStudyId} : Sagittal T2/STIR, has no images\")\n        else:\n            # draw 10 sample image for series\n#             print(f\"Lenght of files list: {len(allImageListST2)}\") # for debug\n            step = len(allImageListST2) / 10.0 # each sample step size\n            start = len(allImageListST2) / 2.0 - 4.0 * step # \n            end = len(allImageListST2) + 0.0001\n            tempRange = np.arange(start, end , step)\n            for j, i in enumerate(tempRange):\n                try:\n                    ind2 = max(0, int((i-0.5001).round())) # calculate actual index\n#                     print(f\"Index : {ind2}\")\n                    path = allImageListST2[ind2]\n#                     print(\"Image path: \", path) # for debut\n                    img = self.getImgArr(path)# get image\n#                     print(\"Image shape: \", img.shape) # expect (512, 512) gray image\n                    if self.transform: \n                        img = self.transform(img) # transform\n                        img = img.cpu().detach().numpy() # covert back to numpy\n                    x[..., j+10] = img.astype(np.uint8) # write image into channel\n                except Exception as error:\n                    print(f\"failed to load on {tempStudyId}, Sagittal T2/STIR, Error: {error}\")\n        \n        # get Axial T2\n        allImageListAT2 = self.getImgPath(tempStudyId, \"Axial T2\")\n        if len(allImageListAT2) == 0:\n            print(f\"{tempStudyId} : Axial T2, has no images\")\n        else:\n            # draw 10 sample image for series\n#             print(f\"Lenght of files list: {len(allImageListAT2)}\") for debug\n            step = len(allImageListAT2) / 10.0 # each sample step size\n            start = len(allImageListAT2) / 2.0 - 4.0 * step # \n            end = len(allImageListAT2) + 0.0001\n            tempRange = np.arange(start, end , step)\n            for j, i in enumerate(tempRange):\n                try:\n                    ind2 = max(0, int((i-0.5001).round())) # calculate actual index\n#                     print(f\"Index : {ind2}\")\n                    path = allImageListAT2[ind2]\n#                     print(\"Image path: \", path) # for debut\n                    img = self.getImgArr(path)# get image\n#                     print(\"Image shape: \", img.shape) # expect (512, 512) gray image\n                    if self.transform: \n                        img = self.transform(img)\n                        img = img.cpu().detach().numpy() # covert back to numpy\n                    x[..., j+20] = img.astype(np.uint8) # write image into channel\n                except Exception as error:\n                    print(f\"failed to load on {tempStudyId}, Axial T2 , Image Path: {path},  Error: {error}\")\n\n        x = x.transpose(2, 0, 1) # re-order to (channel, H, W)  \n        \n        return x , str(tempStudyId) # return image data and study id \n    \n    ","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:17.562531Z","iopub.execute_input":"2024-10-05T12:15:17.562876Z","iopub.status.idle":"2024-10-05T12:15:17.589575Z","shell.execute_reply.started":"2024-10-05T12:15:17.562850Z","shell.execute_reply":"2024-10-05T12:15:17.588605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainDataset = LumberSpineTrainDataset(train,\n                                  trainDescript,\n                                  trainTransformFuct, \n                                  train=True)\nvalDataset = LumberSpineTrainDataset(val,\n                                trainDescript, \n                                trainTransformFuct, \n                                train=True)\n\ntestDataset = LumberSpineTestDataset(testDescript, \n                                     testTransformFuct)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:18.408466Z","iopub.execute_input":"2024-10-05T12:15:18.408874Z","iopub.status.idle":"2024-10-05T12:15:18.415112Z","shell.execute_reply.started":"2024-10-05T12:15:18.408842Z","shell.execute_reply":"2024-10-05T12:15:18.413888Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainDataLoader= torch.utils.data.DataLoader(\n                            trainDataset, \n                            batch_size=CFG.BATCH_SIZE,\n                            shuffle=True,\n                            pin_memory=True,\n                            num_workers=CFG.N_WORKERS)\n\nvalDataLoader = torch.utils.data.DataLoader(\n                            valDataset,\n                            batch_size=CFG.BATCH_SIZE,\n                            shuffle=False,\n                            pin_memory=True,\n                            num_workers=CFG.N_WORKERS)\n\ntestDataLoader = torch.utils.data.DataLoader(\n                            testDataset,\n                            batch_size=1,\n                            shuffle=False,\n                            num_workers=CFG.N_WORKERS,\n                            pin_memory=True,\n                            drop_last=False)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:19.380366Z","iopub.execute_input":"2024-10-05T12:15:19.380787Z","iopub.status.idle":"2024-10-05T12:15:19.388105Z","shell.execute_reply.started":"2024-10-05T12:15:19.380744Z","shell.execute_reply":"2024-10-05T12:15:19.387200Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# trainDataLoader","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:20.182989Z","iopub.execute_input":"2024-10-05T12:15:20.183623Z","iopub.status.idle":"2024-10-05T12:15:20.188178Z","shell.execute_reply.started":"2024-10-05T12:15:20.183592Z","shell.execute_reply":"2024-10-05T12:15:20.187066Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Test reading Training data Loader","metadata":{}},{"cell_type":"code","source":"# cnt =0 \n# for x, y in trainDataLoader:\n#     try:\n#         print(f\"Shape of X : {x.shape}\")\n#         print(f\"Shape of y: {y.shape} {y.dtype}\")\n#         print(x[0].shape)\n#         cnt +=1\n#         if cnt: \n#             break\n#     except:\n#         print(\"Error reading trainDataLoader\")\n#         break","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2024-10-05T12:15:21.667814Z","iopub.execute_input":"2024-10-05T12:15:21.668202Z","iopub.status.idle":"2024-10-05T12:15:21.673240Z","shell.execute_reply.started":"2024-10-05T12:15:21.668171Z","shell.execute_reply":"2024-10-05T12:15:21.672035Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(trainDataLoader)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:22.583384Z","iopub.execute_input":"2024-10-05T12:15:22.583831Z","iopub.status.idle":"2024-10-05T12:15:22.590776Z","shell.execute_reply.started":"2024-10-05T12:15:22.583797Z","shell.execute_reply":"2024-10-05T12:15:22.589462Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Test Validate dataset","metadata":{}},{"cell_type":"code","source":"# cnt =0 \n# for x, y in valDataLoader:\n#     try:\n#         print(f\"Shape of X : {x.shape}\")\n#         print(f\"Shape of y: {y.shape} {y.dtype}\")\n#         print(x[0].shape)\n#         cnt +=1\n#         if cnt: \n#             break\n#     except:\n#         print(\"Error reading valDataLoader\")\n#         break","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2024-10-05T12:15:23.671930Z","iopub.execute_input":"2024-10-05T12:15:23.672339Z","iopub.status.idle":"2024-10-05T12:15:23.677072Z","shell.execute_reply.started":"2024-10-05T12:15:23.672309Z","shell.execute_reply":"2024-10-05T12:15:23.676020Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(valDataLoader)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:24.184303Z","iopub.execute_input":"2024-10-05T12:15:24.185042Z","iopub.status.idle":"2024-10-05T12:15:24.191049Z","shell.execute_reply.started":"2024-10-05T12:15:24.185007Z","shell.execute_reply":"2024-10-05T12:15:24.190004Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cnt =0 \nfor x, idx in testDataLoader:\n    try:\n        print(f\"Shape of X : {x.shape}\")\n        print(x[0].shape)\n        print(\"id : \", idx)\n        cnt +=1\n        if cnt: \n            break\n    except:\n        print(\"Error reading valDataLoader\")\n        break","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:24.834853Z","iopub.execute_input":"2024-10-05T12:15:24.835194Z","iopub.status.idle":"2024-10-05T12:15:26.520254Z","shell.execute_reply.started":"2024-10-05T12:15:24.835168Z","shell.execute_reply":"2024-10-05T12:15:26.519076Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(testDataLoader)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:26.522530Z","iopub.execute_input":"2024-10-05T12:15:26.523852Z","iopub.status.idle":"2024-10-05T12:15:26.534807Z","shell.execute_reply.started":"2024-10-05T12:15:26.523801Z","shell.execute_reply":"2024-10-05T12:15:26.533653Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Define Model","metadata":{"execution":{"iopub.status.busy":"2024-09-11T10:16:14.573471Z","iopub.execute_input":"2024-09-11T10:16:14.573896Z","iopub.status.idle":"2024-09-11T10:16:14.579931Z","shell.execute_reply.started":"2024-09-11T10:16:14.573859Z","shell.execute_reply":"2024-09-11T10:16:14.578761Z"}}},{"cell_type":"code","source":"class EfficientModel(nn.Module):\n    def __init__(self, modelName, inCh=30, nClasses=75, pretrained= False, dropOut=0.0):\n        super(EfficientModel, self).__init__()\n        self.backbone = timm.create_model(model_name=modelName, \n                                          pretrained=pretrained,\n                                          in_chans=inCh,\n                                          num_classes=nClasses,\n                                          global_pool=\"avg\")\n        self.numFeatureL1 = self.backbone.classifier.in_features  # Grab the number of input features to the classifier\n        self.numFeatureL2 = self.numFeatureL1 //2\n        \n        # overwrite classifier \n#         self.backbone.classifier = nn.Sequential(\n#                     nn.Linear(self.numFeatureL1, self.numFeatureL2),\n#                     nn.ReLU(),\n#                     nn.Dropout(dropOut),\n#                     nn.Linear(self.numFeatureL2, nClasses),\n#         )\n    \n    def forward(self, x):\n#         print(f\"Input x shape : {x.shape}\") # for debug expect (16, 30, 312, 312)\n        out = self.backbone(x)\n        return out","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:26.658251Z","iopub.execute_input":"2024-10-05T12:15:26.658843Z","iopub.status.idle":"2024-10-05T12:15:26.672116Z","shell.execute_reply.started":"2024-10-05T12:15:26.658700Z","shell.execute_reply":"2024-10-05T12:15:26.671103Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:27.266915Z","iopub.execute_input":"2024-10-05T12:15:27.267627Z","iopub.status.idle":"2024-10-05T12:15:27.274283Z","shell.execute_reply.started":"2024-10-05T12:15:27.267592Z","shell.execute_reply":"2024-10-05T12:15:27.273171Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if CFG.USE_EFFNETV1:\n    effmodelV1 = EfficientModel(modelName=CFG.modelName1, inCh=CFG.inChannel, nClasses=CFG.nClasses)\n    effmodelV1.to(device)\n    optimizer1 = torch.optim.AdamW(effmodelV1.parameters(), lr=2e-4, weight_decay=1e-2)\n    effmodelV1\n","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2024-10-05T12:15:27.866735Z","iopub.execute_input":"2024-10-05T12:15:27.867707Z","iopub.status.idle":"2024-10-05T12:15:27.875296Z","shell.execute_reply.started":"2024-10-05T12:15:27.867671Z","shell.execute_reply":"2024-10-05T12:15:27.874302Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if CFG.USE_EFFNETV2:\n    effmodelV2= EfficientModel(modelName=CFG.modelName2,  inCh=CFG.inChannel, nClasses =CFG.nClasses)\n    effmodelV2.to(device)\n    optimizer2 = torch.optim.AdamW(effmodelV2.parameters(), lr=2e-4,weight_decay=1e-2)\n    effmodelV2\n    ","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:28.853623Z","iopub.execute_input":"2024-10-05T12:15:28.854531Z","iopub.status.idle":"2024-10-05T12:15:29.110095Z","shell.execute_reply.started":"2024-10-05T12:15:28.854494Z","shell.execute_reply":"2024-10-05T12:15:29.108999Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"classWeight = torch.tensor([1.0, 2.0, 4.0])\nclassWeight1 = torch.tensor([classWeg0, classWeg1, classWeg2], dtype=torch.float)\n# lossFn = nn.CrossEntropyLoss(weight=classWeight.to(device))\nlossFn = nn.CrossEntropyLoss()\nlossFn2 = nn.CrossEntropyLoss(weight=classWeight1.to(device))","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:29.379560Z","iopub.execute_input":"2024-10-05T12:15:29.379975Z","iopub.status.idle":"2024-10-05T12:15:29.386070Z","shell.execute_reply.started":"2024-10-05T12:15:29.379942Z","shell.execute_reply":"2024-10-05T12:15:29.385084Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Use AMP training Method pytorch when USE GPU","metadata":{}},{"cell_type":"code","source":"if device.type == \"cuda\":\n    # autocast = torch.cuda.amp.autocast(enabled=USE_AMP, dtype=torch.bfloat16) # if your gpu is newer Ampere, you can use this, lesser appearance of nan than half\n    autocast = torch.cuda.amp.autocast(enabled=CFG.USE_AMP, dtype=torch.half) # you can use with T4 gpu. or newer\n    scaler = torch.cuda.amp.GradScaler(enabled=CFG.USE_AMP, init_scale=4096)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:31.870308Z","iopub.execute_input":"2024-10-05T12:15:31.870753Z","iopub.status.idle":"2024-10-05T12:15:31.876263Z","shell.execute_reply.started":"2024-10-05T12:15:31.870698Z","shell.execute_reply":"2024-10-05T12:15:31.875233Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Define Train Function ","metadata":{}},{"cell_type":"code","source":"# plot  Loss \ndef plotLoss(epochList, trainLoss, valLoss, modelName):\n    plt.figure(figsize=(6, 4))\n    plt.plot(epochList, trainLoss, label='Training  loss')\n    plt.plot(epochList, valLoss, label='Validation loss')\n    plt.title(f'{modelName} loss (Training/Validation)')\n    plt.xlabel('Epochs')\n    plt.ylabel('Loss')\n    plt.legend()\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:33.190650Z","iopub.execute_input":"2024-10-05T12:15:33.191072Z","iopub.status.idle":"2024-10-05T12:15:33.197569Z","shell.execute_reply.started":"2024-10-05T12:15:33.191043Z","shell.execute_reply":"2024-10-05T12:15:33.196552Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plotAcc(epochList, trainAcc, valAcc, modelName):\n    plt.figure(figsize=(6, 4))\n    plt.plot(epochList, trainAcc, label='Training Acc')\n    plt.plot(epochList, valAcc, label='Validation Acc')\n    plt.title(f'{modelName} Accaury (Training/Validation)')\n    plt.xlabel('Epochs')\n    plt.ylabel('Accaury')\n    plt.legend()\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:33.775058Z","iopub.execute_input":"2024-10-05T12:15:33.775434Z","iopub.status.idle":"2024-10-05T12:15:33.783013Z","shell.execute_reply.started":"2024-10-05T12:15:33.775406Z","shell.execute_reply":"2024-10-05T12:15:33.781796Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def trainFunc(model, loader, optimizer, lossFn):\n    \"\"\"one epoch train \"\"\"\n    model.train()\n    size = len(loader)\n    avgLoss = 0.0\n    losses = []\n    correct =0\n    total = 0 \n    \n    for i, (x, y) in enumerate(tqdm(loader)):\n        x = x.to(device).float() \n        y=  y.to(device)# .float() #.view(-1, 1).float()\n#         print(f\"y shape: {y.shape}\") # for debug expect  (16, 25), \n        loss =0 \n        yhat = model(x)\n#         print(f\"yhat shape: {yhat.shape}\") # for debug expect (16, 75)\n        \n        for col in range(CFG.nLABELS):\n            pred = yhat[:, col*3 : col*3+3] # generate 3 label predict\n            gy = y[:, col]\n#             print(\"pred shape\", pred.shape) # for debug expect (16, 3)\n#             print(\"gt shape\", gy.shape) # for debug expect (16)\n            loss = loss + lossFn(pred, gy) / CFG.nLABELS\n            \n            # find predict \n            predClass = torch.argmax(pred, dim=1 )# find maximum value (classes) in column\n#             print(f\"pred Class: {predClass}\")  # for debug\n            # calulate correct \n            corr =  (predClass == gy).sum().item()  # Count correct predictions\n            correct += corr\n#             print(\"Correct : \", corr)\n#             print(\"target size: \", gy.size(0))  # Total number of samples)\n            total += gy.size(0)\n            \n        \n        losses.append(loss.item())        \n        \n        # reset previous gradient \n        optimizer.zero_grad()\n        if device.type == \"cuda\":\n            scaler.scale(loss).backward() # claute gradient\n            scaler.step(optimizer) # update weight\n            scaler.update() # update scaler \n        else:\n            loss.backward()  #caluate gradient \n            optimizer.step() # update weight \n        \n        if i % 50 ==49: #each 10 mini-batches print the loss\n            tempLoss = np.mean(losses)\n            print(f\"Batch {i+1},  Training Loss : {tempLoss}\")\n#             print(\"Total Correct: \", correct)\n            tempAcc = 100 * correct/(total)\n            print(f\"Batch {i+1}, Training Acc : {tempAcc} %\")\n\n    avgLoss = np.mean(losses)  #average losses\n    print(f\"Training Loss: {avgLoss} \")\n    finalAcc = 100 * correct/total\n    print(f\"Training Accuray: {finalAcc} %\")\n    return avgLoss , finalAcc\n        \n    ","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:34.254767Z","iopub.execute_input":"2024-10-05T12:15:34.255138Z","iopub.status.idle":"2024-10-05T12:15:34.267748Z","shell.execute_reply.started":"2024-10-05T12:15:34.255109Z","shell.execute_reply":"2024-10-05T12:15:34.266701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def valiationFunc(model, loader, lossFn):\n    model.eval()\n    total_loss = 0\n    correct = 0\n    losses = []\n    y_preds = []\n    labels = []\n    correct =0\n    total = 0 \n    # not calulate gradient\n    with torch.no_grad():\n        for i, (x, y) in enumerate(tqdm(loader)): # get dataset \n            x = x.to(device).float() \n            y=  y.to(device)#.view(-1, 1).float()\n#             print(f\"y shape: {y.shape}\") # for debug expect (16, 25)\n            \n            loss =0 \n            # predict \n            yhat = model(x)\n            for col in range(CFG.nLABELS):\n                pred = yhat[:, col *3 : col*3 + 3] # get every 3 column for prediction \n                gt = y[:, col] \n#                 print(\"pred shape\", pred.shape)  # for debug expect (16, 3)\n#                 print(\"gt shape\", gt.shape) # for debug expect (16)\n                loss = loss + lossFn(pred, gt) / CFG.nLABELS\n#                 correct +=  (pred ==gt).sum()\n                y_pred = pred.float()\n#                 y_preds.append(y_pred.cpu())\n                labels.extend(gt.cpu().numpy().astype(int))\n            \n                # find predict class\n                predClass = torch.argmax(pred, dim=1 )# find maximum value (classes) in column\n                y_preds.extend(predClass.cpu().numpy().astype(int))\n#                 print(f\"pred Class: {predClass}\")  # for debug\n                # calulate correct \n                corr =  (predClass == gt).sum().item()  # Count correct predictions\n                correct += corr\n#                 print(\"Correct : \", corr)\n#                 print(\"target size: \", gt.size(0))  # Total number of samples)\n                total += gt.size(0)\n            \n            losses.append(loss.item())        \n            if i % 50 ==49: #each 10 mini-batches print the loss\n                tempLoss = np.mean(losses)\n                print(f\"Batch {i+1},  Val Loss : {tempLoss}\")\n                tempAcc = 100 * correct/(total)\n                print(f\"Batch {i+1}, Val Acc : {tempAcc} %\")\n\n\n        avgLoss = np.mean(losses)  #average losses\n        print(f\"Val Loss: {avgLoss} \")\n        \n        valAcc =  100* correct/ total \n        print(f\"Val Acc: {valAcc} %\")          \n\n    return y_preds, labels, avgLoss , valAcc\n                \n                \n        ","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:34.757305Z","iopub.execute_input":"2024-10-05T12:15:34.757737Z","iopub.status.idle":"2024-10-05T12:15:34.769969Z","shell.execute_reply.started":"2024-10-05T12:15:34.757686Z","shell.execute_reply":"2024-10-05T12:15:34.768869Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainLossHist = []\ntrainAccHist = []\nvalLossHist =[]\nvalAccHist = []\nepochList = []\nmodelHistory= {}\n\ndef clearTrainHist():\n    global trainLossHist,  trainAccHist, valLossHist,  valAccHist, \\\n            epochList\n    \n    trainLossHist.clear()\n    trainAccHist.clear()\n    valLossHist.clear()\n    valAccHist.clear()\n    epochList.clear()\n\n","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:35.670335Z","iopub.execute_input":"2024-10-05T12:15:35.671436Z","iopub.status.idle":"2024-10-05T12:15:35.677642Z","shell.execute_reply.started":"2024-10-05T12:15:35.671390Z","shell.execute_reply":"2024-10-05T12:15:35.676777Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def trainLoop(model, optimizer, modelName, epoches= 50):\n    global trainLossHist, trainAccHist, \\\n            valLossHist, valAccHist, epochList, modelHistory, lossFn, lossFn2\n    \n    #Initialize Variables for EarlyStopping\n    best_model_weights = None   # update/store best model weight \n    patience = 8 #5#20#15\n    bestScore= 0 # use pAUP\n    bestAcc =0\n    bestLoss = np.inf   # init to infinity\n    for i in range(epoches):\n        print(f\"Epochs: {i+1}\")\n        print(\"Training:\")\n        trainLoss, trainAcc = trainFunc(model, trainDataLoader, optimizer, lossFn2)\n        trainLossHist.append(trainLoss)\n        trainAccHist.append(trainAcc)\n        print(\"Validation:\")\n        preds, labels, valLoss, valAcc = valiationFunc(model, valDataLoader, lossFn2)\n        valLossHist.append(valLoss)\n        valAccHist.append(valAcc)\n        epochList.append(i+1)\n        \n        # update best accuary\n        if valAcc > bestAcc:\n            bestAcc = valAcc\n        \n        # update bestloss, best accuracy , best score \n        if valLoss < bestLoss:\n            bestLoss = valLoss\n            best_model_weights = copy.deepcopy(model.state_dict()) #  copyu the best model\n            patience  =  8 #5 #20# 15  # reset counter\n            torch.save({\"model\": model.state_dict(),\n                         'predictions': preds\n                       }, (modelName + \".pt\"))\n        else:\n            patience -= 1\n            if patience == 0:\n                print(\"Early Stop!\")\n                break\n        \n        if i % 3 == 2:\n            # calucate classification matrics , report\n            cm = confusion_matrix(labels, preds)\n            print(f\"\\n\\rClassification Report For {modelName} :\\n\\r\", classification_report(labels, preds))\n            #         cmd =ConfusionMatrixDisplay(cm, display_labels=[False, True])\n            cmd =ConfusionMatrixDisplay(cm)\n            cmd.plot()\n            plt.title(f\"Confusion Matrix for {modelName}\")\n            plt.show()\n        \n                \n    gc.collect()\n    \n    # Load the best model weights\n    model.load_state_dict(best_model_weights)\n    \n    # store model train record in dictionary \n    modelHistory[modelName] = {\n        \"train_loss\": trainLossHist,\n        \"train_acc\": trainAccHist,\n        \"val_loss\": valLossHist,\n        \"val_acc\": valAccHist,\n        'epoch_list': epochList,\n        \"best_loss\": bestLoss,\n        \"best_acc\": bestAcc\n    }\n            \n        ","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:36.359218Z","iopub.execute_input":"2024-10-05T12:15:36.359627Z","iopub.status.idle":"2024-10-05T12:15:36.375188Z","shell.execute_reply.started":"2024-10-05T12:15:36.359596Z","shell.execute_reply":"2024-10-05T12:15:36.374114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"clearMemory()\nclearTrainHist()","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:37.075845Z","iopub.execute_input":"2024-10-05T12:15:37.076629Z","iopub.status.idle":"2024-10-05T12:15:39.548611Z","shell.execute_reply.started":"2024-10-05T12:15:37.076593Z","shell.execute_reply":"2024-10-05T12:15:39.547526Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nif CFG.USE_EFFNETV1:\n    trainLoop(effmodelV1, optimizer1,\"efficientNet1\" , 50)","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2024-10-05T12:15:39.550750Z","iopub.execute_input":"2024-10-05T12:15:39.551620Z","iopub.status.idle":"2024-10-05T12:15:39.557685Z","shell.execute_reply.started":"2024-10-05T12:15:39.551582Z","shell.execute_reply":"2024-10-05T12:15:39.556643Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if CFG.USE_EFFNETV1:\n    plotLoss(epochList,  trainLossHist, valLossHist ,\"efficientNet1\")","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:39.559012Z","iopub.execute_input":"2024-10-05T12:15:39.559377Z","iopub.status.idle":"2024-10-05T12:15:39.568604Z","shell.execute_reply.started":"2024-10-05T12:15:39.559343Z","shell.execute_reply":"2024-10-05T12:15:39.567872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if CFG.USE_EFFNETV1:\n    plotAcc(epochList, trainAccHist, valAccHist, \"efficientNet1\")","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:40.542858Z","iopub.execute_input":"2024-10-05T12:15:40.543241Z","iopub.status.idle":"2024-10-05T12:15:40.548146Z","shell.execute_reply.started":"2024-10-05T12:15:40.543210Z","shell.execute_reply":"2024-10-05T12:15:40.547079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"clearMemory()\nclearTrainHist()\n","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:41.249089Z","iopub.execute_input":"2024-10-05T12:15:41.249756Z","iopub.status.idle":"2024-10-05T12:15:43.661647Z","shell.execute_reply.started":"2024-10-05T12:15:41.249721Z","shell.execute_reply":"2024-10-05T12:15:43.660682Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if CFG.USE_EFFNETV2:\n    trainLoop(effmodelV2, optimizer2, \"efficientNet2\" , 50)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T12:15:43.663548Z","iopub.execute_input":"2024-10-05T12:15:43.663854Z"},"scrolled":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if CFG.USE_EFFNETV2:\n    plotLoss(epochList,  trainLossHist, valLossHist ,\"efficientNet2\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if CFG.USE_EFFNETV2:\n    plotAcc(epochList, trainAccHist, valAccHist, \"efficientNet2\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Inference Predict Test dataset","metadata":{}},{"cell_type":"code","source":"def InferFunc(model, loader):\n    model.eval()\n    y_preds = []\n    labels = []\n    rowNames = []\n    \n    # not calulate gradient\n    with torch.no_grad():\n        for i, (x, idx) in enumerate(tqdm(loader)): # get dataset \n            x = x.to(device).float()\n            predPerStudy = np.zeros((25, 3)) #initial zero output \n            \n            # generate all condition and level\n            for cond in CONDITIONS:\n                for level in LEVELS:\n                    rowNames.append(idx[0] + '_' + cond + '_' + level)\n            \n            # predict \n            yhat = model(x)[0]\n            for col in range(CFG.nLABELS):\n                pred = yhat[col *3 : col*3 + 3] # get every 3 column for prediction \n                \n                y_pred = pred.float().softmax(0).cpu().numpy() # softmax\n                predPerStudy[col] += y_pred\n                \n            y_preds.append(predPerStudy)\n            \n    return y_preds, rowNames","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Final Model","metadata":{}},{"cell_type":"code","source":"if CFG.USE_EFFNETV1:\n    finalModel = effmodelV1\n\nelif CFG.USE_EFFNETV2:\n    finalModel = effmodelV2\n    \nelse: \n    finalModel = effmodelV1","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"yPreds, rowNames = InferFunc(finalModel, testDataLoader)\nfinalPreds = np.concatenate(yPreds, axis=0)\nfinalPreds","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"finalLabel = list(submit.columns[1:])\nfinalLabel","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Generate Predict submit result","metadata":{}},{"cell_type":"code","source":"sub= pd.DataFrame()\nsub[\"row_id\"] = rowNames\nsub[finalLabel] = finalPreds # add predict result for each \nsub.head(25)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub.shape","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub.to_csv('submission.csv', index=False)\npd.read_csv('submission.csv')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}