{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","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,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":273303,"sourceType":"modelInstanceVersion","isSourceIdPinned":false,"modelInstanceId":233998,"modelId":255700},{"sourceId":273562,"sourceType":"modelInstanceVersion","isSourceIdPinned":false,"modelInstanceId":234232,"modelId":255934},{"sourceId":280717,"sourceType":"modelInstanceVersion","isSourceIdPinned":false,"modelInstanceId":240510,"modelId":262156},{"sourceId":285112,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":244341,"modelId":265958}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport os\nimport numpy as np\nfrom sklearn.model_selection import train_test_split\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom sklearn.preprocessing import OneHotEncoder\nimport pydicom\nfrom PIL import Image\nimport tensorflow as tf","metadata":{"_uuid":"f52963e8-2f6e-41f5-a11a-5bb0f3d7c7bc","_cell_guid":"56823815-719a-4e01-95d7-e174028b646e","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:36.743873Z","iopub.execute_input":"2025-03-13T14:04:36.744187Z","iopub.status.idle":"2025-03-13T14:04:50.273096Z","shell.execute_reply.started":"2025-03-13T14:04:36.744158Z","shell.execute_reply":"2025-03-13T14:04:50.272381Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"traing_df = pd.read_csv('/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train.csv')","metadata":{"_uuid":"a0589637-d583-478a-8537-2a73fd8ce6f0","_cell_guid":"c8033e8d-6646-4809-b04a-f711e7f4ef77","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.274044Z","iopub.execute_input":"2025-03-13T14:04:50.274534Z","iopub.status.idle":"2025-03-13T14:04:50.304165Z","shell.execute_reply.started":"2025-03-13T14:04:50.274497Z","shell.execute_reply":"2025-03-13T14:04:50.303350Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"traing_df.head()","metadata":{"_uuid":"357b42cd-b7d4-4aa5-b063-8cc2cafa4cda","_cell_guid":"be6e939d-0d4f-4cdb-b0eb-57b9ea5fefb6","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"_kg_hide-input":true,"execution":{"iopub.status.busy":"2025-03-13T14:04:50.305628Z","iopub.execute_input":"2025-03-13T14:04:50.305903Z","iopub.status.idle":"2025-03-13T14:04:50.342213Z","shell.execute_reply.started":"2025-03-13T14:04:50.305881Z","shell.execute_reply":"2025-03-13T14:04:50.341597Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"traing_df = traing_df.melt(id_vars='study_id')","metadata":{"_uuid":"7a715a17-af13-4680-877c-c9e263f765ec","_cell_guid":"1abb541e-7b4a-4726-9abd-b4df2560f44f","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.343396Z","iopub.execute_input":"2025-03-13T14:04:50.343702Z","iopub.status.idle":"2025-03-13T14:04:50.355214Z","shell.execute_reply.started":"2025-03-13T14:04:50.343681Z","shell.execute_reply":"2025-03-13T14:04:50.354426Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"traing_df.head()","metadata":{"_uuid":"2a730eb2-7883-476b-9b50-bfe535406d1e","_cell_guid":"e3746c59-ddb5-4d55-b2f7-6db7a7ba5b9c","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.355977Z","iopub.execute_input":"2025-03-13T14:04:50.356178Z","iopub.status.idle":"2025-03-13T14:04:50.369244Z","shell.execute_reply.started":"2025-03-13T14:04:50.356161Z","shell.execute_reply":"2025-03-13T14:04:50.368365Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"traing_df[traing_df['study_id']==100206310]","metadata":{"_uuid":"f4e63a00-3f3a-4201-a245-089ba168f1f7","_cell_guid":"640c39db-4b21-4b7f-a4cb-490084177d4b","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.370178Z","iopub.execute_input":"2025-03-13T14:04:50.370517Z","iopub.status.idle":"2025-03-13T14:04:50.385545Z","shell.execute_reply.started":"2025-03-13T14:04:50.370484Z","shell.execute_reply":"2025-03-13T14:04:50.384743Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"label_coords_df = pd.read_csv('/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_label_coordinates.csv')\nseries_desc_df = pd.read_csv('/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_series_descriptions.csv')","metadata":{"_uuid":"ad1c2119-32b5-44c0-b6ae-7a091fe9cf60","_cell_guid":"c921ea84-e969-47d9-90f3-8482c684a437","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.386508Z","iopub.execute_input":"2025-03-13T14:04:50.386769Z","iopub.status.idle":"2025-03-13T14:04:50.507015Z","shell.execute_reply.started":"2025-03-13T14:04:50.386749Z","shell.execute_reply":"2025-03-13T14:04:50.506337Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"label_coords_df[label_coords_df['study_id']==100206310]","metadata":{"_uuid":"a39c291e-fb05-4d6f-8e0d-0733f5432d96","_cell_guid":"226229cf-baf5-4a51-a1ff-cb561fbfebbf","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.509561Z","iopub.execute_input":"2025-03-13T14:04:50.509791Z","iopub.status.idle":"2025-03-13T14:04:50.523394Z","shell.execute_reply.started":"2025-03-13T14:04:50.509771Z","shell.execute_reply":"2025-03-13T14:04:50.522583Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"series_desc_df[series_desc_df['study_id']==100206310]","metadata":{"_uuid":"b0ab4117-c9c4-4230-a13c-65a6ae846a8b","_cell_guid":"e0ff22b7-05b7-42a5-b805-0edfe330711a","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.525151Z","iopub.execute_input":"2025-03-13T14:04:50.525349Z","iopub.status.idle":"2025-03-13T14:04:50.543625Z","shell.execute_reply.started":"2025-03-13T14:04:50.525330Z","shell.execute_reply":"2025-03-13T14:04:50.542737Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"label_coords_df['variable'] = label_coords_df['condition'].str.lower().str.replace(' ','_')+\"_\"+label_coords_df['level'].str.lower().str.replace('/','_')","metadata":{"_uuid":"3f6f6bb4-2819-4442-834b-a70d77722d38","_cell_guid":"b8aa5693-d17f-42b8-8f9d-c00a594432da","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.544452Z","iopub.execute_input":"2025-03-13T14:04:50.544775Z","iopub.status.idle":"2025-03-13T14:04:50.606634Z","shell.execute_reply.started":"2025-03-13T14:04:50.544746Z","shell.execute_reply":"2025-03-13T14:04:50.605937Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"label_coords_df[label_coords_df['study_id']==100206310]","metadata":{"_uuid":"dd82bfec-0981-4319-af2e-e73616316d06","_cell_guid":"80095c9a-3806-441f-9e93-96b19fa0f963","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.607343Z","iopub.execute_input":"2025-03-13T14:04:50.607633Z","iopub.status.idle":"2025-03-13T14:04:50.621201Z","shell.execute_reply.started":"2025-03-13T14:04:50.607611Z","shell.execute_reply":"2025-03-13T14:04:50.620477Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"merged_df = pd.merge(traing_df, label_coords_df, on=['study_id','variable'])","metadata":{"_uuid":"f3a83894-3857-4d40-834c-0b40030cd152","_cell_guid":"fdabbcc3-804b-401f-a3bc-9c045b18ca7d","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.622027Z","iopub.execute_input":"2025-03-13T14:04:50.622314Z","iopub.status.idle":"2025-03-13T14:04:50.669035Z","shell.execute_reply.started":"2025-03-13T14:04:50.622286Z","shell.execute_reply":"2025-03-13T14:04:50.668440Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"merged_df[merged_df['study_id']==100206310]","metadata":{"_uuid":"ffcbd6c5-4fac-44b1-ae7f-25a623289233","_cell_guid":"dc666458-58a1-4959-90cf-56c1889e915a","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.669782Z","iopub.execute_input":"2025-03-13T14:04:50.670073Z","iopub.status.idle":"2025-03-13T14:04:50.684539Z","shell.execute_reply.started":"2025-03-13T14:04:50.670046Z","shell.execute_reply":"2025-03-13T14:04:50.683810Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"merged_df = pd.merge(merged_df, series_desc_df, on=['study_id', 'series_id'])","metadata":{"_uuid":"b9a764b1-7858-4be7-915f-c376dc1afc40","_cell_guid":"6b39af15-686b-4084-b252-3e3508353943","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.685227Z","iopub.execute_input":"2025-03-13T14:04:50.685436Z","iopub.status.idle":"2025-03-13T14:04:50.708640Z","shell.execute_reply.started":"2025-03-13T14:04:50.685401Z","shell.execute_reply":"2025-03-13T14:04:50.707620Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"merged_df[merged_df['study_id']==100206310]","metadata":{"_uuid":"cd2eea41-0499-4354-8996-209dea0a88c4","_cell_guid":"d40da0dc-bfba-43b9-bc9d-ccbf1076b4f2","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.709531Z","iopub.execute_input":"2025-03-13T14:04:50.709822Z","iopub.status.idle":"2025-03-13T14:04:50.724977Z","shell.execute_reply.started":"2025-03-13T14:04:50.709795Z","shell.execute_reply":"2025-03-13T14:04:50.724082Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"merged_df.isnull().sum()","metadata":{"_uuid":"48c296ce-98b4-46c2-b03c-54ed8788ba21","_cell_guid":"353a6dc1-38e7-4db5-8c0f-d2942d79428a","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.725918Z","iopub.execute_input":"2025-03-13T14:04:50.726227Z","iopub.status.idle":"2025-03-13T14:04:50.752810Z","shell.execute_reply.started":"2025-03-13T14:04:50.726197Z","shell.execute_reply":"2025-03-13T14:04:50.752168Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"merged_df.count()","metadata":{"_uuid":"27525a0b-2c44-4571-a9fb-dae6cd2f2239","_cell_guid":"914f65c9-ecb9-4758-b9f5-b5491eb24499","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.753490Z","iopub.execute_input":"2025-03-13T14:04:50.753682Z","iopub.status.idle":"2025-03-13T14:04:50.770824Z","shell.execute_reply.started":"2025-03-13T14:04:50.753666Z","shell.execute_reply":"2025-03-13T14:04:50.770041Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"merged_df.isnull().values.any() or (merged_df == \" \").values.any()","metadata":{"_uuid":"1c0f2ab1-d8cd-44b2-9bd5-8468123c8e9b","_cell_guid":"b9540af6-801c-4c1d-a384-47f706dddc34","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.771748Z","iopub.execute_input":"2025-03-13T14:04:50.772133Z","iopub.status.idle":"2025-03-13T14:04:50.793225Z","shell.execute_reply.started":"2025-03-13T14:04:50.772101Z","shell.execute_reply":"2025-03-13T14:04:50.792467Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"merged_df.dropna(inplace=True)\nmerged_df = merged_df[~(merged_df == \" \").any(axis=1)]","metadata":{"_uuid":"52ce9e5d-b3f7-4cec-bb33-75faf7b8516d","_cell_guid":"27b98266-1c09-4e84-949f-ee0de1d63721","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.794129Z","iopub.execute_input":"2025-03-13T14:04:50.794431Z","iopub.status.idle":"2025-03-13T14:04:50.833973Z","shell.execute_reply.started":"2025-03-13T14:04:50.794377Z","shell.execute_reply":"2025-03-13T14:04:50.833377Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"merged_df.isnull().values.any() or (merged_df == \" \").values.any()","metadata":{"_uuid":"5d310d1f-843f-4300-ab7a-03043a52fb78","_cell_guid":"38acc08f-20eb-483b-aa49-204e4e8c405d","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.834632Z","iopub.execute_input":"2025-03-13T14:04:50.834816Z","iopub.status.idle":"2025-03-13T14:04:50.867401Z","shell.execute_reply.started":"2025-03-13T14:04:50.834800Z","shell.execute_reply":"2025-03-13T14:04:50.866767Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"merged_df.count()","metadata":{"_uuid":"97c3b5e1-5a03-4a07-9916-fe2ac24076e7","_cell_guid":"9252a896-6c40-4be6-be66-8c0e3489ea33","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.868305Z","iopub.execute_input":"2025-03-13T14:04:50.868613Z","iopub.status.idle":"2025-03-13T14:04:50.886082Z","shell.execute_reply.started":"2025-03-13T14:04:50.868593Z","shell.execute_reply":"2025-03-13T14:04:50.885182Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"merged_df.isnull().sum()","metadata":{"_uuid":"3b863b75-f757-4de3-9758-bc4975867464","_cell_guid":"e121ad51-807b-475a-a661-cf5265cf8294","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.886978Z","iopub.execute_input":"2025-03-13T14:04:50.887293Z","iopub.status.idle":"2025-03-13T14:04:50.909162Z","shell.execute_reply.started":"2025-03-13T14:04:50.887254Z","shell.execute_reply":"2025-03-13T14:04:50.908515Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"merged_df.head()","metadata":{"_uuid":"819e6f97-64cd-4a6f-9c75-48650fcc6847","_cell_guid":"ff82a96d-4ede-4b87-8333-7b266996115a","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.913863Z","iopub.execute_input":"2025-03-13T14:04:50.914060Z","iopub.status.idle":"2025-03-13T14:04:50.924761Z","shell.execute_reply.started":"2025-03-13T14:04:50.914043Z","shell.execute_reply":"2025-03-13T14:04:50.923864Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data_types = merged_df.dtypes\ndata_types","metadata":{"_uuid":"6109f764-5db0-4f41-8b51-4bdc7468c9df","_cell_guid":"6fd00421-add7-4dae-8150-c97fdd216b9b","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.927067Z","iopub.execute_input":"2025-03-13T14:04:50.927372Z","iopub.status.idle":"2025-03-13T14:04:50.939275Z","shell.execute_reply.started":"2025-03-13T14:04:50.927320Z","shell.execute_reply":"2025-03-13T14:04:50.938675Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"merged_df.columns","metadata":{"_uuid":"eeb2c638-e61d-44a5-9139-b40e518d27a4","_cell_guid":"695f9a86-6d6d-4e45-b222-dea6c9bb5aeb","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.940011Z","iopub.execute_input":"2025-03-13T14:04:50.940268Z","iopub.status.idle":"2025-03-13T14:04:50.950979Z","shell.execute_reply.started":"2025-03-13T14:04:50.940248Z","shell.execute_reply":"2025-03-13T14:04:50.950233Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"merged_df","metadata":{"_uuid":"78e109e1-79cc-45d0-8dfe-5920a6d79722","_cell_guid":"75089b24-7886-4ddb-9e53-4a5f7a1a028a","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.951792Z","iopub.execute_input":"2025-03-13T14:04:50.952034Z","iopub.status.idle":"2025-03-13T14:04:50.971925Z","shell.execute_reply.started":"2025-03-13T14:04:50.952001Z","shell.execute_reply":"2025-03-13T14:04:50.971134Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sagittal_t1_df = merged_df[merged_df['series_description'].str.contains('Sagittal T1', case=False)]\nsagittal_t2_df = merged_df[merged_df['series_description'].str.contains('Sagittal T2/STIR', case=False)]\naxial_df = merged_df[merged_df['series_description'].str.contains('Axial', case=False)]","metadata":{"_uuid":"67ca9a30-f407-4258-aca5-a931310a2522","_cell_guid":"2f99c56e-9399-454a-a215-b4c90e022230","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:50.972896Z","iopub.execute_input":"2025-03-13T14:04:50.973171Z","iopub.status.idle":"2025-03-13T14:04:51.047449Z","shell.execute_reply.started":"2025-03-13T14:04:50.973151Z","shell.execute_reply":"2025-03-13T14:04:51.046787Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sagittal_t1_df.head()","metadata":{"_uuid":"75a51bea-561d-462b-83e6-b0e43944d5ec","_cell_guid":"17c3d8f9-7ed2-42d9-8f34-b1a8545b4ba3","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:51.048339Z","iopub.execute_input":"2025-03-13T14:04:51.048637Z","iopub.status.idle":"2025-03-13T14:04:51.059097Z","shell.execute_reply.started":"2025-03-13T14:04:51.048616Z","shell.execute_reply":"2025-03-13T14:04:51.058155Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sagittal_t2_df.head()","metadata":{"_uuid":"ac46d7de-e032-4e1b-8fda-2dd90873b180","_cell_guid":"78e5db9e-60d3-4f97-b70d-e56adb71d072","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:51.059808Z","iopub.execute_input":"2025-03-13T14:04:51.060012Z","iopub.status.idle":"2025-03-13T14:04:51.079002Z","shell.execute_reply.started":"2025-03-13T14:04:51.059995Z","shell.execute_reply":"2025-03-13T14:04:51.078212Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"axial_df.head()","metadata":{"_uuid":"b0a729bc-4fa9-43d1-8c62-3cdb34852d7e","_cell_guid":"6351590b-577a-4309-b19e-2536bfa502cd","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:51.079890Z","iopub.execute_input":"2025-03-13T14:04:51.080192Z","iopub.status.idle":"2025-03-13T14:04:51.096093Z","shell.execute_reply.started":"2025-03-13T14:04:51.080164Z","shell.execute_reply":"2025-03-13T14:04:51.095459Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def split_data(df, train_size=0.8, val_size=0.2):\n    \n    train_df, temp_df = train_test_split(df, train_size=train_size, random_state=42, stratify=df['condition'])\n    val_size_adjusted = 0.5 \n    val_df, test_df = train_test_split(temp_df, test_size=val_size_adjusted, random_state=42)\n    \n    return train_df, val_df, test_df","metadata":{"_uuid":"22ef677e-b48a-4eb8-baa0-5b6f641aecc1","_cell_guid":"614143fd-f32c-4ffe-9841-49c41643c478","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:51.096931Z","iopub.execute_input":"2025-03-13T14:04:51.097265Z","iopub.status.idle":"2025-03-13T14:04:51.108035Z","shell.execute_reply.started":"2025-03-13T14:04:51.097206Z","shell.execute_reply":"2025-03-13T14:04:51.107173Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%time\nsagittal_t1_train, sagittal_t1_val ,sagittal_t1_test = split_data(sagittal_t1_df)","metadata":{"_uuid":"86427fc4-002f-4309-ac7f-8f29732e5f2c","_cell_guid":"fa93b236-8581-4ff9-903d-7fa278ad55ac","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:51.108809Z","iopub.execute_input":"2025-03-13T14:04:51.109046Z","iopub.status.idle":"2025-03-13T14:04:51.142058Z","shell.execute_reply.started":"2025-03-13T14:04:51.109025Z","shell.execute_reply":"2025-03-13T14:04:51.141166Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%time\nsagittal_t2_train, sagittal_t2_val, sagittal_t2_test = split_data(sagittal_t2_df)","metadata":{"_uuid":"1a268ee1-0b5e-4ce2-a3ec-0bf2266e71b0","_cell_guid":"aa22cdbe-ef9b-429e-a7ae-4245dc557681","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:51.142997Z","iopub.execute_input":"2025-03-13T14:04:51.143323Z","iopub.status.idle":"2025-03-13T14:04:51.157926Z","shell.execute_reply.started":"2025-03-13T14:04:51.143277Z","shell.execute_reply":"2025-03-13T14:04:51.157044Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%time\naxial_train, axial_val, axial_test = split_data(axial_df)","metadata":{"_uuid":"9abac433-4205-4832-816c-49a7c4ed5c37","_cell_guid":"450a5d4d-392f-41d5-a228-11d882e67c0e","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:51.158861Z","iopub.execute_input":"2025-03-13T14:04:51.159143Z","iopub.status.idle":"2025-03-13T14:04:51.185843Z","shell.execute_reply.started":"2025-03-13T14:04:51.159116Z","shell.execute_reply":"2025-03-13T14:04:51.185041Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_combined = pd.concat([sagittal_t1_train, sagittal_t2_train, axial_train])\nval_combined = pd.concat([sagittal_t1_val, sagittal_t2_val, axial_val])\ntest_combined = pd.concat([sagittal_t1_test, sagittal_t2_test, axial_test])","metadata":{"_uuid":"c142b0e5-4bee-4f13-a761-973088493373","_cell_guid":"fa6d19fa-0034-44e4-a7f3-a8878a673622","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:51.186652Z","iopub.execute_input":"2025-03-13T14:04:51.186912Z","iopub.status.idle":"2025-03-13T14:04:51.194248Z","shell.execute_reply.started":"2025-03-13T14:04:51.186883Z","shell.execute_reply":"2025-03-13T14:04:51.193561Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"encoder = OneHotEncoder(sparse_output=False)\ntrain_labels_onehot = encoder.fit_transform(train_combined[['value']])\nval_labels_onehot = encoder.transform(val_combined[['value']])\ntest_labels_onehot = encoder.transform(test_combined[['value']])","metadata":{"_uuid":"4dea5ce5-7515-4a63-bd69-257641dce583","_cell_guid":"e910d811-df81-4c43-b6dc-f2779ac1fd6c","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:51.195019Z","iopub.execute_input":"2025-03-13T14:04:51.195269Z","iopub.status.idle":"2025-03-13T14:04:51.221117Z","shell.execute_reply.started":"2025-03-13T14:04:51.195249Z","shell.execute_reply":"2025-03-13T14:04:51.220598Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_labels_df = pd.DataFrame(train_labels_onehot, columns=encoder.get_feature_names_out(['value']))\nval_labels_df = pd.DataFrame(val_labels_onehot, columns=encoder.get_feature_names_out(['value']))\ntest_labels_df = pd.DataFrame(test_labels_onehot, columns=encoder.get_feature_names_out(['value']))","metadata":{"_uuid":"d0927707-6a5b-4258-bcf2-5cdb5ce5e054","_cell_guid":"588c4846-0961-4994-a965-efb09109ccc4","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:51.221745Z","iopub.execute_input":"2025-03-13T14:04:51.221923Z","iopub.status.idle":"2025-03-13T14:04:51.226400Z","shell.execute_reply.started":"2025-03-13T14:04:51.221907Z","shell.execute_reply":"2025-03-13T14:04:51.225635Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_combined = train_combined.reset_index(drop=True)\nval_combined = val_combined.reset_index(drop=True)\ntest_combined = test_combined.reset_index(drop=True)","metadata":{"_uuid":"5a45fd98-eabf-4a21-9805-8545e93db4e0","_cell_guid":"240afbcc-6bef-4144-8d1d-d88c16715adc","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:51.227119Z","iopub.execute_input":"2025-03-13T14:04:51.227437Z","iopub.status.idle":"2025-03-13T14:04:51.254578Z","shell.execute_reply.started":"2025-03-13T14:04:51.227386Z","shell.execute_reply":"2025-03-13T14:04:51.253912Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_combined = pd.concat([train_combined, train_labels_df], axis=1)\nval_combined = pd.concat([val_combined, val_labels_df], axis=1)\ntest_combined = pd.concat([test_combined, test_labels_df], axis=1)","metadata":{"_uuid":"00b52508-6d63-4b80-bf1f-0f6e5b5f91a6","_cell_guid":"f9163877-01f4-42f3-8a84-9219d09cb628","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:51.255280Z","iopub.execute_input":"2025-03-13T14:04:51.255595Z","iopub.status.idle":"2025-03-13T14:04:51.262172Z","shell.execute_reply.started":"2025-03-13T14:04:51.255573Z","shell.execute_reply":"2025-03-13T14:04:51.261489Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_sampled_df = train_combined.sample(frac=0.1, random_state=42)\nval_sampled_df = val_combined.sample(frac=0.1, random_state=42)\ntest_sampled_df = test_combined.sample(frac=0.1, random_state=42)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-13T14:04:51.263133Z","iopub.execute_input":"2025-03-13T14:04:51.263390Z","iopub.status.idle":"2025-03-13T14:04:51.275844Z","shell.execute_reply.started":"2025-03-13T14:04:51.263371Z","shell.execute_reply":"2025-03-13T14:04:51.274995Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f\"Train Shape :{train_combined.shape},Val Shape :{val_combined.shape},Test Shape : {test_combined.shape}\")","metadata":{"_uuid":"4f678ef4-a108-4817-9247-1de91f8cfafd","_cell_guid":"2414107f-0e50-4d20-b16b-84ff4f33c120","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:51.276665Z","iopub.execute_input":"2025-03-13T14:04:51.276990Z","iopub.status.idle":"2025-03-13T14:04:51.281751Z","shell.execute_reply.started":"2025-03-13T14:04:51.276956Z","shell.execute_reply":"2025-03-13T14:04:51.280998Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_combined.head()","metadata":{"_uuid":"1bf5ce58-bc53-4621-8c78-0f22c4fde09a","_cell_guid":"bb8e0933-b096-4222-a267-87b7771e826b","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:51.282344Z","iopub.execute_input":"2025-03-13T14:04:51.282578Z","iopub.status.idle":"2025-03-13T14:04:51.303572Z","shell.execute_reply.started":"2025-03-13T14:04:51.282550Z","shell.execute_reply":"2025-03-13T14:04:51.302671Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def add_image_paths(df, base_path='/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_images/'):\n    df['image_path'] = df.apply(\n        lambda row: os.path.join(base_path, f\"{row['study_id']}/{row['series_id']}/{row['instance_number']}.dcm\"), axis=1\n    )\n    return df","metadata":{"_uuid":"6d3ae048-ac77-4e9a-90a8-46561c04cb0d","_cell_guid":"b1ddefff-3419-43cd-a350-b298c75880e0","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:51.304372Z","iopub.execute_input":"2025-03-13T14:04:51.304702Z","iopub.status.idle":"2025-03-13T14:04:51.314191Z","shell.execute_reply.started":"2025-03-13T14:04:51.304672Z","shell.execute_reply":"2025-03-13T14:04:51.313573Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_sampled_df = add_image_paths(train_sampled_df)\nval_sampled_df = add_image_paths(val_sampled_df)\ntest_sampled_df = add_image_paths(test_sampled_df)","metadata":{"_uuid":"1bb3fd75-94ba-42f7-a0f4-fd7532225ff3","_cell_guid":"dbd45153-f38d-4a41-a51a-6765fa5964eb","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:51.314958Z","iopub.execute_input":"2025-03-13T14:04:51.315233Z","iopub.status.idle":"2025-03-13T14:04:51.384436Z","shell.execute_reply.started":"2025-03-13T14:04:51.315208Z","shell.execute_reply":"2025-03-13T14:04:51.383858Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_combined.head()","metadata":{"_uuid":"36b4adfd-5a57-4d01-930c-d2b2b654e4a4","_cell_guid":"f79b396e-b69c-4bfc-940e-823339edfe1b","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:51.385109Z","iopub.execute_input":"2025-03-13T14:04:51.385401Z","iopub.status.idle":"2025-03-13T14:04:51.398736Z","shell.execute_reply.started":"2025-03-13T14:04:51.385380Z","shell.execute_reply":"2025-03-13T14:04:51.397752Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from PIL import Image\n\ndef convert_dcm_to_jpeg(dcm_file_path, jpeg_file_path):\n    \n    dicom_image = pydicom.dcmread(dcm_file_path)\n    pixel_array = dicom_image.pixel_array.astype(np.float32)  # Ensure float32 for processing\n    \n    if 'RescaleSlope' in dicom_image and 'RescaleIntercept' in dicom_image:\n        pixel_array = pixel_array * dicom_image.RescaleSlope + dicom_image.RescaleIntercept\n    \n    min_val, max_val = np.min(pixel_array), np.max(pixel_array)\n    if max_val != min_val:\n        pixel_array = (pixel_array - min_val) / (max_val - min_val) * 255\n    else:\n        pixel_array = np.zeros_like(pixel_array)  # Black image if no intensity variation\n    \n    pixel_array = pixel_array.astype(np.uint8)\n    image = Image.fromarray(pixel_array).convert('L')  \n    image.save(jpeg_file_path, \"JPEG\")","metadata":{"_uuid":"d5cefa29-f322-4bea-b9a9-a681ed2f31ff","_cell_guid":"a6d5b2a0-2f90-48a3-b468-fe91cde01d81","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:51.399584Z","iopub.execute_input":"2025-03-13T14:04:51.399803Z","iopub.status.idle":"2025-03-13T14:04:51.409952Z","shell.execute_reply.started":"2025-03-13T14:04:51.399784Z","shell.execute_reply":"2025-03-13T14:04:51.409119Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def update_dataframe_with_jpeg_paths(df, output_dir):\n   \n    if not os.path.exists(output_dir):\n        os.makedirs(output_dir)\n    jpeg_paths = []\n\n    for index, row in df.iterrows():\n        dcm_file_path = row['image_path']  \n\n        study_id = row['study_id']  \n        condition = row['condition'] \n        level = row['level'] \n        \n        jpeg_file_name = f\"{study_id}_{condition}_{level}.jpg\"\n        jpeg_file_path = os.path.join(output_dir, jpeg_file_name)  # Construct JPEG file path\n\n        jpeg_dir = os.path.dirname(jpeg_file_path)\n        if not os.path.exists(jpeg_dir):\n            os.makedirs(jpeg_dir)\n       \n        convert_dcm_to_jpeg(dcm_file_path, jpeg_file_path)\n        jpeg_paths.append(jpeg_file_path)\n    df['jpeg_file_path'] = jpeg_paths\n\n    return df","metadata":{"_uuid":"cb6f884a-abc3-4c99-be8d-8d947f5114c6","_cell_guid":"ad091968-81d6-4cdd-806e-8157caaa75c2","trusted":true,"execution":{"iopub.status.busy":"2025-03-13T14:04:51.410643Z","iopub.execute_input":"2025-03-13T14:04:51.410880Z","iopub.status.idle":"2025-03-13T14:04:51.422491Z","shell.execute_reply.started":"2025-03-13T14:04:51.410862Z","shell.execute_reply":"2025-03-13T14:04:51.421648Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%time\noutput_dir = '/kaggle/working/output/train'\nupdated_train_df = update_dataframe_with_jpeg_paths(train_sampled_df, output_dir)","metadata":{"_uuid":"7163a67f-44a9-4380-93b5-5b0b2b5e6409","_cell_guid":"184eb900-a481-4c05-8127-e669a4fd207f","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:04:51.423216Z","iopub.execute_input":"2025-03-13T14:04:51.423402Z","iopub.status.idle":"2025-03-13T14:06:06.174296Z","shell.execute_reply.started":"2025-03-13T14:04:51.423386Z","shell.execute_reply":"2025-03-13T14:06:06.173600Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%time\noutput_dir = '/kaggle/working/output/val'\nupdated_val_df = update_dataframe_with_jpeg_paths(val_sampled_df, output_dir)","metadata":{"_uuid":"d4ef7452-0973-40ae-a3a7-4e9b61e6e645","_cell_guid":"ee218896-d28c-447c-a5b7-10c251150399","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:06:06.175048Z","iopub.execute_input":"2025-03-13T14:06:06.175379Z","iopub.status.idle":"2025-03-13T14:06:14.887066Z","shell.execute_reply.started":"2025-03-13T14:06:06.175355Z","shell.execute_reply":"2025-03-13T14:06:14.885999Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%time\noutput_dir = '/kaggle/working/output/test'\nupdated_test_df = update_dataframe_with_jpeg_paths(test_sampled_df, output_dir)","metadata":{"_uuid":"11596858-ee5f-496d-ab86-95a4fc261e3a","_cell_guid":"b89a5d08-ad6c-4ab6-9159-24ac0b00be6b","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:06:14.888239Z","iopub.execute_input":"2025-03-13T14:06:14.888671Z","iopub.status.idle":"2025-03-13T14:06:23.333627Z","shell.execute_reply.started":"2025-03-13T14:06:14.888640Z","shell.execute_reply":"2025-03-13T14:06:23.332721Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"updated_train_df.head()","metadata":{"_uuid":"76e74eb2-958e-4bb1-ab97-6a2db0f89fe7","_cell_guid":"e6117882-5678-475e-a672-dbcad1149d67","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:06:23.334594Z","iopub.execute_input":"2025-03-13T14:06:23.334898Z","iopub.status.idle":"2025-03-13T14:06:23.350616Z","shell.execute_reply.started":"2025-03-13T14:06:23.334867Z","shell.execute_reply":"2025-03-13T14:06:23.349619Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"updated_train_df.columns","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-13T14:06:23.351348Z","iopub.execute_input":"2025-03-13T14:06:23.351610Z","iopub.status.idle":"2025-03-13T14:06:23.363027Z","shell.execute_reply.started":"2025-03-13T14:06:23.351591Z","shell.execute_reply":"2025-03-13T14:06:23.362311Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"updated_train_df.head(2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-13T14:06:23.363757Z","iopub.execute_input":"2025-03-13T14:06:23.364027Z","iopub.status.idle":"2025-03-13T14:06:23.384957Z","shell.execute_reply.started":"2025-03-13T14:06:23.364006Z","shell.execute_reply":"2025-03-13T14:06:23.384084Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def preprocess_dicom(image_array):\n    image = tf.convert_to_tensor(image_array, dtype=tf.float32)\n    image = tf.where(tf.math.is_nan(image) | tf.math.is_inf(image), 0.0, image)  # Replace NaN/inf with 0\n    new_size = tf.constant([320, 320])\n    image = tf.image.resize(image, new_size)\n    image = image / 255.0\n    return image","metadata":{"_uuid":"e23c2cfd-ee56-4adc-a5ff-4c3c211c469e","_cell_guid":"2235faf1-c2c6-4868-814b-7d16a5d2e223","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:06:23.385793Z","iopub.execute_input":"2025-03-13T14:06:23.386038Z","iopub.status.idle":"2025-03-13T14:06:23.396858Z","shell.execute_reply.started":"2025-03-13T14:06:23.386006Z","shell.execute_reply":"2025-03-13T14:06:23.396065Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(\n    rotation_range=5,\n    width_shift_range=0.1,\n    height_shift_range=0.1,\n    shear_range=0.1,\n    zoom_range=0.1,\n    horizontal_flip=True,\n    preprocessing_function=preprocess_dicom\n)","metadata":{"_uuid":"e85ad5f5-b263-4411-b9f2-f024e17d3bd3","_cell_guid":"3f9a7a91-d004-438a-aef0-3811e7ef7f04","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:06:23.397788Z","iopub.execute_input":"2025-03-13T14:06:23.398112Z","iopub.status.idle":"2025-03-13T14:06:23.410911Z","shell.execute_reply.started":"2025-03-13T14:06:23.398091Z","shell.execute_reply":"2025-03-13T14:06:23.410129Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_test_datagen = ImageDataGenerator(\n    preprocessing_function=preprocess_dicom\n)","metadata":{"_uuid":"d508cbf1-5751-4747-8452-4ed8b48b36cb","_cell_guid":"643da5f5-583e-4278-bed3-73267cf98bea","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:06:23.411722Z","iopub.execute_input":"2025-03-13T14:06:23.411994Z","iopub.status.idle":"2025-03-13T14:06:23.427174Z","shell.execute_reply.started":"2025-03-13T14:06:23.411966Z","shell.execute_reply":"2025-03-13T14:06:23.426401Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def capsule_data_generator(generator):\n    while True:\n        X_batch, y_batch = next(generator)\n        y_classification = np.array(y_batch, dtype=np.float32)  # Ensure float32\n        y_reconstruction = X_batch  # Shape: (batch_size, 320, 320, 1)\n        assert y_classification.shape[1] == 3, \"y_classification must have 3 columns\"\n        assert not np.any(np.isnan(X_batch)), \"NaN in X_batch\"\n        assert not np.any(np.isnan(y_classification)), \"NaN in y_classification\"\n        yield X_batch, {\"classification_output\": y_classification, \"decoder_output\": y_reconstruction}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-13T14:06:23.428216Z","iopub.execute_input":"2025-03-13T14:06:23.428591Z","iopub.status.idle":"2025-03-13T14:06:23.440586Z","shell.execute_reply.started":"2025-03-13T14:06:23.428562Z","shell.execute_reply":"2025-03-13T14:06:23.439796Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_generator_base = train_datagen.flow_from_dataframe(\n    dataframe=updated_train_df,\n    x_col='jpeg_file_path',\n    y_col = ['value_Moderate','value_Normal/Mild', 'value_Severe'],\n    target_size=(320, 320),\n    color_mode='grayscale',\n    class_mode='raw',\n    batch_size=32,\n    shuffle=True\n)\n\nval_generator_base = val_test_datagen.flow_from_dataframe(\n    dataframe=updated_val_df,\n    x_col='jpeg_file_path',\n    #y_col=['value_Moderate','value_Normal/Mild', 'value_Severe'],\n    y_col = ['value_Moderate','value_Normal/Mild', 'value_Severe'],\n    target_size=(320, 320),\n    color_mode='grayscale',\n    class_mode='raw',\n    batch_size=32,\n    shuffle=False\n)\n\ntest_generator_base = val_test_datagen.flow_from_dataframe(\n    dataframe=updated_test_df,\n    x_col='jpeg_file_path',\n    y_col=['value_Moderate','value_Normal/Mild', 'value_Severe'],\n    #y_col = 'lables',\n    target_size=(320, 320),\n    color_mode='grayscale',\n    class_mode='raw',\n    batch_size=32,\n    shuffle=False\n)","metadata":{"_uuid":"14878458-45fe-4623-8d37-0f76b27410d3","_cell_guid":"a114f931-8c3f-49f7-8812-6d1694963545","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:06:23.441371Z","iopub.execute_input":"2025-03-13T14:06:23.441674Z","iopub.status.idle":"2025-03-13T14:06:23.507179Z","shell.execute_reply.started":"2025-03-13T14:06:23.441647Z","shell.execute_reply":"2025-03-13T14:06:23.506458Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_generator = capsule_data_generator(train_generator_base)\nval_generator = capsule_data_generator(val_generator_base)\ntest_generator = capsule_data_generator(test_generator_base)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-13T14:06:23.508187Z","iopub.execute_input":"2025-03-13T14:06:23.508484Z","iopub.status.idle":"2025-03-13T14:06:23.511944Z","shell.execute_reply.started":"2025-03-13T14:06:23.508457Z","shell.execute_reply":"2025-03-13T14:06:23.511214Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_sample, y_sample = next(train_generator)\n\nprint(\"Input Image Shape:\", X_sample.shape)\nprint(\"Classification Labels Shape:\", y_sample[\"classification_output\"].shape)  \nprint(\"Decoder Target Shape:\", y_sample[\"decoder_output\"].shape)  ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-13T14:06:23.512832Z","iopub.execute_input":"2025-03-13T14:06:23.513120Z","iopub.status.idle":"2025-03-13T14:06:26.722717Z","shell.execute_reply.started":"2025-03-13T14:06:23.513092Z","shell.execute_reply":"2025-03-13T14:06:26.721688Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras import layers, models, optimizers, regularizers, callbacks\nfrom tensorflow.keras.layers import LeakyReLU\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom sklearn.preprocessing import OneHotEncoder\nimport pandas as pd\nimport os\nimport logging\n\nlogging.getLogger('tensorflow').setLevel(logging.ERROR)\n\n@tf.keras.utils.register_keras_serializable()\nclass Squash(layers.Layer):\n    def __init__(self, **kwargs):\n        super(Squash, self).__init__(**kwargs)\n\n    def call(self, inputs):\n        squared_norm = tf.reduce_sum(tf.square(inputs), axis=-1, keepdims=True)\n        scale = squared_norm / (1 + squared_norm)\n        result = (scale * inputs) / tf.sqrt(squared_norm + 1e-12)\n        return result\n\n    def compute_output_shape(self, input_shape):\n        return input_shape\n\n    def get_config(self):\n        config = super(Squash, self).get_config()\n        return config\n\n@tf.keras.utils.register_keras_serializable()\nclass PrimaryCaps(layers.Layer):\n    def __init__(self, num_capsules, dim_capsule, kernel_size, strides, **kwargs):\n        super(PrimaryCaps, self).__init__(**kwargs)\n        self.num_capsules = num_capsules\n        self.dim_capsule = dim_capsule\n        self.kernel_size = kernel_size\n        self.strides = strides\n\n        # Define the Conv2D layer\n        self.conv = layers.Conv2D(\n            filters=self.num_capsules * self.dim_capsule,\n            kernel_size=self.kernel_size,\n            strides=self.strides,\n            padding='same',\n            activation=None,\n            kernel_initializer='glorot_normal',\n            kernel_regularizer=regularizers.l2(1e-3),\n            name='conv2d' \n        )\n        \n        self.batch_norm = layers.BatchNormalization(name='batch_norm')\n        self.activation = layers.Activation('relu', name='relu')\n\n    def build(self, input_shape):\n        \n        self.conv.build(input_shape)\n        conv_output_shape = self.conv.compute_output_shape(input_shape)\n        self.batch_norm.build(conv_output_shape)\n        self.activation.build(conv_output_shape)\n        super(PrimaryCaps, self).build(input_shape)\n\n    def call(self, inputs, training=True):\n        x = self.conv(inputs)\n        x = self.batch_norm(x, training=training)  \n        x = self.activation(x)                     \n        batch_size = tf.shape(x)[0]\n        spatial_dims = tf.shape(x)[1] * tf.shape(x)[2]\n        num_capsules = spatial_dims * self.num_capsules\n        x = tf.reshape(x, [batch_size, num_capsules, self.dim_capsule])\n        return Squash()(x)\n\n    def compute_output_shape(self, input_shape):\n        conv_output_shape = self.conv.compute_output_shape(input_shape)\n        spatial_dims = conv_output_shape[1] * conv_output_shape[2]\n        num_capsules = spatial_dims * self.num_capsules\n        return (conv_output_shape[0], num_capsules, self.dim_capsule)\n\n    def get_config(self):\n        config = super(PrimaryCaps, self).get_config()\n        config.update({\n            'num_capsules': self.num_capsules,\n            'dim_capsule': self.dim_capsule,\n            'kernel_size': self.kernel_size,\n            'strides': self.strides\n        })\n        return config\n\n@tf.keras.utils.register_keras_serializable()\nclass DigitCaps(layers.Layer):\n    def __init__(self, num_capsules, dim_capsule, routing_iters=3, **kwargs):\n        super(DigitCaps, self).__init__(**kwargs)\n        self.num_capsules = num_capsules\n        self.dim_capsule = dim_capsule\n        self.routing_iters = routing_iters\n        self.batch_norm = layers.BatchNormalization(name='batch_norm')\n\n    def build(self, input_shape):\n        self.num_input_capsules = input_shape[1]\n        self.dim_input_capsule = input_shape[2]\n        self.W = self.add_weight(\n            shape=[self.num_input_capsules, self.num_capsules, self.dim_input_capsule, self.dim_capsule],\n            initializer='glorot_normal',\n            trainable=True,\n            name='W'\n        )\n        self.batch_norm.build(input_shape=(None, self.num_capsules, self.dim_capsule))\n        super(DigitCaps, self).build(input_shape)\n\n    def call(self, inputs, training=True):\n        u_hat = tf.einsum('bik,ijkd->bijd', inputs, self.W)\n        return self.dynamic_routing(u_hat, training=training)\n\n    def dynamic_routing(self, u_hat, training=True):\n        b = tf.zeros(shape=[tf.shape(u_hat)[0], self.num_input_capsules, self.num_capsules])\n        for i in range(self.routing_iters):\n            c = tf.nn.softmax(b, axis=2)\n            c_expand = tf.expand_dims(c, axis=-1)\n            s = tf.reduce_sum(c_expand * u_hat, axis=1)\n            s = self.batch_norm(s, training=training)\n            v = Squash()(s)\n            if i < self.routing_iters - 1:\n                v_expand = tf.expand_dims(v, axis=1)\n                u_v_dot = tf.reduce_sum(u_hat * v_expand, axis=-1)\n                b += u_v_dot\n        return v\n\n    def compute_output_shape(self, input_shape):\n        return (input_shape[0], self.num_capsules, self.dim_capsule)\n\n    def get_config(self):\n        config = super(DigitCaps, self).get_config()\n        config.update({\n            'num_capsules': self.num_capsules,\n            'dim_capsule': self.dim_capsule,\n            'routing_iters': self.routing_iters\n        })\n        return config\n\n    def get_weights(self):\n        weights = super(DigitCaps, self).get_weights()\n        weights.extend(self.batch_norm.get_weights())\n        return weights\n\n    def set_weights(self, weights):\n        main_weights = weights[:1]  \n        batch_norm_weights = weights[1:] \n        super(DigitCaps, self).set_weights(main_weights)\n        if batch_norm_weights:\n            self.batch_norm.set_weights(batch_norm_weights)\n\n@tf.keras.utils.register_keras_serializable()\nclass Decoder(layers.Layer):\n    def __init__(self, decoder_output_shape=(320, 320, 1), num_classes=3, dim_capsule=16, **kwargs):\n        super(Decoder, self).__init__(**kwargs)\n        self.decoder_output_shape = decoder_output_shape\n        self.num_classes = num_classes\n        self.dim_capsule = dim_capsule\n        self.decoder = None  \n    def build(self, input_shape):\n    \n        self.decoder = models.Sequential([\n            layers.Flatten(name='flatten'),\n            layers.Dense(10 * 10 * 64, activation='relu', kernel_initializer='glorot_normal', kernel_regularizer=regularizers.l2(1e-5), name='dense'),\n            layers.BatchNormalization(name='batch_norm_1'),\n            layers.Reshape((10, 10, 64), name='reshape'),\n            layers.Conv2DTranspose(\n                filters=32,\n                kernel_size=(5, 5),\n                strides=(2, 2),\n                padding='same',\n                activation='relu',\n                kernel_initializer='glorot_normal',\n                kernel_regularizer=regularizers.l2(1e-5),\n                name='conv2d_transpose_1'\n            ),\n            layers.BatchNormalization(name='batch_norm_2'),\n            layers.Conv2DTranspose(\n                filters=16,\n                kernel_size=(5, 5),\n                strides=(2, 2),\n                padding='same',\n                activation='relu',\n                kernel_initializer='glorot_normal',\n                kernel_regularizer=regularizers.l2(1e-5),\n                name='conv2d_transpose_2'\n            ),\n            layers.BatchNormalization(name='batch_norm_3'),\n            layers.Conv2DTranspose(\n                filters=8,\n                kernel_size=(5, 5),\n                strides=(4, 4),\n                padding='same',\n                activation='relu',\n                kernel_initializer='glorot_normal',\n                kernel_regularizer=regularizers.l2(1e-5),\n                name='conv2d_transpose_3'\n            ),\n            layers.BatchNormalization(name='batch_norm_4'),\n            layers.Conv2DTranspose(\n                filters=1,\n                kernel_size=(5, 5),\n                strides=(2, 2),\n                padding='same',\n                activation='sigmoid',\n                kernel_initializer='glorot_normal',\n                kernel_regularizer=regularizers.l2(1e-5),\n                name='conv2d_transpose_4'\n            )\n        ], name='decoder_sequential')\n        self.decoder.build(input_shape)\n        super(Decoder, self).build(input_shape)\n\n    def call(self, inputs):\n        return self.decoder(inputs)\n\n    def compute_output_shape(self, input_shape):\n        return (input_shape[0],) + tuple(self.decoder_output_shape)\n\n    def get_config(self):\n        config = super(Decoder, self).get_config()\n        config.update({\n            'decoder_output_shape': self.decoder_output_shape,\n            'num_classes': self.num_classes,\n            'dim_capsule': self.dim_capsule\n        })\n        return config\n\n    def get_weights(self):\n        # Include the weights of the Sequential model\n        if self.decoder is None:\n            return []\n        return self.decoder.get_weights()\n\n    def set_weights(self, weights):\n        # Set the weights of the Sequential model\n        if self.decoder is not None and weights:\n            self.decoder.set_weights(weights)\n\n# Custom MarginLoss\n@tf.keras.utils.register_keras_serializable()\nclass MarginLoss(tf.keras.losses.Loss):\n    def __init__(self, **kwargs):\n        super(MarginLoss, self).__init__(**kwargs)\n\n    def call(self, y_true, y_pred):\n        m_plus, m_minus, lambda_val = 0.9, 0.1, 0.5\n        L = (y_true * tf.square(tf.maximum(0., (m_plus - y_pred)))) + \\\n            (lambda_val * (1 - y_true) * tf.square(tf.maximum(0., (y_pred - m_minus))))\n        return tf.reduce_mean(tf.reduce_sum(L, axis=1))\n\n    def get_config(self):\n        config = super(MarginLoss, self).get_config()\n        return config\n\n# Custom CapsuleNormLayer\n@tf.keras.utils.register_keras_serializable()\nclass CapsuleNormLayer(layers.Layer):\n    def __init__(self, **kwargs):\n        super(CapsuleNormLayer, self).__init__(**kwargs)\n\n    def call(self, inputs):\n        return tf.norm(inputs, axis=-1)\n\n    def get_config(self):\n        config = super(CapsuleNormLayer, self).get_config()\n        return config","metadata":{"_uuid":"4e6a279d-57e6-4a8b-b680-3b1faaabc017","_cell_guid":"521869c8-09a3-42d4-b4e2-de4287113a87","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:06:26.723632Z","iopub.execute_input":"2025-03-13T14:06:26.723920Z","iopub.status.idle":"2025-03-13T14:06:26.752190Z","shell.execute_reply.started":"2025-03-13T14:06:26.723899Z","shell.execute_reply":"2025-03-13T14:06:26.751305Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from keras.layers import Lambda\n\ndef CapsNet(input_shape, num_classes, routing_iters=3):\n    inputs = layers.Input(shape=input_shape)\n\n    x = layers.Conv2D(\n        filters=266,\n        kernel_size=(4,4),\n        strides=(2, 2),\n        padding='same',\n        kernel_initializer='glorot_normal',\n        activation='leaky_relu',\n        name='conv1'\n    )(inputs)\n    \n    x = layers.BatchNormalization()(x)\n\n    y = layers.Conv2D(\n        filters=144,\n        kernel_size=(5,5),\n        strides=(2, 2),\n        padding='same',\n        kernel_initializer='glorot_normal',\n        activation='leaky_relu',\n        name='conv2'\n    )(x)\n    \n    y = layers.BatchNormalization()(y)\n\n    z = layers.Conv2D(\n        filters=1,\n        kernel_size=(6,6),\n        strides=(2, 2),\n        padding='same',\n        kernel_initializer='glorot_normal',\n        activation='relu',\n        name='conv3'\n    )(y)\n    \n    z= layers.BatchNormalization()(z)\n\n    primary_caps = PrimaryCaps(\n        num_capsules=8,   \n        dim_capsule=16,    \n        kernel_size=4,\n        strides=3,\n        name='primary_caps'\n    )(z)\n\n    digit_caps1 = DigitCaps(\n        num_capsules=num_classes,\n        dim_capsule=16,    \n        routing_iters=routing_iters,\n        name='digit_caps1'\n    )(primary_caps)\n\n    caps_norm = CapsuleNormLayer(name='caps_norm')(digit_caps1)\n    classification_output = layers.Softmax(name='classification_output')(caps_norm)\n \n\n    decoder_output = Decoder(\n        decoder_output_shape=input_shape,  \n        name='decoder_output'\n    )(digit_caps1)\n\n    model = models.Model(\n        inputs=inputs,\n        outputs=[classification_output,decoder_output],\n        name='CapsNet'\n    )\n    \n    return model","metadata":{"_uuid":"0aa59754-cea9-41bc-9d3f-213dfcb666dc","_cell_guid":"5312bc30-63e0-4591-ad5f-ed8cd2438534","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:06:26.753051Z","iopub.execute_input":"2025-03-13T14:06:26.753309Z","iopub.status.idle":"2025-03-13T14:06:26.769904Z","shell.execute_reply.started":"2025-03-13T14:06:26.753277Z","shell.execute_reply":"2025-03-13T14:06:26.769205Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"try:\n    resolver = tf.distribute.cluster_resolver.TPUClusterResolver(tpu='')  \n    tf.config.experimental_connect_to_cluster(resolver)\n    tf.tpu.experimental.initialize_tpu_system(resolver)\n    strategy = tf.distribute.TPUStrategy(resolver)\n    print(\"TPU initialized successfully.\")\nexcept ValueError as e:\n    print(f\"TPU initialization failed: {e}\")\n    strategy = tf.distribute.MirroredStrategy()\n    print(\"Using MirroredStrategy instead.\")","metadata":{"_uuid":"4484c893-af05-4957-8bbc-d0d1d96d7b20","_cell_guid":"04960099-af37-42aa-9bc3-6739afcd61f9","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:06:26.770676Z","iopub.execute_input":"2025-03-13T14:06:26.770955Z","iopub.status.idle":"2025-03-13T14:06:26.793034Z","shell.execute_reply.started":"2025-03-13T14:06:26.770928Z","shell.execute_reply":"2025-03-13T14:06:26.792284Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau, TerminateOnNaN\nfrom tensorflow.keras.optimizers import SGD\nfrom tensorflow.keras.optimizers import Nadam\nfrom tensorflow.keras.callbacks import TensorBoard\nimport datetime\nfrom keras.optimizers import Adam\nfrom tensorflow.keras.optimizers import Lamb\nfrom tensorflow.keras.optimizers import Adafactor\n\nwith strategy.scope():\n    input_shape = (320, 320, 1)\n    num_classes = 3\n    routing_iters = 6\n    model = CapsNet(input_shape, num_classes, routing_iters)\n\n    lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(\n        initial_learning_rate=1e-6,\n        decay_steps=1000,\n        decay_rate=0.9,\n        staircase=False\n    )\n    \n    optimizer = tf.keras.optimizers.Lamb(learning_rate= 1e-6, clipnorm=1.0)\n\n    model.compile(\n        optimizer=optimizer,\n        loss={\n            'classification_output':tf.keras.losses.CategoricalCrossentropy(),\n            'decoder_output': tf.keras.losses.MeanSquaredError()\n        },\n        loss_weights={'classification_output': 0.1, 'decoder_output': 0.1},\n        metrics={\n            'classification_output': 'accuracy',\n            'decoder_output': 'mse'\n        }\n    )\n    \nmodel.summary()","metadata":{"_uuid":"c586355e-cc2c-48ef-af88-04a255ad7bf2","_cell_guid":"d832f6ca-d353-423e-9147-8e62b3fc7930","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:06:26.794097Z","iopub.execute_input":"2025-03-13T14:06:26.794393Z","iopub.status.idle":"2025-03-13T14:06:28.002815Z","shell.execute_reply.started":"2025-03-13T14:06:26.794361Z","shell.execute_reply":"2025-03-13T14:06:28.002117Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model.fit(\n    train_generator,\n    steps_per_epoch=len(updated_train_df) // 32,\n    validation_data=val_generator,\n    validation_steps=len(updated_val_df) // 32,\n    epochs=70,\n    callbacks = [\n        #lr_scheduler,\n        tf.keras.callbacks.TerminateOnNaN(),\n        tf.keras.callbacks.EarlyStopping(monitor='val_classification_output_accuracy', patience=10, restore_best_weights=True,mode = 'max'),\n        tf.keras.callbacks.TensorBoard(log_dir = \"/kaggle/working/logs/fit/\", histogram_freq=1) \n    ]\n)","metadata":{"_uuid":"7738ea4a-2b94-4092-88ab-1a24d2e714ca","_cell_guid":"e36e6254-f8ea-465f-9605-5295b3f3d558","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-13T14:06:28.003471Z","iopub.execute_input":"2025-03-13T14:06:28.003678Z","iopub.status.idle":"2025-03-13T15:48:14.352660Z","shell.execute_reply.started":"2025-03-13T14:06:28.003660Z","shell.execute_reply":"2025-03-13T15:48:14.351909Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"classification_output_accuracy,classification_output_loss,decoder_output_loss,decoder_output_mse,loss = model.evaluate(test_generator, batch_size=32,steps=len(updated_test_df) // 32,return_dict=True)","metadata":{"_uuid":"c468ba4c-3b41-4018-a0e4-212107a392d6","_cell_guid":"bbd2c137-1a2e-472b-bfa6-75f965c8292b","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true,"execution":{"iopub.status.busy":"2025-03-13T15:53:56.951193Z","iopub.execute_input":"2025-03-13T15:53:56.951548Z","iopub.status.idle":"2025-03-13T15:54:01.442423Z","shell.execute_reply.started":"2025-03-13T15:53:56.951521Z","shell.execute_reply":"2025-03-13T15:54:01.441691Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(classification_output_accuracy,classification_output_loss,decoder_output_loss,decoder_output_mse,loss)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-13T15:54:11.501842Z","iopub.execute_input":"2025-03-13T15:54:11.502211Z","iopub.status.idle":"2025-03-13T15:54:11.507174Z","shell.execute_reply.started":"2025-03-13T15:54:11.502181Z","shell.execute_reply":"2025-03-13T15:54:11.506471Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\ndef plot_history(history):\n    # Plot accuracy\n    plt.figure(figsize=(12, 4))\n\n    # Plot accuracy for softmax output\n    plt.subplot(1, 3, 1)\n    plt.plot(history.history['classification_output_accuracy'], label='Train Accuracy')\n    plt.plot(history.history['val_classification_output_accuracy'], label='Val Accuracy')\n    plt.title('Model Accuracy')\n    plt.xlabel('Epochs')\n    plt.ylabel('Accuracy')\n    plt.legend()\n\n    # Plot loss for softmax output\n    plt.subplot(1, 3, 2)\n    plt.plot(history.history['loss'], label='Train Loss')\n    plt.plot(history.history['val_loss'], label='Val Loss')\n    plt.title('Model Loss')\n    plt.xlabel('Epochs')\n    plt.ylabel('Loss')\n    plt.legend()\n\n    plt.tight_layout()\n    plt.show()\n\n# Call the function\nplot_history(history)","metadata":{"_uuid":"ba4a9411-e46c-4c02-9316-9d9785b9642d","_cell_guid":"77fa03f7-fab3-4572-9347-82ceab67c0e1","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-03-13T15:54:14.057665Z","iopub.execute_input":"2025-03-13T15:54:14.057942Z","iopub.status.idle":"2025-03-13T15:54:14.474610Z","shell.execute_reply.started":"2025-03-13T15:54:14.057920Z","shell.execute_reply":"2025-03-13T15:54:14.473674Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Include the learning rate in the history object\nhistory.history['lr'] = [lr_schedule(step) for step in range(len(history.history['loss']))]\n\n# Plot the learning rate\nplt.figure(figsize=(6, 4))\nplt.plot(history.history['lr'], label='Learning Rate')\nplt.title('Learning Rate Schedule')\nplt.xlabel('Epochs')\nplt.ylabel('Learning Rate')\nplt.legend()\nplt.show()","metadata":{"_uuid":"bd55d31d-4779-40e5-afea-596d039ac289","_cell_guid":"40c6bb40-cd13-4387-82d1-28895c3eac28","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-03-13T15:59:54.627514Z","iopub.execute_input":"2025-03-13T15:59:54.627833Z","iopub.status.idle":"2025-03-13T15:59:54.898201Z","shell.execute_reply.started":"2025-03-13T15:59:54.627809Z","shell.execute_reply":"2025-03-13T15:59:54.897155Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.save('/kaggle/working/capsnet_model_lamb_v1.h5')","metadata":{"_uuid":"d7fb6e67-29e6-44df-aa73-5567dde769b0","_cell_guid":"ae8b6c04-9ee1-4182-8cd9-44e7f82ca7e6","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-03-13T16:00:08.374056Z","iopub.execute_input":"2025-03-13T16:00:08.374362Z","iopub.status.idle":"2025-03-13T16:00:08.517850Z","shell.execute_reply.started":"2025-03-13T16:00:08.374327Z","shell.execute_reply":"2025-03-13T16:00:08.516865Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install streamlit\n!pip install pyngrok","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-13T16:00:16.442959Z","iopub.execute_input":"2025-03-13T16:00:16.443248Z","iopub.status.idle":"2025-03-13T16:00:26.364570Z","shell.execute_reply.started":"2025-03-13T16:00:16.443225Z","shell.execute_reply":"2025-03-13T16:00:26.363545Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%writefile app.py\n\nimport streamlit as st\nimport numpy as np\nimport pydicom\nimport tensorflow as tf\nfrom PIL import Image\nfrom tensorflow.keras import layers, models, optimizers, regularizers, callbacks\nfrom tensorflow.keras.layers import LeakyReLU\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nimport h5py\nimport json\nimport logging\n\nimport tensorflow as tf\nfrom tensorflow.keras import layers, models, optimizers, regularizers, callbacks\nfrom tensorflow.keras.layers import LeakyReLU\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom sklearn.preprocessing import OneHotEncoder\nimport pandas as pd\nimport os\nimport logging\n\n# Suppress TensorFlow logging for cleaner output\nlogging.getLogger('tensorflow').setLevel(logging.ERROR)\n\n# Custom Squash Layer\n@tf.keras.utils.register_keras_serializable()\nclass Squash(layers.Layer):\n    def __init__(self, **kwargs):\n        super(Squash, self).__init__(**kwargs)\n\n    def call(self, inputs):\n        squared_norm = tf.reduce_sum(tf.square(inputs), axis=-1, keepdims=True)\n        scale = squared_norm / (1 + squared_norm)\n        result = (scale * inputs) / tf.sqrt(squared_norm + 1e-12)\n        return result\n\n    def compute_output_shape(self, input_shape):\n        return input_shape\n\n    def get_config(self):\n        config = super(Squash, self).get_config()\n        return config\n\n# Custom PrimaryCaps Layer (Updated to Use All Sublayers)\n@tf.keras.utils.register_keras_serializable()\nclass PrimaryCaps(layers.Layer):\n    def __init__(self, num_capsules, dim_capsule, kernel_size, strides, **kwargs):\n        super(PrimaryCaps, self).__init__(**kwargs)\n        self.num_capsules = num_capsules\n        self.dim_capsule = dim_capsule\n        self.kernel_size = kernel_size\n        self.strides = strides\n\n        # Define the Conv2D layer\n        self.conv = layers.Conv2D(\n            filters=self.num_capsules * self.dim_capsule,\n            kernel_size=self.kernel_size,\n            strides=self.strides,\n            padding='same',\n            activation=None,\n            kernel_initializer='glorot_normal',\n            kernel_regularizer=regularizers.l2(1e-3),\n            name='conv2d'  # Named to match potential saved weights\n        )\n        \n        # Define BatchNormalization and Activation layers\n        self.batch_norm = layers.BatchNormalization(name='batch_norm')\n        self.activation = layers.Activation('relu', name='relu')\n\n    def build(self, input_shape):\n        # Explicitly build sublayers to ensure parameters are registered\n        self.conv.build(input_shape)\n        conv_output_shape = self.conv.compute_output_shape(input_shape)\n        self.batch_norm.build(conv_output_shape)\n        self.activation.build(conv_output_shape)  # Activation doesn't have parameters but included for completeness\n        super(PrimaryCaps, self).build(input_shape)\n\n    def call(self, inputs, training=True):\n        x = self.conv(inputs)\n        x = self.batch_norm(x, training=training)  # Apply batch normalization\n        x = self.activation(x)                     # Apply ReLU activation\n        batch_size = tf.shape(x)[0]\n        spatial_dims = tf.shape(x)[1] * tf.shape(x)[2]\n        num_capsules = spatial_dims * self.num_capsules\n        x = tf.reshape(x, [batch_size, num_capsules, self.dim_capsule])\n        return Squash()(x)\n\n    def compute_output_shape(self, input_shape):\n        conv_output_shape = self.conv.compute_output_shape(input_shape)\n        spatial_dims = conv_output_shape[1] * conv_output_shape[2]\n        num_capsules = spatial_dims * self.num_capsules\n        return (conv_output_shape[0], num_capsules, self.dim_capsule)\n\n    def get_config(self):\n        config = super(PrimaryCaps, self).get_config()\n        config.update({\n            'num_capsules': self.num_capsules,\n            'dim_capsule': self.dim_capsule,\n            'kernel_size': self.kernel_size,\n            'strides': self.strides\n        })\n        return config\n\n@tf.keras.utils.register_keras_serializable()\nclass DigitCaps(layers.Layer):\n    def __init__(self, num_capsules, dim_capsule, routing_iters=3, **kwargs):\n        super(DigitCaps, self).__init__(**kwargs)\n        self.num_capsules = num_capsules\n        self.dim_capsule = dim_capsule\n        self.routing_iters = routing_iters\n        self.batch_norm = layers.BatchNormalization(name='batch_norm')\n\n    def build(self, input_shape):\n        self.num_input_capsules = input_shape[1]\n        self.dim_input_capsule = input_shape[2]\n        self.W = self.add_weight(\n            shape=[self.num_input_capsules, self.num_capsules, self.dim_input_capsule, self.dim_capsule],\n            initializer='glorot_normal',\n            trainable=True,\n            name='W'\n        )\n        # Explicitly build the batch_norm layer to ensure its weights are registered\n        self.batch_norm.build(input_shape=(None, self.num_capsules, self.dim_capsule))\n        super(DigitCaps, self).build(input_shape)\n\n    def call(self, inputs, training=True):\n        u_hat = tf.einsum('bik,ijkd->bijd', inputs, self.W)\n        return self.dynamic_routing(u_hat, training=training)\n\n    def dynamic_routing(self, u_hat, training=True):\n        b = tf.zeros(shape=[tf.shape(u_hat)[0], self.num_input_capsules, self.num_capsules])\n        for i in range(self.routing_iters):\n            c = tf.nn.softmax(b, axis=2)\n            c_expand = tf.expand_dims(c, axis=-1)\n            s = tf.reduce_sum(c_expand * u_hat, axis=1)\n            s = self.batch_norm(s, training=training)\n            v = Squash()(s)\n            if i < self.routing_iters - 1:\n                v_expand = tf.expand_dims(v, axis=1)\n                u_v_dot = tf.reduce_sum(u_hat * v_expand, axis=-1)\n                b += u_v_dot\n        return v\n\n    def compute_output_shape(self, input_shape):\n        return (input_shape[0], self.num_capsules, self.dim_capsule)\n\n    def get_config(self):\n        config = super(DigitCaps, self).get_config()\n        config.update({\n            'num_capsules': self.num_capsules,\n            'dim_capsule': self.dim_capsule,\n            'routing_iters': self.routing_iters\n        })\n        return config\n\n    def get_weights(self):\n        # Include batch_norm weights in the layer's weights\n        weights = super(DigitCaps, self).get_weights()\n        weights.extend(self.batch_norm.get_weights())\n        return weights\n\n    def set_weights(self, weights):\n        # Split weights between the main layer and batch_norm\n        main_weights = weights[:1]  # W\n        batch_norm_weights = weights[1:]  # beta, gamma, moving_mean, moving_variance\n        super(DigitCaps, self).set_weights(main_weights)\n        if batch_norm_weights:\n            self.batch_norm.set_weights(batch_norm_weights)\n\n@tf.keras.utils.register_keras_serializable()\nclass Decoder(layers.Layer):\n    def __init__(self, decoder_output_shape=(320, 320, 1), num_classes=3, dim_capsule=16, **kwargs):\n        super(Decoder, self).__init__(**kwargs)\n        self.decoder_output_shape = decoder_output_shape\n        self.num_classes = num_classes\n        self.dim_capsule = dim_capsule\n        self.decoder = None  # Initialize as None; build in the build method\n\n    def build(self, input_shape):\n        # Define the Sequential model in the build method to ensure weights are registered\n        self.decoder = models.Sequential([\n            layers.Flatten(name='flatten'),\n            layers.Dense(10 * 10 * 64, activation='relu', kernel_initializer='glorot_normal', kernel_regularizer=regularizers.l2(1e-5), name='dense'),\n            layers.BatchNormalization(name='batch_norm_1'),\n            layers.Reshape((10, 10, 64), name='reshape'),\n            layers.Conv2DTranspose(\n                filters=32,\n                kernel_size=(5, 5),\n                strides=(2, 2),\n                padding='same',\n                activation='relu',\n                kernel_initializer='glorot_normal',\n                kernel_regularizer=regularizers.l2(1e-5),\n                name='conv2d_transpose_1'\n            ),\n            layers.BatchNormalization(name='batch_norm_2'),\n            layers.Conv2DTranspose(\n                filters=16,\n                kernel_size=(5, 5),\n                strides=(2, 2),\n                padding='same',\n                activation='relu',\n                kernel_initializer='glorot_normal',\n                kernel_regularizer=regularizers.l2(1e-5),\n                name='conv2d_transpose_2'\n            ),\n            layers.BatchNormalization(name='batch_norm_3'),\n            layers.Conv2DTranspose(\n                filters=8,\n                kernel_size=(5, 5),\n                strides=(4, 4),\n                padding='same',\n                activation='relu',\n                kernel_initializer='glorot_normal',\n                kernel_regularizer=regularizers.l2(1e-5),\n                name='conv2d_transpose_3'\n            ),\n            layers.BatchNormalization(name='batch_norm_4'),\n            layers.Conv2DTranspose(\n                filters=1,\n                kernel_size=(5, 5),\n                strides=(2, 2),\n                padding='same',\n                activation='sigmoid',\n                kernel_initializer='glorot_normal',\n                kernel_regularizer=regularizers.l2(1e-5),\n                name='conv2d_transpose_4'\n            )\n        ], name='decoder_sequential')\n        # Explicitly build the Sequential model to register its weights\n        self.decoder.build(input_shape)\n        super(Decoder, self).build(input_shape)\n\n    def call(self, inputs):\n        return self.decoder(inputs)\n\n    def compute_output_shape(self, input_shape):\n        return (input_shape[0],) + tuple(self.decoder_output_shape)\n\n    def get_config(self):\n        config = super(Decoder, self).get_config()\n        config.update({\n            'decoder_output_shape': self.decoder_output_shape,\n            'num_classes': self.num_classes,\n            'dim_capsule': self.dim_capsule\n        })\n        return config\n\n    def get_weights(self):\n        # Include the weights of the Sequential model\n        if self.decoder is None:\n            return []\n        return self.decoder.get_weights()\n\n    def set_weights(self, weights):\n        # Set the weights of the Sequential model\n        if self.decoder is not None and weights:\n            self.decoder.set_weights(weights)\n\n# Custom MarginLoss\n@tf.keras.utils.register_keras_serializable()\nclass MarginLoss(tf.keras.losses.Loss):\n    def __init__(self, **kwargs):\n        super(MarginLoss, self).__init__(**kwargs)\n\n    def call(self, y_true, y_pred):\n        m_plus, m_minus, lambda_val = 0.9, 0.1, 0.5\n        L = (y_true * tf.square(tf.maximum(0., (m_plus - y_pred)))) + \\\n            (lambda_val * (1 - y_true) * tf.square(tf.maximum(0., (y_pred - m_minus))))\n        return tf.reduce_mean(tf.reduce_sum(L, axis=1))\n\n    def get_config(self):\n        config = super(MarginLoss, self).get_config()\n        return config\n\n# Custom CapsuleNormLayer\n@tf.keras.utils.register_keras_serializable()\nclass CapsuleNormLayer(layers.Layer):\n    def __init__(self, **kwargs):\n        super(CapsuleNormLayer, self).__init__(**kwargs)\n\n    def call(self, inputs):\n        return tf.norm(inputs, axis=-1)\n\n    def get_config(self):\n        config = super(CapsuleNormLayer, self).get_config()\n        return config\n\nfrom keras.layers import Lambda\n\ndef CapsNet(input_shape, num_classes, routing_iters=3):\n    inputs = layers.Input(shape=input_shape)\n\n    x = layers.Conv2D(\n        filters=266,\n        kernel_size=(4,4),\n        strides=(2, 2),\n        padding='same',\n        kernel_initializer='glorot_normal',\n        activation='leaky_relu',\n        name='conv1'\n    )(inputs)\n    \n    x = layers.BatchNormalization()(x)\n\n    y = layers.Conv2D(\n        filters=144,\n        kernel_size=(5,5),\n        strides=(2, 2),\n        padding='same',\n        kernel_initializer='glorot_normal',\n        activation='leaky_relu',\n        name='conv2'\n    )(x)\n    \n    y = layers.BatchNormalization()(y)\n\n    z = layers.Conv2D(\n        filters=1,\n        kernel_size=(6,6),\n        strides=(2, 2),\n        padding='same',\n        kernel_initializer='glorot_normal',\n        activation='relu',\n        name='conv3'\n    )(y)\n    \n    z= layers.BatchNormalization()(z)\n\n    primary_caps = PrimaryCaps(\n        num_capsules=8,   \n        dim_capsule=16,    \n        kernel_size=4,\n        strides=3,\n        name='primary_caps'\n    )(z)\n\n    digit_caps1 = DigitCaps(\n        num_capsules=num_classes,\n        dim_capsule=16,    \n        routing_iters=routing_iters,\n        name='digit_caps1'\n    )(primary_caps)\n\n    caps_norm = CapsuleNormLayer(name='caps_norm')(digit_caps1)\n    classification_output = layers.Softmax(name='classification_output')(caps_norm)\n \n\n    decoder_output = Decoder(\n        decoder_output_shape=input_shape,  \n        name='decoder_output'\n    )(digit_caps1)\n\n    model = models.Model(\n        inputs=inputs,\n        outputs=[classification_output,decoder_output],\n        name='CapsNet'\n    )\n    \n    return model\n\n\n   \n\ndef preprocess_dicom(image_array, dicom=None):\n    # Convert to float32 and handle NaN/Inf values\n    image = tf.convert_to_tensor(image_array, dtype=tf.float32)\n    image = tf.where(tf.math.is_nan(image) | tf.math.is_inf(image), 0.0, image)  # Replace NaN/inf with 0\n    \n    # Apply DICOM rescaling if metadata is provided\n    if dicom is not None:\n        if hasattr(dicom, 'RescaleSlope') and hasattr(dicom, 'RescaleIntercept'):\n            image = image * dicom.RescaleSlope + dicom.RescaleIntercept\n    \n    # Clip to a reasonable range (e.g., HU for CT, adjust as needed for your data)\n    image = tf.clip_by_value(image, -1000, 1000)\n    \n    # Normalize to [0, 1]\n    image = (image + 1000) / 2000  # Maps [-1000, 1000] to [0, 1]\n    \n    # Ensure the image has a channel dimension\n    if len(image.shape) == 2:  # Grayscale image [height, width]\n        image = tf.expand_dims(image, axis=-1)  # Add channel dimension: [height, width, 1]\n    elif len(image.shape) == 3:  # Image already has channels [height, width, channels]\n        if image.shape[-1] not in [1, 3]:  # Unexpected number of channels\n            raise ValueError(f\"Unexpected number of channels in image: {image.shape[-1]}. Expected 1 or 3.\")\n    else:\n        raise ValueError(f\"Unexpected image shape: {image.shape}. Expected 2D or 3D image.\")\n    \n    # Resize the image to the target size\n    new_size = tf.constant([320, 320])\n    image = tf.image.resize(image, new_size)\n    \n    return image\n\ndef predict(image, model):\n    if len(image.shape) == 3:\n        image = tf.expand_dims(image, axis=0)\n    predictions = model.predict(image)\n    if isinstance(predictions, list):\n        classification_output = predictions[0]\n        reconstruction_output = predictions[1]\n        return classification_output, reconstruction_output\n    return predictions, None\n\ndef get_predicted_label(classification_output, class_labels):\n    # Get the index of the class with the highest probability\n    predicted_class_idx = np.argmax(classification_output, axis=1)[0]\n    # Map the index to the corresponding label\n    predicted_label = class_labels[predicted_class_idx]\n    return predicted_label\n\nclass_labels = ['Normal', 'Mild', 'Severe']\n\n# Main Streamlit App\nst.title('Lumbar Spine Degeneration Classification')\n\n# Define model parameters\ninput_shape = (320, 320, 1)\nnum_classes = 3\nrouting_iters = 6\n\n\nmodel_path = \"/kaggle/working/capsnet_model_lamb_v1.h5\"\n\nst.write(\"Defining the model...\")\nmodel = CapsNet(input_shape=input_shape, num_classes=num_classes, routing_iters=routing_iters)\n\ntry:\n    model.load_weights(model_path)\n    st.success(\"Model weights loaded successfully using layer names!\")\nexcept Exception as e:\n    st.error(f\"Error loading model weights: {e}\")\n\n# Compile the model\nmodel.compile(\n    optimizer='adam',\n    loss=[MarginLoss(), 'mse'],\n    loss_weights=[1.0, 0.0005],\n    metrics=['accuracy']\n)\n\nuploaded_file = st.file_uploader(\"Upload a DICOM file\", type=[\"dcm\"])\n\nif uploaded_file is not None:\n    # Read and preprocess the DICOM file\n    dicom = pydicom.dcmread(uploaded_file)\n    image_array = dicom.pixel_array\n    preprocessed_image = preprocess_dicom(image_array, dicom)\n    \n    # Display the preprocessed image\n    #st.image(preprocessed_image.numpy(), caption='Preprocessed Image', use_container_width=True)\n    \n    # Make predictions\n    try:\n        classification_output, reconstruction_output = predict(preprocessed_image, model)\n        \n        # Get the predicted label\n        predicted_label = get_predicted_label(classification_output, class_labels)\n        \n        # Display the predicted label\n        st.write(\"Predicted Lumbar Spine Degeneration Level:\")\n        st.write(f\"**{predicted_label}**\")\n        \n        # Optionally, display the raw prediction probabilities for debugging\n        st.write(\"Prediction probabilities for each class (Normal, Mild, Severe):\")\n        st.write(classification_output)\n        \n    except Exception as e:\n        st.error(f\"Error during prediction: {e}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-13T16:25:23.043165Z","iopub.execute_input":"2025-03-13T16:25:23.043504Z","iopub.status.idle":"2025-03-13T16:25:23.052236Z","shell.execute_reply.started":"2025-03-13T16:25:23.043478Z","shell.execute_reply":"2025-03-13T16:25:23.051510Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!ls","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-13T16:25:23.390148Z","iopub.execute_input":"2025-03-13T16:25:23.390474Z","iopub.status.idle":"2025-03-13T16:25:23.605905Z","shell.execute_reply.started":"2025-03-13T16:25:23.390446Z","shell.execute_reply":"2025-03-13T16:25:23.604775Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from kaggle_secrets import UserSecretsClient\nuser_secrets = UserSecretsClient()\nsecret_value_0 = user_secrets.get_secret(\"ngrok\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-13T16:25:23.819029Z","iopub.execute_input":"2025-03-13T16:25:23.819330Z","iopub.status.idle":"2025-03-13T16:25:24.094860Z","shell.execute_reply.started":"2025-03-13T16:25:23.819303Z","shell.execute_reply":"2025-03-13T16:25:24.093855Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from pyngrok import ngrok\nngrok.set_auth_token(secret_value_0)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-13T16:25:24.334201Z","iopub.execute_input":"2025-03-13T16:25:24.334527Z","iopub.status.idle":"2025-03-13T16:25:24.370032Z","shell.execute_reply.started":"2025-03-13T16:25:24.334500Z","shell.execute_reply":"2025-03-13T16:25:24.369325Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport subprocess\n\nPORT = 8501\nos.system(f\"streamlit run app.py --server.port {PORT} &\")\npublic_url = ngrok.connect(PORT).public_url\nprint(f\"Streamlit App is running at: {public_url}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-13T16:25:26.697336Z","iopub.execute_input":"2025-03-13T16:25:26.697673Z","iopub.status.idle":"2025-03-13T16:25:26.926657Z","shell.execute_reply.started":"2025-03-13T16:25:26.697648Z","shell.execute_reply":"2025-03-13T16:25:26.925025Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import h5py\n\nmodel_path = \"/kaggle/working/capsnet_model_v9.h5\"\nwith h5py.File(model_path, 'r') as f:\n    print(list(f.keys()))","metadata":{"_uuid":"e831ab47-09a4-4749-8a85-5bbbf39ce130","_cell_guid":"0ddb2ff9-2a75-45be-aa6b-30f5773851ee","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-03-10T15:59:02.191364Z","iopub.execute_input":"2025-03-10T15:59:02.191735Z","iopub.status.idle":"2025-03-10T15:59:02.198355Z","shell.execute_reply.started":"2025-03-10T15:59:02.191709Z","shell.execute_reply":"2025-03-10T15:59:02.197628Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import h5py\n\nmodel_path = \"/kaggle/working/capsnet_model_v9.h5\"\nwith h5py.File(model_path, 'r') as f:\n    print(\"Detailed weights in the saved model:\")\n    def print_weights(name, obj):\n        if isinstance(obj, h5py.Dataset):\n            print(f\"  Weight: {name}\")\n        elif isinstance(obj, h5py.Group):\n            print(f\"Layer/Group: {name}\")\n    f['model_weights'].visititems(print_weights)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-10T15:59:10.780122Z","iopub.execute_input":"2025-03-10T15:59:10.780446Z","iopub.status.idle":"2025-03-10T15:59:10.817058Z","shell.execute_reply.started":"2025-03-10T15:59:10.780416Z","shell.execute_reply":"2025-03-10T15:59:10.816237Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}