{"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":30733,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Import Libraries","metadata":{}},{"cell_type":"code","source":"import os\nimport sys\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nfrom glob import glob\nfrom tqdm import tqdm\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.model_selection import KFold\nimport polars as pl\npl.Config.set_tbl_rows(40)\npl.Config.set_fmt_str_lengths(n=40)\npl.Config.set_tbl_cols(100)\nimport seaborn as sns\nimport pydicom\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-06-22T14:08:15.269874Z","iopub.execute_input":"2024-06-22T14:08:15.270434Z","iopub.status.idle":"2024-06-22T14:08:22.733708Z","shell.execute_reply.started":"2024-06-22T14:08:15.270407Z","shell.execute_reply":"2024-06-22T14:08:22.732757Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dir = \"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification\"","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:22.735417Z","iopub.execute_input":"2024-06-22T14:08:22.736241Z","iopub.status.idle":"2024-06-22T14:08:22.740579Z","shell.execute_reply.started":"2024-06-22T14:08:22.736204Z","shell.execute_reply":"2024-06-22T14:08:22.739769Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\ntrain = pl.read_csv(os.path.join(dir, \"train.csv\"))\ntrain_labels = pl.read_csv(os.path.join(dir, \"train_label_coordinates.csv\"))\ntrain_des = pl.read_csv(os.path.join(dir, \"train_series_descriptions.csv\"))\ntest_des = pl.read_csv(os.path.join(dir, \"test_series_descriptions.csv\"))\nsample_sub = pl.read_csv(os.path.join(dir, \"sample_submission.csv\"))","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:22.742854Z","iopub.execute_input":"2024-06-22T14:08:22.743203Z","iopub.status.idle":"2024-06-22T14:08:22.926407Z","shell.execute_reply.started":"2024-06-22T14:08:22.743169Z","shell.execute_reply":"2024-06-22T14:08:22.925594Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## データの確認","metadata":{}},{"cell_type":"code","source":"train.head(3)","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:22.928463Z","iopub.execute_input":"2024-06-22T14:08:22.928771Z","iopub.status.idle":"2024-06-22T14:08:22.951279Z","shell.execute_reply.started":"2024-06-22T14:08:22.928744Z","shell.execute_reply":"2024-06-22T14:08:22.950293Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label_columns = train.columns[1:]\n\n# ラベルの分布を計算\nlabel_distribution = train.select(label_columns).melt().groupby('variable', 'value').count().sort('variable')\n\n# 分布を表示\nprint(label_distribution)","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:22.952395Z","iopub.execute_input":"2024-06-22T14:08:22.952675Z","iopub.status.idle":"2024-06-22T14:08:23.017881Z","shell.execute_reply.started":"2024-06-22T14:08:22.952652Z","shell.execute_reply":"2024-06-22T14:08:23.016961Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 症状のラベルと翻訳\n\n#### spinal_canal_stenosis（脊柱管狭窄症）\n- **説明**: 脊柱管が狭くなり、神経が圧迫される状態\n\n#### neural_foraminal_narrowing（神経孔狭窄）\n- **説明**: 神経孔が狭くなり、神経が圧迫される状態\n- **評価**: 左右の神経孔に対してそれぞれ評価される（左側、右側）\n\n#### subarticular_stenosis（関節下狭窄症）\n- **説明**: 関節下の空間が狭くなり、神経が圧迫される状態\n- **評価**: 左右の関節下に対してそれぞれ評価される（左側、右側）\n\n### レベル\n- **説明**: 各症状には、対応する椎間（例えば、l1_l2, l2_l3など）のレベルがあります。これらは腰椎の特定の部位を示します。\n\n### 例\n- **spinal_canal_stenosis_l1_l2**: 腰椎第1-2間の脊柱管狭窄症\n- **neural_foraminal_narrowing_left_l3_l4**: 腰椎第3-4間の左側神経孔狭窄\n- **subarticular_stenosis_right_l5_s1**: 腰椎第5仙骨第1間の右側関節下狭窄症","metadata":{}},{"cell_type":"markdown","source":"### train_labelについて","metadata":{}},{"cell_type":"code","source":"# ラベルの分布をpandasデータフレームに変換（matplotlibでのプロット用）\nlabel_distribution_pd = label_distribution.to_pandas()\n\n# プロットのためのデータを整形\nlabel_distribution_pd.columns = ['Label', 'Category', 'Count']\n\n# カテゴリ列を文字列に変換\nlabel_distribution_pd['Category'] = label_distribution_pd['Category'].astype(str)\n\n# 可視化\nplt.figure(figsize=(12, 8))\nfor label in label_columns:\n    subset = label_distribution_pd[label_distribution_pd['Label'] == label]\n    plt.bar(subset['Category'], subset['Count'], label=label)\n\nplt.xlabel('Category')\nplt.ylabel('Count')\nplt.title('Distribution of Labels')\nplt.legend(loc='upper right')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:23.018971Z","iopub.execute_input":"2024-06-22T14:08:23.019225Z","iopub.status.idle":"2024-06-22T14:08:23.726514Z","shell.execute_reply.started":"2024-06-22T14:08:23.019202Z","shell.execute_reply":"2024-06-22T14:08:23.725627Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### train_labelについて","metadata":{}},{"cell_type":"markdown","source":"### データラベルの解説\n\n#### study_id\n- **説明**: 各MRI検査の一意の識別子。各検査は複数の画像シリーズを含むことがあります。\n\n#### series_id\n- **説明**: 各画像シリーズの一意の識別子。各シリーズは複数の3D画像を含むことがあります。\n\n#### instance_number\n- **説明**: 3Dスタック内の各画像の順序番号。\n\n#### condition\n- **説明**: 検査対象の病状を示すラベル。以下の病状が含まれます：\n  - **spinal_canal_stenosis**（脊柱管狭窄症）\n  - **neural_foraminal_narrowing**（神経孔狭窄）\n  - **subarticular_stenosis**（関節下狭窄症）\n\n#### level\n- **説明**: 病状が発生している椎骨のレベル。例：l1_l2, l2_l3など。\n\n#### x\n- **説明**: ラベルが定義された領域の中心のx座標。\n\n#### y\n- **説明**: ラベルが定義された領域の中心のy座標。","metadata":{}},{"cell_type":"code","source":"train_labels.head(3)","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:23.727575Z","iopub.execute_input":"2024-06-22T14:08:23.727854Z","iopub.status.idle":"2024-06-22T14:08:23.736053Z","shell.execute_reply.started":"2024-06-22T14:08:23.727828Z","shell.execute_reply":"2024-06-22T14:08:23.735045Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 先頭3行を保存\n# train_labels.head(3).write_csv('train_labels_head3.csv')","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:23.737259Z","iopub.execute_input":"2024-06-22T14:08:23.737517Z","iopub.status.idle":"2024-06-22T14:08:23.741821Z","shell.execute_reply.started":"2024-06-22T14:08:23.737495Z","shell.execute_reply":"2024-06-22T14:08:23.740946Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 'condition'列の分布を計算\ncondition_distribution = train_labels.group_by('condition').agg(pl.count('condition').alias('count')).sort('count', descending=True)\n\n# データフレームを表示\nprint(condition_distribution)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:23.743142Z","iopub.execute_input":"2024-06-22T14:08:23.743396Z","iopub.status.idle":"2024-06-22T14:08:23.760102Z","shell.execute_reply.started":"2024-06-22T14:08:23.743375Z","shell.execute_reply":"2024-06-22T14:08:23.759275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 条件の分布をpandasデータフレームに変換（matplotlibでのプロット用）\ncondition_distribution_pd = condition_distribution.to_pandas()\n\n# 可視化\nplt.figure(figsize=(10, 6))\nplt.bar(condition_distribution_pd['condition'], condition_distribution_pd['count'], color='skyblue')\n\nplt.xlabel('Condition')\nplt.ylabel('Count')\nplt.title('Distribution of Conditions')\nplt.xticks(rotation=45, ha='right')\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:23.763806Z","iopub.execute_input":"2024-06-22T14:08:23.764078Z","iopub.status.idle":"2024-06-22T14:08:23.973086Z","shell.execute_reply.started":"2024-06-22T14:08:23.764055Z","shell.execute_reply":"2024-06-22T14:08:23.972217Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### train_desについて(データラベルの解説)\n\n#### study_id\n- **説明**: 各MRI検査の一意の識別子。各検査は複数の画像シリーズを含むことがあります。\n\n#### series_id\n- **説明**: 各画像シリーズの一意の識別子。各シリーズは複数の3D画像を含むことがあります。\n\n#### series_description\n- **説明**: 画像シリーズの説明。画像の取得方法や視点に関する情報が含まれます。以下は例です：\n  - **Sagittal T2/STIR**: 矢状断面のT2/STIRイメージ。T2強調画像およびSTIR（短時間反転回復）画像。\n  - **Sagittal T1**: 矢状断面のT1強調画像。\n  - **Axial T2**: 横断面のT2強調画像。\n\nこのデータセットは、MRIスキャンの異なるシリーズについての情報を提供し、各スキャンがどのように取得されたか、どの断面であるかを示しています。これにより、各画像シリーズが異なる視点や撮影条件で撮影されていることがわかります。","metadata":{}},{"cell_type":"code","source":"train_des.head(3)","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:23.974037Z","iopub.execute_input":"2024-06-22T14:08:23.974275Z","iopub.status.idle":"2024-06-22T14:08:23.980717Z","shell.execute_reply.started":"2024-06-22T14:08:23.974254Z","shell.execute_reply":"2024-06-22T14:08:23.979862Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# series_descriptionの分布を計算\nseries_description_distribution = train_des.group_by('series_description').agg(pl.count('series_description').alias('count')).sort('count', descending=True)\n\n# series_description_distributionを可視化\nprint(series_description_distribution)","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:23.981942Z","iopub.execute_input":"2024-06-22T14:08:23.982242Z","iopub.status.idle":"2024-06-22T14:08:23.990822Z","shell.execute_reply.started":"2024-06-22T14:08:23.982216Z","shell.execute_reply":"2024-06-22T14:08:23.989860Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sns.countplot(x='series_description', data=train_des.to_pandas())\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:23.991822Z","iopub.execute_input":"2024-06-22T14:08:23.992308Z","iopub.status.idle":"2024-06-22T14:08:24.130565Z","shell.execute_reply.started":"2024-06-22T14:08:23.992285Z","shell.execute_reply":"2024-06-22T14:08:24.129685Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### study_idの偏り確認","metadata":{}},{"cell_type":"code","source":"sns.countplot(x='study_id', data=train_des.to_pandas())\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:24.131843Z","iopub.execute_input":"2024-06-22T14:08:24.132191Z","iopub.status.idle":"2024-06-22T14:08:40.007679Z","shell.execute_reply.started":"2024-06-22T14:08:24.132161Z","shell.execute_reply":"2024-06-22T14:08:40.006904Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Imageの読み込み確認","metadata":{}},{"cell_type":"code","source":"# train_labelsの先頭20行を対象に画像を読み込むみ読み込む画像確認\ntrain_labels.head(25)","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:40.008710Z","iopub.execute_input":"2024-06-22T14:08:40.008992Z","iopub.status.idle":"2024-06-22T14:08:40.021735Z","shell.execute_reply.started":"2024-06-22T14:08:40.008967Z","shell.execute_reply":"2024-06-22T14:08:40.020720Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"study_id = train_labels['study_id'][0]\nseries_id = train_labels['series_id'][0]\ninstance_number = train_labels['instance_number'][0]","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:40.023114Z","iopub.execute_input":"2024-06-22T14:08:40.023736Z","iopub.status.idle":"2024-06-22T14:08:40.028733Z","shell.execute_reply.started":"2024-06-22T14:08:40.023703Z","shell.execute_reply":"2024-06-22T14:08:40.027839Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### DICOM（.dcm）データの解説\n\nDICOM（Digital Imaging and Communications in Medicine）は、医療画像の保存、交換、および表示のための標準フォーマットです。DICOMファイルの拡張子は通常「.dcm」であり、画像データと関連するメタデータを含んでいます。\n\n#### 1. ファイルメタ情報（File Meta Information）\n- **(0002, 0001) File Meta Information Version**: ファイルメタ情報のバージョン。\n- **(0002, 0002) Media Storage SOP Class UID**: 保存されるSOPクラスのUID。ここでは「Enhanced MR Image Storage」（拡張MR画像保存）を示します。\n- **(0002, 0003) Media Storage SOP Instance UID**: 保存されるSOPインスタンスのUID。\n- **(0002, 0010) Transfer Syntax UID**: 転送シンタックスのUID。ここでは「RLE Lossless」（可逆圧縮）を示します。\n- **(0002, 0012) Implementation Class UID**: 実装クラスのUID。\n- **(0002, 0013) Implementation Version Name**: 実装バージョン名。ここでは「PYDICOM 2.4.2」。\n\n#### 2. 画像情報（Image Information）\n- **(0008, 0018) SOP Instance UID**: この特定の画像のUID。\n- **(0008, 0023) Content Date**: 画像の内容が作成された日付。\n- **(0008, 0033) Content Time**: 画像の内容が作成された時刻。\n- **(0008, 103e) Series Description**: シリーズの説明。ここでは「T2」と記載されています。\n- **(0018, 0050) Slice Thickness**: 画像スライスの厚さ（ミリメートル単位）。\n- **(0018, 0088) Spacing Between Slices**: 連続するスライス間のスペース（ミリメートル単位）。\n- **(0018, 5100) Patient Position**: 患者のポジション。ここでは「HFS」（Head First Supine）を示します。\n- **(0020, 0013) Instance Number**: 画像スタック内のインスタンス番号。\n- **(0020, 0032) Image Position (Patient)**: 患者座標系における画像の位置。\n- **(0020, 0037) Image Orientation (Patient)**: 患者座標系における画像の向き。\n- **(0020, 1041) Slice Location**: スライスの位置。\n- **(0028, 0002) Samples per Pixel**: 各ピクセルのサンプル数。ここでは1を示します。\n- **(0028, 0004) Photometric Interpretation**: 画像のフォトメトリック解釈。ここでは「MONOCHROME2」（白黒画像）を示します。\n- **(0028, 0010) Rows**: 画像の行数。\n- **(0028, 0011) Columns**: 画像の列数。\n- **(0028, 0030) Pixel Spacing**: ピクセル間の物理的な距離（ミリメートル単位）。\n- **(0028, 0100) Bits Allocated**: 各ピクセルに割り当てられたビット数。\n- **(0028, 0101) Bits Stored**: 各ピクセルに格納されているビット数。\n- **(0028, 0102) High Bit**: 各ピクセルの最高位ビット。\n- **(0028, 0103) Pixel Representation**: ピクセルデータの表現方法。0は符号なし整数を示します。\n- **(0028, 1050) Window Center**: ウィンドウの中心値（ウィンドウレベル）。\n- **(0028, 1051) Window Width**: ウィンドウの幅。\n- **(7fe0, 0010) Pixel Data**: 実際の画像ピクセルデータ。\n\n#### 3. 患者情報（Patient Information）\n- **(0010, 0020) Patient ID**: 患者の一意の識別子。\n\n#### 4. 検査情報（Study Information）\n- **(0020, 000d) Study Instance UID**: 検査の一意の識別子。\n\n#### 5. シリーズ情報（Series Information）\n- **(0020, 000e) Series Instance UID**: シリーズの一意の識別子。\n- **(0020, 0052) Frame of Reference UID**: 参照フレームのUID。\n","metadata":{}},{"cell_type":"code","source":"dicom_data = pydicom.dcmread(f\"{dir}/train_images/{study_id}/{series_id}/{instance_number}.dcm\")\n\ndicom_data","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:40.030033Z","iopub.execute_input":"2024-06-22T14:08:40.030487Z","iopub.status.idle":"2024-06-22T14:08:40.050200Z","shell.execute_reply.started":"2024-06-22T14:08:40.030451Z","shell.execute_reply":"2024-06-22T14:08:40.049315Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# DICOM画像データを取得\nimage_data = dicom_data.pixel_array\n\n\n# プロットする座標を指定\nx = train_labels[\"x\"][0]\ny = train_labels[\"y\"][0]\n\n# 画像をプロット\nfig, axes = plt.subplots(1, 2, figsize=(15, 7))\n\n# オリジナル画像\naxes[0].imshow(image_data, cmap=plt.cm.gray)\naxes[0].set_title('Original DICOM Image')\naxes[0].set_xlabel('X Axis')\naxes[0].set_ylabel('Y Axis')\n\n# マークされた画像\naxes[1].imshow(image_data, cmap=plt.cm.gray)\naxes[1].scatter([x], [y], c='red', s=100)  # 赤色の点をプロット\naxes[1].set_title('DICOM Image with Marked Point')\naxes[1].set_xlabel('X Axis')\naxes[1].set_ylabel('Y Axis')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:40.051278Z","iopub.execute_input":"2024-06-22T14:08:40.051549Z","iopub.status.idle":"2024-06-22T14:08:40.745349Z","shell.execute_reply.started":"2024-06-22T14:08:40.051527Z","shell.execute_reply":"2024-06-22T14:08:40.744518Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# DICOM画像データを取得\nimage_data = dicom_data.pixel_array\n# 最初の4行のデータを抽出\nsubset_data = train_labels[:4]\n\n# DICOM画像データを取得\nimage_data = dicom_data.pixel_array\n\n# 画像をプロット\nfig, ax = plt.subplots(figsize=(10, 10))\n\n# オリジナル画像\nax.imshow(image_data, cmap=plt.cm.gray)\n\n# 複数のポイントをプロット\nfor row in subset_data.iter_rows(named=True):\n    x = row['x']\n    y = row['y']\n    label = f\"{row['condition']} {row['level']}\"\n    ax.scatter(x, y, c='red', s=100)  # 赤色の点をプロット\n    ax.text(x, y, label, color='white', fontsize=12, ha='right')\n\nax.set_title('DICOM Image with Marked Points')\nax.set_xlabel('X Axis')\nax.set_ylabel('Y Axis')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:40.746396Z","iopub.execute_input":"2024-06-22T14:08:40.746668Z","iopub.status.idle":"2024-06-22T14:08:41.348845Z","shell.execute_reply.started":"2024-06-22T14:08:40.746643Z","shell.execute_reply":"2024-06-22T14:08:41.347954Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 別画像も確認","metadata":{}},{"cell_type":"code","source":"import math\n# データの読み込み\ntrain_labels = train_labels[:25]\n\n# DICOM画像のディレクトリを指定\ndicom_dir = '/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_images'\n\n\n# ユニークなDICOMファイル情報を抽出\nunique_files = train_labels.select(['study_id', 'series_id', 'instance_number']).unique()\n\n# 画像を4列に並べる\nnum_cols = 4\nnum_rows = math.ceil(len(unique_files) / num_cols)\n\n# 全体のプロットを設定\nfig, axs = plt.subplots(num_rows, num_cols, figsize=(20, num_rows * 5))\naxs = axs.flatten()\n\n# 各DICOM画像に対してプロット\nfor idx, row in enumerate(unique_files.iter_rows(named=True)):\n    study_id = row['study_id']\n    series_id = row['series_id']\n    instance_number = row['instance_number']\n\n    # DICOMファイルのパスを生成\n    dicom_file_path = f\"{dicom_dir}/{study_id}/{series_id}/{instance_number}.dcm\"\n\n    # DICOMファイルを読み込む\n    dicom_data = pydicom.dcmread(dicom_file_path)\n\n    # DICOM画像データを取得\n    image_data = dicom_data.pixel_array\n\n    # 該当するラベルデータをフィルタリング\n    filtered_data = train_labels.filter(\n        (pl.col('study_id') == study_id) & \n        (pl.col('series_id') == series_id) & \n        (pl.col('instance_number') == instance_number)\n    )\n\n    # サブプロットに画像を表示\n    ax = axs[idx]\n    ax.imshow(image_data, cmap=plt.cm.gray)\n\n    # 各ポイントをプロット\n    for label_row in filtered_data.iter_rows(named=True):\n        x = label_row['x']\n        y = label_row['y']\n        condition = label_row['condition']\n        level = label_row['level']\n        label = f\"{condition} {level}\"\n        ax.scatter(x, y, c='red', s=100)  # 赤色の点をプロット\n        ax.text(x, y, label, color='white', fontsize=8, ha='right')\n\n    ax.set_title(f'Study: {study_id}, Series: {series_id}, Instance: {instance_number}')\n    ax.set_xlabel('X Axis')\n    ax.set_ylabel('Y Axis')\n\n# 空のサブプロットを非表示にする\nfor ax in axs[len(unique_files):]:\n    ax.axis('off')\n\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:41.350182Z","iopub.execute_input":"2024-06-22T14:08:41.350554Z","iopub.status.idle":"2024-06-22T14:08:45.444011Z","shell.execute_reply.started":"2024-06-22T14:08:41.350520Z","shell.execute_reply":"2024-06-22T14:08:45.442981Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 提出用のデータ確認","metadata":{}},{"cell_type":"code","source":"# sample_subの先頭3行を表示\n# sample_sub.head(3)\nsample_sub.shape","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:45.445212Z","iopub.execute_input":"2024-06-22T14:08:45.445510Z","iopub.status.idle":"2024-06-22T14:08:45.451060Z","shell.execute_reply.started":"2024-06-22T14:08:45.445484Z","shell.execute_reply":"2024-06-22T14:08:45.450126Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 各カラムの説明\n\n1. **normal_mild**\n   - **説明**: 症状が軽度であることを示すカラムです。通常、症状がないか、非常に軽度の状態を示します。\n   - **例**: 軽い痛み、僅かな異常など。\n\n2. **moderate**\n   - **説明**: 症状が中等度であることを示すカラムです。症状が明らかに存在し、日常生活にある程度の支障をきたす状態を示します。\n   - **例**: 中等度の痛み、明確な異常など。\n\n3. **severe**\n   - **説明**: 症状が重度であることを示すカラムです。症状が非常に強く、日常生活に重大な支障をきたす状態を示します。\n   - **例**: 激しい痛み、大きな異常など。\n\n","metadata":{}},{"cell_type":"code","source":"sample_sub[\"row_id\"][0]","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:45.452228Z","iopub.execute_input":"2024-06-22T14:08:45.452505Z","iopub.status.idle":"2024-06-22T14:08:45.459727Z","shell.execute_reply.started":"2024-06-22T14:08:45.452482Z","shell.execute_reply":"2024-06-22T14:08:45.458847Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### IDの構成要素\n\n1. **Study ID (44036939)**\n   - **説明**: `44036939`は、特定のMRI検査（スタディ）の一意の識別子です。このIDは、複数の画像シリーズやスライスを含む一連の検査を指します。\n\n2. **Side (left)**\n   - **説明**: `left`は、病変や観察対象が身体の左側にあることを示しています。一般的に、MRI検査では左右の情報が重要です。\n\n3. **Condition (neural_foraminal_narrowing)**\n   - **説明**: `neural_foraminal_narrowing`は、神経孔狭窄を示しています。これは神経が脊柱から出る部分が狭くなっている状態を指し、神経圧迫による痛みや痺れが生じることがあります。\n\n4. **Level (l1_l2)**\n   - **説明**: `l1_l2`は、狭窄が発生している脊椎の特定の部位を示しています。ここでは、腰椎の第1腰椎（L1）と第2腰椎（L2）の間を指します。","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import random","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:12:11.664642Z","iopub.execute_input":"2024-06-22T14:12:11.665324Z","iopub.status.idle":"2024-06-22T14:12:11.669093Z","shell.execute_reply.started":"2024-06-22T14:12:11.665290Z","shell.execute_reply":"2024-06-22T14:12:11.668227Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"NOT_DEBUG = True # True -> run naormally, False -> debug mode, with lesser computing cost\n\nOUTPUT_DIR = f'rsna24-results'\ndevice = 'cuda:0' if torch.cuda.is_available() else 'cpu'\nN_WORKERS = os.cpu_count() \nUSE_AMP = True # can change True if using T4 or newer than Ampere\nSEED = 8620\n\nIMG_SIZE = [512, 512]\nIN_CHANS = 30\nN_LABELS = 25\nN_CLASSES = 3 * N_LABELS\n\nAUG_PROB = 0.75\n\nN_FOLDS = 5 if NOT_DEBUG else 2\nEPOCHS = 20 if NOT_DEBUG else 2\nMODEL_NAME = \"tf_efficientnet_b3.ns_jft_in1k\" if NOT_DEBUG else \"tf_efficientnet_b0.ns_jft_in1k\"\n\nGRAD_ACC = 2\nTGT_BATCH_SIZE = 32\nBATCH_SIZE = TGT_BATCH_SIZE // GRAD_ACC\nMAX_GRAD_NORM = None\nEARLY_STOPPING_EPOCH = 3\n\nLR = 2e-4 * TGT_BATCH_SIZE / 32\nWD = 1e-2\nAUG = True","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:12:12.362597Z","iopub.execute_input":"2024-06-22T14:12:12.363011Z","iopub.status.idle":"2024-06-22T14:12:12.370309Z","shell.execute_reply.started":"2024-06-22T14:12:12.362977Z","shell.execute_reply":"2024-06-22T14:12:12.369361Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def set_random_seed(seed: int = 8620, deterministic: bool = False):\n    \"\"\"Set seeds\"\"\"\n    random.seed(seed)\n    np.random.seed(seed)\n    os.environ[\"PYTHONHASHSEED\"] = str(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)  # type: ignore\n    torch.backends.cudnn.benchmark = True\n    torch.backends.cudnn.deterministic = deterministic  # type: ignore\n\nset_random_seed(SEED)","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:12:12.588041Z","iopub.execute_input":"2024-06-22T14:12:12.588681Z","iopub.status.idle":"2024-06-22T14:12:12.596547Z","shell.execute_reply.started":"2024-06-22T14:12:12.588656Z","shell.execute_reply":"2024-06-22T14:12:12.595580Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def set_random_seed(seed: int = 8620, deterministic: bool = False):\n    \"\"\"Set seeds\"\"\"\n    random.seed(seed)\n    np.random.seed(seed)\n    os.environ[\"PYTHONHASHSEED\"] = str(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)  # type: ignore\n    torch.backends.cudnn.benchmark = True\n    torch.backends.cudnn.deterministic = deterministic  # type: ignore\n\nset_random_seed(SEED)","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:12:42.567442Z","iopub.execute_input":"2024-06-22T14:12:42.567803Z","iopub.status.idle":"2024-06-22T14:12:42.575250Z","shell.execute_reply.started":"2024-06-22T14:12:42.567774Z","shell.execute_reply":"2024-06-22T14:12:42.574278Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 前処理","metadata":{}},{"cell_type":"markdown","source":"## trainデータの欠損値除去","metadata":{}},{"cell_type":"code","source":"missing_values = train.null_count()\n\n# 結果を表示\nprint(\"Missing values in each column:\")\nprint(missing_values)","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:08:45.460983Z","iopub.execute_input":"2024-06-22T14:08:45.461306Z","iopub.status.idle":"2024-06-22T14:08:45.468113Z","shell.execute_reply.started":"2024-06-22T14:08:45.461279Z","shell.execute_reply":"2024-06-22T14:08:45.467147Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = train.fill_null(-100)","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:15:19.614329Z","iopub.execute_input":"2024-06-22T14:15:19.614995Z","iopub.status.idle":"2024-06-22T14:15:19.621363Z","shell.execute_reply.started":"2024-06-22T14:15:19.614964Z","shell.execute_reply":"2024-06-22T14:15:19.620393Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# サンプルデータフレームの作成\ndata = {\n    \"study_id\": [123456, 789012],\n    \"spinal_canal_stenosis_l1_l2\": [\"Normal/Mild\", \"Moderate\"],\n    \"spinal_canal_stenosis_l2_l3\": [\"Severe\", \"Normal/Mild\"],\n    # 他のラベル列も追加する\n}\n\n# ラベルをIDに置換する辞書\nlabel2id = {'Normal/Mild': 0, 'Moderate': 1, 'Severe': 2}\n\n# ラベルをIDに置換する関数\ndef replace_labels(column, label2id):\n    return column.apply(lambda x: label2id.get(x, x))\n\n# 各列に対してラベルを置換\nfor col in train.columns[1:]:  # 最初の列は 'study_id' なので除外\n    train = train.with_columns(replace_labels(pl.col(col), label2id).alias(col))\n\n# データフレームの内容を確認\nprint(train)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-22T14:22:53.612350Z","iopub.execute_input":"2024-06-22T14:22:53.612711Z","iopub.status.idle":"2024-06-22T14:22:53.673961Z","shell.execute_reply.started":"2024-06-22T14:22:53.612682Z","shell.execute_reply":"2024-06-22T14:22:53.673159Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}