{
  "id": 539494,
  "title": "27th Place solution: Algorithm vs Memmory or Transformers is all you need, 0.39/0.44",
  "url": "/competitions/rsna-2024-lumbar-spine-degenerative-classification/discussion/539494",
  "author_name": "Ángel Jacinto Sánchez Ruiz",
  "post_date": "2024-10-09T07:32:19.746000",
  "votes": 12,
  "comment_count": 29,
  "views": 0,
  "content": "<p>Thank you so much to everyone, especially to organizers and people who shared insights. Has been a long and stressful but enjoyable experience. There is a lot to comment and explain, but at the moment  a summary accross the full process.</p>\n<p><strong>Starting point:</strong></p>\n<p><a href=\"https://www.kaggle.com/code/abhinavsuri/anatomy-image-visualization-overview-rsna-raids\" target=\"_blank\">https://www.kaggle.com/code/abhinavsuri/anatomy-image-visualization-overview-rsna-raids</a></p>\n<p>This notebook introduced me perfectly to the problem and gave me the fundamentals of my approach since first contact. Often professionals base their diagnosis on 2D Sagittal T1 analysis for foraminal, 2D Axial T2 analysis for subarticular and 2D Sagittal T2 and Axial T2 analysis for spinal.</p>\n<p>The main problem is that slices doesn't match perfectly between them, at least without metadata. So I've decided to use a flexible architecture to handle them, Transformers.</p>\n<p><strong>2D UNet for ROI localization in images:</strong></p>\n<p><a href=\"https://www.kaggle.com/code/sacuscreed/sagittal-t1-sagittal-level-segmentation\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/sagittal-t1-sagittal-level-segmentation</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/sagittal-t2-sagittal-level-segmentation\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/sagittal-t2-sagittal-level-segmentation</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/axial-t2-axial-side-segmentation\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/axial-t2-axial-side-segmentation</a></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F6a41878578ada30eaeec0096cdfcab49%2Fsagittal_T1_levels.png?generation=1728465530762952&amp;alt=media\" alt=\"Predicted and True levels\"></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2Fc226ff687bf8f99cd3a4b21ec81cfdd9%2Fsagittal_T2_levels.png?generation=1728465554068790&amp;alt=media\" alt=\"Predicted and True levels\"></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F3b7f8383acbf6c293271b0816cf38a6c%2FAxial_T2_sides.png?generation=1728465338817627&amp;alt=media\" alt=\"Predicted and True sides\"></p>\n<p>Those coordinates together allowed to point backbone slices in Sagittal T1, spine slices in Sagittal T2 and to assign levels to Axial T2 slices. Special thanks to <a href=\"https://www.kaggle.com/hengck23\" target=\"_blank\">@hengck23</a> for <a href=\"https://www.kaggle.com/code/hengck23/2d-to-3d-projection-for-dicom\" target=\"_blank\">2D to 3D proejection for DICOM</a></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F5ef923d887223d67aaf5e47ea5f48c0c%2Faxial_sagittal_correspondence.png?generation=1728464895653686&amp;alt=media\" alt=\"\"></p>\n<p>Is important to mention that I've only used competition data. By data processing I've been able to impute coordinates to slices that hasn't been labeled. All slices between left and right labels for forminal, all neighbor slices in a range of D//5 for spinal and neighbor slices for subarticular. Increasing considerably the amount of data available. I've also duplicated Axial T2 slices by flipping images and coordinates properly.</p>\n<p><strong>CNN for ROI localization in crops:</strong></p>\n<p>At first, I started by feeding Transformer \"full-slice sandwiches\" of the corresponding level or side.</p>\n<p><a href=\"https://www.kaggle.com/sergiosaharovskiy\" target=\"_blank\">@sergiosaharovskiy</a> \"so it means for your pipeline you do not find the centroid, but rather taking the entire axial slice, which gives 0.47 LB overall :D?\" That's exactly what I did.</p>\n<p>But because the above comment and the unsolved problem of effectively downsample big MRIs, with the consequent possible valuable information loss, I've started to try to find ROI also in crop slices.</p>\n<p><a href=\"https://www.kaggle.com/code/sacuscreed/sagittal-t1-foramina-discriminator\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/sagittal-t1-foramina-discriminator</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/sagittal-t2-spine-discriminator\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/sagittal-t2-spine-discriminator</a></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F75a56e4cf4ec31a58a20a31b4f3e117a%2Fspinal_discriminator.png?generation=1728467778513712&amp;alt=media\" alt=\"\"></p>\n<p>Again naive but reasonable label imputation was a key. Explicitely labeled crops were directly trusted. Immediate neighbors were excluded. And remaining crops were labeled as negatives.</p>\n<p>At first the idea was to directly select the crops of interest of each \"sandwich\" but results were inconsistent so finally I've decided to aproximate ROI with DICOM correspondence between MRIs and use this discriminators as starting encoders for Transformer. Which resulted in considerably smoother trainings.</p>\n<p><strong>DICOM for axial level assignation:</strong></p>\n<p><a href=\"https://www.kaggle.com/code/sacuscreed/getting-true-axial-levels\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/getting-true-axial-levels</a></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F56229cd953a8d408f0cc07626df4db3a%2Fplane_assignments.png?generation=1728489253664414&amp;alt=media\" alt=\"\"></p>\n<p>A direct implementation from <a href=\"url\" target=\"_blank\">[ver.1] demo workflow: 2-stage approach</a>. I've been working in a less literal adaptation. But time ran out and this one worked perfectly. Axial T2 slices are assigned to levels as the closer planes to the respective level coordinates in middle Sagittal slice.</p>\n<p><strong>ViT over crops for final predictions:</strong></p>\n<p><a href=\"https://www.kaggle.com/code/sacuscreed/sagittal-t1-foraminal-prediction\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/sagittal-t1-foraminal-prediction</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/sagittal-t2-spinal-prediction\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/sagittal-t2-spinal-prediction</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/axial-t2-subarticular-prediction\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/axial-t2-subarticular-prediction</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/axial-t2-spinal-prediction-1-4\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/axial-t2-spinal-prediction-1-4</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/axial-t2-spinal-prediction-5\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/axial-t2-spinal-prediction-5</a></p>\n<p>Finally I've trained five fold CV ViTs feeding Transformer with different sequences of crops using ResNet18 as encoder. Sagittal T1 crops for foraminal predictions:</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F470d3c5e37b1c4bba961d689cf276bca%2Fforaminal_crops.png?generation=1728489469181879&amp;alt=media\" alt=\"Sagittal T1 crops\"></p>\n<p>Sagittal T2 crops for one source of spinal predictions:</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F42eeaa8b3690521d6246cbf6ab872701%2Fspinal_crops.png?generation=1728489501285059&amp;alt=media\" alt=\"Sagittal T2 crops\"></p>\n<p>Axial T2 crops for subarticular predictions:</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F9de6ec6c7d3f23fa502fee861fbedae6%2Faxial_subarticular_crops.png?generation=1728489535332345&amp;alt=media\" alt=\"Axial T2 subarticular crops\"></p>\n<p>And Axial T2 crops for second source of spinal predictions:</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2Ff754e2eb26416596feab21ba760e68a9%2Faxial_spinal_crops.png?generation=1728489574899812&amp;alt=media\" alt=\"Axial T2 spinal crops\"></p>\n<p>I've been working cyclically between pathologies trying to transfer what I have learned each time to the next one. Trying to unify architectures. The main structure is a Transformer for crops in each level/side followed by a second Transformer between levels and sides. I've been experimenting with different positional encoding:</p>\n<p>1) Learnable or not.</p>\n<p>2) Distinguishing sides or not.</p>\n<p>3) Absolute or relative to a Lmax as normalized position.</p>\n<p>I would say that best approach is to absolute encode crops, with not learnable positional encodings and without distinguish sides. That is grouping second Transformer in sequence of 10 (2 for each level) since sides should be equivalent. The diagnosis shouldn't change depending on what side. I've updated this schema for Sagittal T1 and T2 predictions. But I haven't been able to traslate it to Axial T2 ones. In this case although original trainings were very unstable, they achieved at the end better performance. So I kept them.</p>\n<p><strong>Inference:</strong></p>\n<p><a href=\"https://www.kaggle.com/code/sacuscreed/rsna-private-submission-v2\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/rsna-private-submission-v2</a></p>\n<p><strong>Old code:</strong></p>\n<p><a href=\"https://www.kaggle.com/code/sacuscreed/old-axial-t2-axial-side-segmentation\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/old-axial-t2-axial-side-segmentation</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/old-sagittal-t2-segmentation\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/old-sagittal-t2-segmentation</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/sagittal-t1-direction-training\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/sagittal-t1-direction-training</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/sagittal-t1-axial-side-segmentation\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/sagittal-t1-axial-side-segmentation</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/sagittal-t2-axial-spine-segmentation\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/sagittal-t2-axial-spine-segmentation</a></p>",
  "messages": [
    {
      "id": 3012577,
      "postDate": "2024-10-09T07:32:19.747Z",
      "content": "<p>Thank you so much to everyone, especially to organizers and people who shared insights. Has been a long and stressful but enjoyable experience. There is a lot to comment and explain, but at the moment  a summary accross the full process.</p>\n<p><strong>Starting point:</strong></p>\n<p><a href=\"https://www.kaggle.com/code/abhinavsuri/anatomy-image-visualization-overview-rsna-raids\" target=\"_blank\">https://www.kaggle.com/code/abhinavsuri/anatomy-image-visualization-overview-rsna-raids</a></p>\n<p>This notebook introduced me perfectly to the problem and gave me the fundamentals of my approach since first contact. Often professionals base their diagnosis on 2D Sagittal T1 analysis for foraminal, 2D Axial T2 analysis for subarticular and 2D Sagittal T2 and Axial T2 analysis for spinal.</p>\n<p>The main problem is that slices doesn't match perfectly between them, at least without metadata. So I've decided to use a flexible architecture to handle them, Transformers.</p>\n<p><strong>2D UNet for ROI localization in images:</strong></p>\n<p><a href=\"https://www.kaggle.com/code/sacuscreed/sagittal-t1-sagittal-level-segmentation\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/sagittal-t1-sagittal-level-segmentation</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/sagittal-t2-sagittal-level-segmentation\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/sagittal-t2-sagittal-level-segmentation</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/axial-t2-axial-side-segmentation\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/axial-t2-axial-side-segmentation</a></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F6a41878578ada30eaeec0096cdfcab49%2Fsagittal_T1_levels.png?generation=1728465530762952&amp;alt=media\" alt=\"Predicted and True levels\"></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2Fc226ff687bf8f99cd3a4b21ec81cfdd9%2Fsagittal_T2_levels.png?generation=1728465554068790&amp;alt=media\" alt=\"Predicted and True levels\"></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F3b7f8383acbf6c293271b0816cf38a6c%2FAxial_T2_sides.png?generation=1728465338817627&amp;alt=media\" alt=\"Predicted and True sides\"></p>\n<p>Those coordinates together allowed to point backbone slices in Sagittal T1, spine slices in Sagittal T2 and to assign levels to Axial T2 slices. Special thanks to <a href=\"https://www.kaggle.com/hengck23\" target=\"_blank\">@hengck23</a> for <a href=\"https://www.kaggle.com/code/hengck23/2d-to-3d-projection-for-dicom\" target=\"_blank\">2D to 3D proejection for DICOM</a></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F5ef923d887223d67aaf5e47ea5f48c0c%2Faxial_sagittal_correspondence.png?generation=1728464895653686&amp;alt=media\" alt=\"\"></p>\n<p>Is important to mention that I've only used competition data. By data processing I've been able to impute coordinates to slices that hasn't been labeled. All slices between left and right labels for forminal, all neighbor slices in a range of D//5 for spinal and neighbor slices for subarticular. Increasing considerably the amount of data available. I've also duplicated Axial T2 slices by flipping images and coordinates properly.</p>\n<p><strong>CNN for ROI localization in crops:</strong></p>\n<p>At first, I started by feeding Transformer \"full-slice sandwiches\" of the corresponding level or side.</p>\n<p><a href=\"https://www.kaggle.com/sergiosaharovskiy\" target=\"_blank\">@sergiosaharovskiy</a> \"so it means for your pipeline you do not find the centroid, but rather taking the entire axial slice, which gives 0.47 LB overall :D?\" That's exactly what I did.</p>\n<p>But because the above comment and the unsolved problem of effectively downsample big MRIs, with the consequent possible valuable information loss, I've started to try to find ROI also in crop slices.</p>\n<p><a href=\"https://www.kaggle.com/code/sacuscreed/sagittal-t1-foramina-discriminator\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/sagittal-t1-foramina-discriminator</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/sagittal-t2-spine-discriminator\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/sagittal-t2-spine-discriminator</a></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F75a56e4cf4ec31a58a20a31b4f3e117a%2Fspinal_discriminator.png?generation=1728467778513712&amp;alt=media\" alt=\"\"></p>\n<p>Again naive but reasonable label imputation was a key. Explicitely labeled crops were directly trusted. Immediate neighbors were excluded. And remaining crops were labeled as negatives.</p>\n<p>At first the idea was to directly select the crops of interest of each \"sandwich\" but results were inconsistent so finally I've decided to aproximate ROI with DICOM correspondence between MRIs and use this discriminators as starting encoders for Transformer. Which resulted in considerably smoother trainings.</p>\n<p><strong>DICOM for axial level assignation:</strong></p>\n<p><a href=\"https://www.kaggle.com/code/sacuscreed/getting-true-axial-levels\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/getting-true-axial-levels</a></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F56229cd953a8d408f0cc07626df4db3a%2Fplane_assignments.png?generation=1728489253664414&amp;alt=media\" alt=\"\"></p>\n<p>A direct implementation from <a href=\"url\" target=\"_blank\">[ver.1] demo workflow: 2-stage approach</a>. I've been working in a less literal adaptation. But time ran out and this one worked perfectly. Axial T2 slices are assigned to levels as the closer planes to the respective level coordinates in middle Sagittal slice.</p>\n<p><strong>ViT over crops for final predictions:</strong></p>\n<p><a href=\"https://www.kaggle.com/code/sacuscreed/sagittal-t1-foraminal-prediction\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/sagittal-t1-foraminal-prediction</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/sagittal-t2-spinal-prediction\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/sagittal-t2-spinal-prediction</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/axial-t2-subarticular-prediction\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/axial-t2-subarticular-prediction</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/axial-t2-spinal-prediction-1-4\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/axial-t2-spinal-prediction-1-4</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/axial-t2-spinal-prediction-5\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/axial-t2-spinal-prediction-5</a></p>\n<p>Finally I've trained five fold CV ViTs feeding Transformer with different sequences of crops using ResNet18 as encoder. Sagittal T1 crops for foraminal predictions:</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F470d3c5e37b1c4bba961d689cf276bca%2Fforaminal_crops.png?generation=1728489469181879&amp;alt=media\" alt=\"Sagittal T1 crops\"></p>\n<p>Sagittal T2 crops for one source of spinal predictions:</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F42eeaa8b3690521d6246cbf6ab872701%2Fspinal_crops.png?generation=1728489501285059&amp;alt=media\" alt=\"Sagittal T2 crops\"></p>\n<p>Axial T2 crops for subarticular predictions:</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F9de6ec6c7d3f23fa502fee861fbedae6%2Faxial_subarticular_crops.png?generation=1728489535332345&amp;alt=media\" alt=\"Axial T2 subarticular crops\"></p>\n<p>And Axial T2 crops for second source of spinal predictions:</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2Ff754e2eb26416596feab21ba760e68a9%2Faxial_spinal_crops.png?generation=1728489574899812&amp;alt=media\" alt=\"Axial T2 spinal crops\"></p>\n<p>I've been working cyclically between pathologies trying to transfer what I have learned each time to the next one. Trying to unify architectures. The main structure is a Transformer for crops in each level/side followed by a second Transformer between levels and sides. I've been experimenting with different positional encoding:</p>\n<p>1) Learnable or not.</p>\n<p>2) Distinguishing sides or not.</p>\n<p>3) Absolute or relative to a Lmax as normalized position.</p>\n<p>I would say that best approach is to absolute encode crops, with not learnable positional encodings and without distinguish sides. That is grouping second Transformer in sequence of 10 (2 for each level) since sides should be equivalent. The diagnosis shouldn't change depending on what side. I've updated this schema for Sagittal T1 and T2 predictions. But I haven't been able to traslate it to Axial T2 ones. In this case although original trainings were very unstable, they achieved at the end better performance. So I kept them.</p>\n<p><strong>Inference:</strong></p>\n<p><a href=\"https://www.kaggle.com/code/sacuscreed/rsna-private-submission-v2\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/rsna-private-submission-v2</a></p>\n<p><strong>Old code:</strong></p>\n<p><a href=\"https://www.kaggle.com/code/sacuscreed/old-axial-t2-axial-side-segmentation\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/old-axial-t2-axial-side-segmentation</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/old-sagittal-t2-segmentation\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/old-sagittal-t2-segmentation</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/sagittal-t1-direction-training\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/sagittal-t1-direction-training</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/sagittal-t1-axial-side-segmentation\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/sagittal-t1-axial-side-segmentation</a><br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/sagittal-t2-axial-spine-segmentation\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/sagittal-t2-axial-spine-segmentation</a></p>",
      "rawMarkdown": "Thank you so much to everyone, especially to organizers and people who shared insights. Has been a long and stressful but enjoyable experience. There is a lot to comment and explain, but at the moment  a summary accross the full process.\n\n**Starting point:**\n\nhttps://www.kaggle.com/code/abhinavsuri/anatomy-image-visualization-overview-rsna-raids\n\nThis notebook introduced me perfectly to the problem and gave me the fundamentals of my approach since first contact. Often professionals base their diagnosis on 2D Sagittal T1 analysis for foraminal, 2D Axial T2 analysis for subarticular and 2D Sagittal T2 and Axial T2 analysis for spinal.\n\nThe main problem is that slices doesn't match perfectly between them, at least without metadata. So I've decided to use a flexible architecture to handle them, Transformers.\n\n**2D UNet for ROI localization in images:**\n\nhttps://www.kaggle.com/code/sacuscreed/sagittal-t1-sagittal-level-segmentation\nhttps://www.kaggle.com/code/sacuscreed/sagittal-t2-sagittal-level-segmentation\nhttps://www.kaggle.com/code/sacuscreed/axial-t2-axial-side-segmentation\n\n![Predicted and True levels](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F6a41878578ada30eaeec0096cdfcab49%2Fsagittal_T1_levels.png?generation=1728465530762952&alt=media)\n\n![Predicted and True levels](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2Fc226ff687bf8f99cd3a4b21ec81cfdd9%2Fsagittal_T2_levels.png?generation=1728465554068790&alt=media)\n\n![Predicted and True sides](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F3b7f8383acbf6c293271b0816cf38a6c%2FAxial_T2_sides.png?generation=1728465338817627&alt=media)\n\nThose coordinates together allowed to point backbone slices in Sagittal T1, spine slices in Sagittal T2 and to assign levels to Axial T2 slices. Special thanks to @hengck23 for [2D to 3D proejection for DICOM](https://www.kaggle.com/code/hengck23/2d-to-3d-projection-for-dicom)\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F5ef923d887223d67aaf5e47ea5f48c0c%2Faxial_sagittal_correspondence.png?generation=1728464895653686&alt=media)\n\nIs important to mention that I've only used competition data. By data processing I've been able to impute coordinates to slices that hasn't been labeled. All slices between left and right labels for forminal, all neighbor slices in a range of D//5 for spinal and neighbor slices for subarticular. Increasing considerably the amount of data available. I've also duplicated Axial T2 slices by flipping images and coordinates properly.\n\n**CNN for ROI localization in crops:**\n\nAt first, I started by feeding Transformer \"full-slice sandwiches\" of the corresponding level or side.\n\n@sergiosaharovskiy \"so it means for your pipeline you do not find the centroid, but rather taking the entire axial slice, which gives 0.47 LB overall :D?\" That's exactly what I did.\n\nBut because the above comment and the unsolved problem of effectively downsample big MRIs, with the consequent possible valuable information loss, I've started to try to find ROI also in crop slices.\n\nhttps://www.kaggle.com/code/sacuscreed/sagittal-t1-foramina-discriminator\nhttps://www.kaggle.com/code/sacuscreed/sagittal-t2-spine-discriminator\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F75a56e4cf4ec31a58a20a31b4f3e117a%2Fspinal_discriminator.png?generation=1728467778513712&alt=media)\n\nAgain naive but reasonable label imputation was a key. Explicitely labeled crops were directly trusted. Immediate neighbors were excluded. And remaining crops were labeled as negatives.\n\nAt first the idea was to directly select the crops of interest of each \"sandwich\" but results were inconsistent so finally I've decided to aproximate ROI with DICOM correspondence between MRIs and use this discriminators as starting encoders for Transformer. Which resulted in considerably smoother trainings.\n\n**DICOM for axial level assignation:**\n\nhttps://www.kaggle.com/code/sacuscreed/getting-true-axial-levels\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F56229cd953a8d408f0cc07626df4db3a%2Fplane_assignments.png?generation=1728489253664414&alt=media)\n\nA direct implementation from [[ver.1] demo workflow: 2-stage approach](url). I've been working in a less literal adaptation. But time ran out and this one worked perfectly. Axial T2 slices are assigned to levels as the closer planes to the respective level coordinates in middle Sagittal slice.\n\n**ViT over crops for final predictions:**\n\nhttps://www.kaggle.com/code/sacuscreed/sagittal-t1-foraminal-prediction\nhttps://www.kaggle.com/code/sacuscreed/sagittal-t2-spinal-prediction\nhttps://www.kaggle.com/code/sacuscreed/axial-t2-subarticular-prediction\nhttps://www.kaggle.com/code/sacuscreed/axial-t2-spinal-prediction-1-4\nhttps://www.kaggle.com/code/sacuscreed/axial-t2-spinal-prediction-5\n\nFinally I've trained five fold CV ViTs feeding Transformer with different sequences of crops using ResNet18 as encoder. Sagittal T1 crops for foraminal predictions:\n\n![Sagittal T1 crops](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F470d3c5e37b1c4bba961d689cf276bca%2Fforaminal_crops.png?generation=1728489469181879&alt=media)\n\nSagittal T2 crops for one source of spinal predictions:\n\n![Sagittal T2 crops](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F42eeaa8b3690521d6246cbf6ab872701%2Fspinal_crops.png?generation=1728489501285059&alt=media)\n\nAxial T2 crops for subarticular predictions:\n\n![Axial T2 subarticular crops](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F9de6ec6c7d3f23fa502fee861fbedae6%2Faxial_subarticular_crops.png?generation=1728489535332345&alt=media)\n\nAnd Axial T2 crops for second source of spinal predictions:\n\n![Axial T2 spinal crops](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2Ff754e2eb26416596feab21ba760e68a9%2Faxial_spinal_crops.png?generation=1728489574899812&alt=media)\n\nI've been working cyclically between pathologies trying to transfer what I have learned each time to the next one. Trying to unify architectures. The main structure is a Transformer for crops in each level/side followed by a second Transformer between levels and sides. I've been experimenting with different positional encoding:\n\n1) Learnable or not.\n \n2) Distinguishing sides or not.\n\n3) Absolute or relative to a Lmax as normalized position.\n\nI would say that best approach is to absolute encode crops, with not learnable positional encodings and without distinguish sides. That is grouping second Transformer in sequence of 10 (2 for each level) since sides should be equivalent. The diagnosis shouldn't change depending on what side. I've updated this schema for Sagittal T1 and T2 predictions. But I haven't been able to traslate it to Axial T2 ones. In this case although original trainings were very unstable, they achieved at the end better performance. So I kept them.\n\n**Inference:**\n\nhttps://www.kaggle.com/code/sacuscreed/rsna-private-submission-v2\n\n**Old code:**\n\nhttps://www.kaggle.com/code/sacuscreed/old-axial-t2-axial-side-segmentation\nhttps://www.kaggle.com/code/sacuscreed/old-sagittal-t2-segmentation\nhttps://www.kaggle.com/code/sacuscreed/sagittal-t1-direction-training\nhttps://www.kaggle.com/code/sacuscreed/sagittal-t1-axial-side-segmentation\nhttps://www.kaggle.com/code/sacuscreed/sagittal-t2-axial-spine-segmentation",
      "votes": 12
    },
    {
      "id": 3025146,
      "postDate": "2024-10-22T13:13:59.290Z",
      "content": "<p>Congratulations🥳<br>\nThanks for sharing your solution<br>\nCan you send the  train_split.csv file ?</p>",
      "rawMarkdown": "Congratulations🥳\nThanks for sharing your solution\nCan you send the  train_split.csv file ?\n",
      "replies": [
        {
          "id": 3025587,
          "postDate": "2024-10-23T01:03:24.507Z",
          "content": "<p>Sure. At the end of the competition I couldn't make it public. May be because an antispam mechanism, but <a href=\"https://www.kaggle.com/code/sacuscreed/cv-splits\" target=\"_blank\">here</a> it is. Was just a plane study_id CV.</p>",
          "rawMarkdown": "Sure. At the end of the competition I couldn't make it public. May be because an antispam mechanism, but [here](https://www.kaggle.com/code/sacuscreed/cv-splits) it is. Was just a plane study_id CV.",
          "replies": [
            {
              "id": 3026760,
              "postDate": "2024-10-24T07:53:40.867Z",
              "content": "<p>Thanks a lot for sharing.<br>\nAre all of your notebooks fully compatible with Kaggle(run on Kaggle)? </p>",
              "rawMarkdown": "Thanks a lot for sharing.\nAre all of your notebooks fully compatible with Kaggle(run on Kaggle)? "
            },
            {
              "id": 3026845,
              "postDate": "2024-10-24T09:16:44.393Z",
              "content": "<p>They should if you change the paths. I haven't tested.</p>",
              "rawMarkdown": "They should if you change the paths. I haven't tested."
            },
            {
              "id": 3026906,
              "postDate": "2024-10-24T10:38:09.360Z",
              "content": "<p>I saw the train_splits file, but is this line right <br>\n\"spinal = list(filter(lambda x: x.find('right_subarticular') &gt; -1, train.columns))\"?<br>\n and why did not write so \"spinal = list(filter(lambda x: x.find('spinal') &gt; -1, train.columns))\"?</p>",
              "rawMarkdown": "I saw the train_splits file, but is this line right \n\"spinal = list(filter(lambda x: x.find('right_subarticular') > -1, train.columns))\"?\n and why did not write so \"spinal = list(filter(lambda x: x.find('spinal') > -1, train.columns))\"?"
            },
            {
              "id": 3026923,
              "postDate": "2024-10-24T10:50:45.683Z",
              "content": "<p>when I used this code \"<br>\nfor (study_id,series_id),df in tqdm(F.groupby(['study_id','series_id'])):<br>\n    sample = TRAIN_PATH + str(study_id) + '/' + str(series_id)<br>\n    instance_numbers = [int(x.replace('\\','/').split('/')[-1].replace('.dcm','')) for x in glob.glob(sample+'/<em>.dcm')]\n    instance_numbers.sort()\n    instance_numbers = np.array(instance_numbers)\n    D = len(instance_numbers)\n    FIRST = int(np.arange(D)[instance_numbers == df['instance_number'].min()])\n    LAST = int(np.arange(D)[instance_numbers == df['instance_number'].max()])\n    new = instance_numbers[FIRST+1:LAST].tolist()\n    if FIRST &gt; 0: new.append(instance_numbers[FIRST - 1])\n    if LAST &lt; D - 1: new.append(instance_numbers[LAST + 1])\n    L = len(new)\n    F = pd.concat([\n        F,\n        pd.DataFrame({\n            'study_id':[int(study_id)]</em>L,<br>\n            'series_id':[int(series_id)]<em>L,\n            'instance_number':new,\n            'x_L1L2':[torch.nan]</em>L,<br>\n            'y_L1L2':[torch.nan]<em>L,\n            'x_L2L3':[torch.nan]</em>L,<br>\n            'y_L2L3':[torch.nan]<em>L,\n            'x_L3L4':[torch.nan]</em>L,<br>\n            'y_L3L4':[torch.nan]<em>L,\n            'x_L4L5':[torch.nan]</em>L,<br>\n            'y_L4L5':[torch.nan]<em>L,\n            'x_L5S1':[torch.nan]</em>L,<br>\n            'y_L5S1':[torch.nan]*L<br>\n        })<br>\n    ])\"<br>\nI found that \"Min or Max instance_number not found in instance_numbers for study_id 3967802493, series_id 1589249065\"<br>\ntherefore, the my output is (12240, 10) not like your notebook  (27440, 10), </p>",
              "rawMarkdown": "when I used this code \"\nfor (study_id,series_id),df in tqdm(F.groupby(['study_id','series_id'])):\n    sample = TRAIN_PATH + str(study_id) + '/' + str(series_id)\n    instance_numbers = [int(x.replace('\\\\','/').split('/')[-1].replace('.dcm','')) for x in glob.glob(sample+'/*.dcm')]\n    instance_numbers.sort()\n    instance_numbers = np.array(instance_numbers)\n    D = len(instance_numbers)\n    FIRST = int(np.arange(D)[instance_numbers == df['instance_number'].min()])\n    LAST = int(np.arange(D)[instance_numbers == df['instance_number'].max()])\n    new = instance_numbers[FIRST+1:LAST].tolist()\n    if FIRST > 0: new.append(instance_numbers[FIRST - 1])\n    if LAST < D - 1: new.append(instance_numbers[LAST + 1])\n    L = len(new)\n    F = pd.concat([\n        F,\n        pd.DataFrame({\n            'study_id':[int(study_id)]*L,\n            'series_id':[int(series_id)]*L,\n            'instance_number':new,\n            'x_L1L2':[torch.nan]*L,\n            'y_L1L2':[torch.nan]*L,\n            'x_L2L3':[torch.nan]*L,\n            'y_L2L3':[torch.nan]*L,\n            'x_L3L4':[torch.nan]*L,\n            'y_L3L4':[torch.nan]*L,\n            'x_L4L5':[torch.nan]*L,\n            'y_L4L5':[torch.nan]*L,\n            'x_L5S1':[torch.nan]*L,\n            'y_L5S1':[torch.nan]*L\n        })\n    ])\"\nI found that \"Min or Max instance_number not found in instance_numbers for study_id 3967802493, series_id 1589249065\"\ntherefore, the my output is (12240, 10) not like your notebook  (27440, 10), \n"
            },
            {
              "id": 3026946,
              "postDate": "2024-10-24T11:27:19.247Z",
              "content": "<p>\"I saw the train_splits file, but is this line right<br>\n\"spinal = list(filter(lambda x: x.find('right_subarticular') &gt; -1, train.columns))\"?<br>\nand why did not write so \"spinal = list(filter(lambda x: x.find('spinal') &gt; -1, train.columns))\"?\"</p>\n<p>it should in fact, it is a bug, but those definitions are not used in train_splits</p>",
              "rawMarkdown": "\"I saw the train_splits file, but is this line right\n\"spinal = list(filter(lambda x: x.find('right_subarticular') > -1, train.columns))\"?\nand why did not write so \"spinal = list(filter(lambda x: x.find('spinal') > -1, train.columns))\"?\"\n\nit should in fact, it is a bug, but those definitions are not used in train_splits"
            },
            {
              "id": 3026950,
              "postDate": "2024-10-24T11:29:14.543Z",
              "content": "<p>What notebook is that from? Or better, what's in \"sample\" in that moment?</p>",
              "rawMarkdown": "What notebook is that from? Or better, what's in \"sample\" in that moment?"
            },
            {
              "id": 3026952,
              "postDate": "2024-10-24T11:32:25.913Z",
              "content": "<p>from that \"https://www.kaggle.com/code/sacuscreed/sagittal-t1-sagittal-level-segmentation/notebook\"</p>",
              "rawMarkdown": "from that \"https://www.kaggle.com/code/sacuscreed/sagittal-t1-sagittal-level-segmentation/notebook\""
            },
            {
              "id": 3026953,
              "postDate": "2024-10-24T11:33:34.293Z",
              "rawMarkdown": "",
              "isDeleted": true
            },
            {
              "id": 3026957,
              "postDate": "2024-10-24T11:43:51.233Z",
              "content": "<p>correct is \"spinal\" not 'right_subarticular?<br>\nI found this line \"spinal = list(filter(lambda x: x.find('right_subarticular') &gt; -1, train.columns))\"?<br>\nand why did not write so \"spinal = list(filter(lambda x: x.find('spinal') &gt; -1, train.columns))\"?\" from here \"https://www.kaggle.com/code/sacuscreed/cv-splits\"</p>",
              "rawMarkdown": "correct is \"spinal\" not 'right_subarticular?\nI found this line \"spinal = list(filter(lambda x: x.find('right_subarticular') > -1, train.columns))\"?\nand why did not write so \"spinal = list(filter(lambda x: x.find('spinal') > -1, train.columns))\"?\" from here \"https://www.kaggle.com/code/sacuscreed/cv-splits\""
            },
            {
              "id": 3026966,
              "postDate": "2024-10-24T11:51:18.007Z",
              "content": "<p>I've updated it to run in kaggle, ran till training without errors. You can check it now or wait till the commit ends.</p>\n<p>That filtering was indeed a fast edit bug, you are right.</p>\n<p>EDIT: The results are quite similars, but I have no idea why they differ, specifically fold 1 so much.</p>",
              "rawMarkdown": "I've updated it to run in kaggle, ran till training without errors. You can check it now or wait till the commit ends.\n\nThat filtering was indeed a fast edit bug, you are right.\n\nEDIT: The results are quite similars, but I have no idea why they differ, specifically fold 1 so much."
            },
            {
              "id": 3027724,
              "postDate": "2024-10-25T07:43:40.560Z",
              "content": "<p>Thanks for your efforts</p>",
              "rawMarkdown": "Thanks for your efforts"
            },
            {
              "id": 3027773,
              "postDate": "2024-10-25T09:06:06.087Z",
              "content": "<p>First of all, thank you for answering my questions. I wanted to ask you. <br>\n1- I am interested in understanding your solution. What I understood so far is that you are doing a segmentation for each orientation alone, so you have 3 notebooks. Then I found a lot of files, and when I tried to see the notebook called \"rsna-private-submission-v2\", I found this code\"Sagittal_T1_sagittal_segmentation_paths = [<br>\n        '/kaggle/input/sagittal-t1/Sagittal_T1_sagittal_level_segmentation_1',<br>\n        '/kaggle/input/sagittal-t1/Sagittal_T1_sagittal_level_segmentation_2',<br>\n        '/kaggle/input/sagittal-t1/Sagittal_T1_sagittal_level_segmentation_3',<br>\n        '/kaggle/input/sagittal-t1/Sagittal_T1_sagittal_level_segmentation_4',<br>\n        '/kaggle/input/sagittal-t1/Sagittal_T1_sagittal_level_segmentation_5'<br>\n]\". <br>\nHonestly, it confused me. Why is it written as 5 paths, while it is one notebook that was implementing the segmentation for Sagittal_T1? </p>\n<p>2- Can you explain your solution to me? </p>\n<p>3- I hope you arrange your notebooks in the order of execution to reach the notebook reference.</p>\n<p>Finally, I would like to express my gratitude for your help.</p>",
              "rawMarkdown": "First of all, thank you for answering my questions. I wanted to ask you. \n1- I am interested in understanding your solution. What I understood so far is that you are doing a segmentation for each orientation alone, so you have 3 notebooks. Then I found a lot of files, and when I tried to see the notebook called \"rsna-private-submission-v2\", I found this code\"Sagittal_T1_sagittal_segmentation_paths = [\n        '/kaggle/input/sagittal-t1/Sagittal_T1_sagittal_level_segmentation_1',\n        '/kaggle/input/sagittal-t1/Sagittal_T1_sagittal_level_segmentation_2',\n        '/kaggle/input/sagittal-t1/Sagittal_T1_sagittal_level_segmentation_3',\n        '/kaggle/input/sagittal-t1/Sagittal_T1_sagittal_level_segmentation_4',\n        '/kaggle/input/sagittal-t1/Sagittal_T1_sagittal_level_segmentation_5'\n]\". \nHonestly, it confused me. Why is it written as 5 paths, while it is one notebook that was implementing the segmentation for Sagittal_T1? \n\n2- Can you explain your solution to me? \n\n3- I hope you arrange your notebooks in the order of execution to reach the notebook reference.\n\nFinally, I would like to express my gratitude for your help."
            },
            {
              "id": 3027836,
              "postDate": "2024-10-25T10:54:41.260Z",
              "content": "<p>1-  Because every single notebook produces five models, one per fold.</p>\n<p>2- If you have any specific question rather than explain it all (actually that's the purpose of this thread).</p>\n<p>3- They're already arranged.</p>",
              "rawMarkdown": "1-  Because every single notebook produces five models, one per fold.\n\n2- If you have any specific question rather than explain it all (actually that's the purpose of this thread).\n\n3- They're already arranged."
            },
            {
              "id": 3033647,
              "postDate": "2024-11-01T11:53:57.403Z",
              "content": "<p>The notebook  \"Axial_T2_subarticular_prediction\" is in a file called\"axial_centers.pkl\" . How do I get it?</p>\n<p>I found a file \"level_assignments.pkl\" when run the notebook\"https://www.kaggle.com/code/sacuscreed/getting-true-axial-levels\"</p>",
              "rawMarkdown": "The notebook  \"Axial_T2_subarticular_prediction\" is in a file called\"axial_centers.pkl\" . How do I get it?\n\nI found a file \"level_assignments.pkl\" when run the notebook\"https://www.kaggle.com/code/sacuscreed/getting-true-axial-levels\""
            },
            {
              "id": 3033658,
              "postDate": "2024-11-01T12:11:39.680Z",
              "content": "<p>Since was an old version I forgot to include it. Sorry about that. It should contain the left and right coordinates segmented with Axial_T2_side_segmentation models. In that version I've saved a pickle jason containing the segmented coordinates of all train for every fold model. Should be not hard to regenerate. Tell me if you need me to explicitely do it.</p>",
              "rawMarkdown": "Since was an old version I forgot to include it. Sorry about that. It should contain the left and right coordinates segmented with Axial_T2_side_segmentation models. In that version I've saved a pickle jason containing the segmented coordinates of all train for every fold model. Should be not hard to regenerate. Tell me if you need me to explicitely do it."
            },
            {
              "id": 3033792,
              "postDate": "2024-11-01T14:14:45.503Z",
              "content": "<p>This time I've updated coordinates segmentation with flips and rot90s, making it x8 slower. Anyway, should finish in about 8 hours <br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/axial-t2-centers-generation\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/axial-t2-centers-generation</a></p>",
              "rawMarkdown": "This time I've updated coordinates segmentation with flips and rot90s, making it x8 slower. Anyway, should finish in about 8 hours \nhttps://www.kaggle.com/code/sacuscreed/axial-t2-centers-generation"
            },
            {
              "id": 3033894,
              "postDate": "2024-11-01T15:47:12.797Z",
              "content": "<p>Is there another way to make the time less than 8 hours?</p>",
              "rawMarkdown": "Is there another way to make the time less than 8 hours?"
            },
            {
              "id": 3033968,
              "postDate": "2024-11-01T16:54:57.793Z",
              "content": "<p>You can make a single prediction per batch, ~1 hour. </p>\n<p>And that won't affect time, but you also can calculate a single set of coordinates by ensembling the folds instead of a set of coordinates per fold. But you should then also modify the dataset on \"Axial_T2_subarticular_prediction\".</p>\n<p>Anyway, just take the output from my notebook once it's done (about 5 hours remaining).</p>",
              "rawMarkdown": "You can make a single prediction per batch, ~1 hour. \n\nAnd that won't affect time, but you also can calculate a single set of coordinates by ensembling the folds instead of a set of coordinates per fold. But you should then also modify the dataset on \"Axial_T2_subarticular_prediction\".\n\nAnyway, just take the output from my notebook once it's done (about 5 hours remaining)."
            },
            {
              "id": 3034029,
              "postDate": "2024-11-01T17:43:41.167Z",
              "content": "<p>note<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3826569%2Fb2ae3d62a98487ff537a6c595fbcc85d%2FCapture.JPG?generation=1730483007381545&amp;alt=media\" alt=\"\"></p>",
              "rawMarkdown": " note![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3826569%2Fb2ae3d62a98487ff537a6c595fbcc85d%2FCapture.JPG?generation=1730483007381545&alt=media)"
            },
            {
              "id": 3034036,
              "postDate": "2024-11-01T17:47:44.077Z",
              "content": "<p>I found that error in \"https://www.kaggle.com/code/sacuscreed/axial-t2-centers-generation\" I also found it when I used it , Can you help me find a solution to this error?</p>",
              "rawMarkdown": "I found that error in \"https://www.kaggle.com/code/sacuscreed/axial-t2-centers-generation\" I also found it when I used it , Can you help me find a solution to this error?"
            },
            {
              "id": 3034086,
              "postDate": "2024-11-01T18:54:40.513Z",
              "content": "<p>That's a Ctrl+C execution kill. My commit execution is 1635/2340 right now. Just wait 2-3 hours and get the output.</p>",
              "rawMarkdown": "That's a Ctrl+C execution kill. My commit execution is 1635/2340 right now. Just wait 2-3 hours and get the output."
            },
            {
              "id": 3034762,
              "postDate": "2024-11-02T15:54:47.060Z",
              "content": "<p>I would like to thank you for your help.<br>\nWhile I was working on this file\"https://www.kaggle.com/code/sacuscreed/axial-t2-subarticular-prediction\", I got this error \"https://www.kaggle.com/code/samarkilany/axial-t2-subarticular-prediction\"Did it happen to you too?</p>",
              "rawMarkdown": "I would like to thank you for your help.\nWhile I was working on this file\"https://www.kaggle.com/code/sacuscreed/axial-t2-subarticular-prediction\", I got this error \"https://www.kaggle.com/code/samarkilany/axial-t2-subarticular-prediction\"Did it happen to you too?"
            },
            {
              "id": 3034873,
              "postDate": "2024-11-02T17:34:08.967Z",
              "content": "<p>I'm running a single fold and EPOCH. That error suggests that the crop failed, may be cause bad centers. That early version had no corrections to centers in order to prevent it. If the experiment I'm running right now crashes I'll check it carefully.</p>",
              "rawMarkdown": "I'm running a single fold and EPOCH. That error suggests that the crop failed, may be cause bad centers. That early version had no corrections to centers in order to prevent it. If the experiment I'm running right now crashes I'll check it carefully."
            },
            {
              "id": 3034894,
              "postDate": "2024-11-02T18:24:27.663Z",
              "content": "<p>Error appeared in fold=4 ,but in case fold =1,2,3 not appeared </p>",
              "rawMarkdown": "Error appeared in fold=4 ,but in case fold =1,2,3 not appeared "
            },
            {
              "id": 3034899,
              "postDate": "2024-11-02T18:35:53.520Z",
              "content": "<p>Testing fold 4…</p>\n<p>EDIT: <a href=\"https://www.kaggle.com/samarkilany\" target=\"_blank\">@samarkilany</a> Yes, I've got same error. I've just updated dataset. Is no the best solution. But will work. And most importantly, won't affect the samples that crop properly. I don't want to change the original code.</p>",
              "rawMarkdown": "Testing fold 4...\n\nEDIT: @samarkilany Yes, I've got same error. I've just updated dataset. Is no the best solution. But will work. And most importantly, won't affect the samples that crop properly. I don't want to change the original code."
            },
            {
              "id": 3035517,
              "postDate": "2024-11-03T14:32:04.623Z",
              "content": "<p>What do you mean? You updated the data.</p>",
              "rawMarkdown": "What do you mean? You updated the data."
            },
            {
              "id": 3046285,
              "postDate": "2024-11-15T10:15:41.947Z",
              "content": "<p>Not the data. The function that takes samples from it.</p>",
              "rawMarkdown": "Not the data. The function that takes samples from it."
            }
          ]
        }
      ]
    }
  ],
  "comments": [
    {
      "id": 3025146,
      "author_name": "KS",
      "author_url": "",
      "post_date": "2024-10-22T13:13:59.290000",
      "content": "<p>Congratulations🥳<br>\nThanks for sharing your solution<br>\nCan you send the  train_split.csv file ?</p>",
      "votes": 0,
      "replies": [
        {
          "id": 3025587,
          "author_name": "Ángel Jacinto Sánchez Ruiz",
          "author_url": "",
          "post_date": "2024-10-23T01:03:24.507000",
          "content": "<p>Sure. At the end of the competition I couldn't make it public. May be because an antispam mechanism, but <a href=\"https://www.kaggle.com/code/sacuscreed/cv-splits\" target=\"_blank\">here</a> it is. Was just a plane study_id CV.</p>",
          "votes": 0,
          "replies": [
            {
              "id": 3026760,
              "author_name": "KS",
              "author_url": "",
              "post_date": "2024-10-24T07:53:40.867000",
              "content": "<p>Thanks a lot for sharing.<br>\nAre all of your notebooks fully compatible with Kaggle(run on Kaggle)? </p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3026845,
              "author_name": "Ángel Jacinto Sánchez Ruiz",
              "author_url": "",
              "post_date": "2024-10-24T09:16:44.393000",
              "content": "<p>They should if you change the paths. I haven't tested.</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3026906,
              "author_name": "KS",
              "author_url": "",
              "post_date": "2024-10-24T10:38:09.360000",
              "content": "<p>I saw the train_splits file, but is this line right <br>\n\"spinal = list(filter(lambda x: x.find('right_subarticular') &gt; -1, train.columns))\"?<br>\n and why did not write so \"spinal = list(filter(lambda x: x.find('spinal') &gt; -1, train.columns))\"?</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3026923,
              "author_name": "KS",
              "author_url": "",
              "post_date": "2024-10-24T10:50:45.683000",
              "content": "<p>when I used this code \"<br>\nfor (study_id,series_id),df in tqdm(F.groupby(['study_id','series_id'])):<br>\n    sample = TRAIN_PATH + str(study_id) + '/' + str(series_id)<br>\n    instance_numbers = [int(x.replace('\\','/').split('/')[-1].replace('.dcm','')) for x in glob.glob(sample+'/<em>.dcm')]\n    instance_numbers.sort()\n    instance_numbers = np.array(instance_numbers)\n    D = len(instance_numbers)\n    FIRST = int(np.arange(D)[instance_numbers == df['instance_number'].min()])\n    LAST = int(np.arange(D)[instance_numbers == df['instance_number'].max()])\n    new = instance_numbers[FIRST+1:LAST].tolist()\n    if FIRST &gt; 0: new.append(instance_numbers[FIRST - 1])\n    if LAST &lt; D - 1: new.append(instance_numbers[LAST + 1])\n    L = len(new)\n    F = pd.concat([\n        F,\n        pd.DataFrame({\n            'study_id':[int(study_id)]</em>L,<br>\n            'series_id':[int(series_id)]<em>L,\n            'instance_number':new,\n            'x_L1L2':[torch.nan]</em>L,<br>\n            'y_L1L2':[torch.nan]<em>L,\n            'x_L2L3':[torch.nan]</em>L,<br>\n            'y_L2L3':[torch.nan]<em>L,\n            'x_L3L4':[torch.nan]</em>L,<br>\n            'y_L3L4':[torch.nan]<em>L,\n            'x_L4L5':[torch.nan]</em>L,<br>\n            'y_L4L5':[torch.nan]<em>L,\n            'x_L5S1':[torch.nan]</em>L,<br>\n            'y_L5S1':[torch.nan]*L<br>\n        })<br>\n    ])\"<br>\nI found that \"Min or Max instance_number not found in instance_numbers for study_id 3967802493, series_id 1589249065\"<br>\ntherefore, the my output is (12240, 10) not like your notebook  (27440, 10), </p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3026946,
              "author_name": "Ángel Jacinto Sánchez Ruiz",
              "author_url": "",
              "post_date": "2024-10-24T11:27:19.247000",
              "content": "<p>\"I saw the train_splits file, but is this line right<br>\n\"spinal = list(filter(lambda x: x.find('right_subarticular') &gt; -1, train.columns))\"?<br>\nand why did not write so \"spinal = list(filter(lambda x: x.find('spinal') &gt; -1, train.columns))\"?\"</p>\n<p>it should in fact, it is a bug, but those definitions are not used in train_splits</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3026950,
              "author_name": "Ángel Jacinto Sánchez Ruiz",
              "author_url": "",
              "post_date": "2024-10-24T11:29:14.543000",
              "content": "<p>What notebook is that from? Or better, what's in \"sample\" in that moment?</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3026952,
              "author_name": "KS",
              "author_url": "",
              "post_date": "2024-10-24T11:32:25.913000",
              "content": "<p>from that \"https://www.kaggle.com/code/sacuscreed/sagittal-t1-sagittal-level-segmentation/notebook\"</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3026953,
              "author_name": "",
              "author_url": "",
              "post_date": "2024-10-24T11:33:34.293000",
              "content": "",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3026957,
              "author_name": "KS",
              "author_url": "",
              "post_date": "2024-10-24T11:43:51.233000",
              "content": "<p>correct is \"spinal\" not 'right_subarticular?<br>\nI found this line \"spinal = list(filter(lambda x: x.find('right_subarticular') &gt; -1, train.columns))\"?<br>\nand why did not write so \"spinal = list(filter(lambda x: x.find('spinal') &gt; -1, train.columns))\"?\" from here \"https://www.kaggle.com/code/sacuscreed/cv-splits\"</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3026966,
              "author_name": "Ángel Jacinto Sánchez Ruiz",
              "author_url": "",
              "post_date": "2024-10-24T11:51:18.007000",
              "content": "<p>I've updated it to run in kaggle, ran till training without errors. You can check it now or wait till the commit ends.</p>\n<p>That filtering was indeed a fast edit bug, you are right.</p>\n<p>EDIT: The results are quite similars, but I have no idea why they differ, specifically fold 1 so much.</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3027724,
              "author_name": "KS",
              "author_url": "",
              "post_date": "2024-10-25T07:43:40.560000",
              "content": "<p>Thanks for your efforts</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3027773,
              "author_name": "KS",
              "author_url": "",
              "post_date": "2024-10-25T09:06:06.087000",
              "content": "<p>First of all, thank you for answering my questions. I wanted to ask you. <br>\n1- I am interested in understanding your solution. What I understood so far is that you are doing a segmentation for each orientation alone, so you have 3 notebooks. Then I found a lot of files, and when I tried to see the notebook called \"rsna-private-submission-v2\", I found this code\"Sagittal_T1_sagittal_segmentation_paths = [<br>\n        '/kaggle/input/sagittal-t1/Sagittal_T1_sagittal_level_segmentation_1',<br>\n        '/kaggle/input/sagittal-t1/Sagittal_T1_sagittal_level_segmentation_2',<br>\n        '/kaggle/input/sagittal-t1/Sagittal_T1_sagittal_level_segmentation_3',<br>\n        '/kaggle/input/sagittal-t1/Sagittal_T1_sagittal_level_segmentation_4',<br>\n        '/kaggle/input/sagittal-t1/Sagittal_T1_sagittal_level_segmentation_5'<br>\n]\". <br>\nHonestly, it confused me. Why is it written as 5 paths, while it is one notebook that was implementing the segmentation for Sagittal_T1? </p>\n<p>2- Can you explain your solution to me? </p>\n<p>3- I hope you arrange your notebooks in the order of execution to reach the notebook reference.</p>\n<p>Finally, I would like to express my gratitude for your help.</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3027836,
              "author_name": "Ángel Jacinto Sánchez Ruiz",
              "author_url": "",
              "post_date": "2024-10-25T10:54:41.260000",
              "content": "<p>1-  Because every single notebook produces five models, one per fold.</p>\n<p>2- If you have any specific question rather than explain it all (actually that's the purpose of this thread).</p>\n<p>3- They're already arranged.</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3033647,
              "author_name": "KS",
              "author_url": "",
              "post_date": "2024-11-01T11:53:57.403000",
              "content": "<p>The notebook  \"Axial_T2_subarticular_prediction\" is in a file called\"axial_centers.pkl\" . How do I get it?</p>\n<p>I found a file \"level_assignments.pkl\" when run the notebook\"https://www.kaggle.com/code/sacuscreed/getting-true-axial-levels\"</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3033658,
              "author_name": "Ángel Jacinto Sánchez Ruiz",
              "author_url": "",
              "post_date": "2024-11-01T12:11:39.680000",
              "content": "<p>Since was an old version I forgot to include it. Sorry about that. It should contain the left and right coordinates segmented with Axial_T2_side_segmentation models. In that version I've saved a pickle jason containing the segmented coordinates of all train for every fold model. Should be not hard to regenerate. Tell me if you need me to explicitely do it.</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3033792,
              "author_name": "Ángel Jacinto Sánchez Ruiz",
              "author_url": "",
              "post_date": "2024-11-01T14:14:45.503000",
              "content": "<p>This time I've updated coordinates segmentation with flips and rot90s, making it x8 slower. Anyway, should finish in about 8 hours <br>\n<a href=\"https://www.kaggle.com/code/sacuscreed/axial-t2-centers-generation\" target=\"_blank\">https://www.kaggle.com/code/sacuscreed/axial-t2-centers-generation</a></p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3033894,
              "author_name": "KS",
              "author_url": "",
              "post_date": "2024-11-01T15:47:12.797000",
              "content": "<p>Is there another way to make the time less than 8 hours?</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3033968,
              "author_name": "Ángel Jacinto Sánchez Ruiz",
              "author_url": "",
              "post_date": "2024-11-01T16:54:57.793000",
              "content": "<p>You can make a single prediction per batch, ~1 hour. </p>\n<p>And that won't affect time, but you also can calculate a single set of coordinates by ensembling the folds instead of a set of coordinates per fold. But you should then also modify the dataset on \"Axial_T2_subarticular_prediction\".</p>\n<p>Anyway, just take the output from my notebook once it's done (about 5 hours remaining).</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3034029,
              "author_name": "KS",
              "author_url": "",
              "post_date": "2024-11-01T17:43:41.167000",
              "content": "<p>note<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3826569%2Fb2ae3d62a98487ff537a6c595fbcc85d%2FCapture.JPG?generation=1730483007381545&amp;alt=media\" alt=\"\"></p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3034036,
              "author_name": "KS",
              "author_url": "",
              "post_date": "2024-11-01T17:47:44.077000",
              "content": "<p>I found that error in \"https://www.kaggle.com/code/sacuscreed/axial-t2-centers-generation\" I also found it when I used it , Can you help me find a solution to this error?</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3034086,
              "author_name": "Ángel Jacinto Sánchez Ruiz",
              "author_url": "",
              "post_date": "2024-11-01T18:54:40.513000",
              "content": "<p>That's a Ctrl+C execution kill. My commit execution is 1635/2340 right now. Just wait 2-3 hours and get the output.</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3034762,
              "author_name": "KS",
              "author_url": "",
              "post_date": "2024-11-02T15:54:47.060000",
              "content": "<p>I would like to thank you for your help.<br>\nWhile I was working on this file\"https://www.kaggle.com/code/sacuscreed/axial-t2-subarticular-prediction\", I got this error \"https://www.kaggle.com/code/samarkilany/axial-t2-subarticular-prediction\"Did it happen to you too?</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3034873,
              "author_name": "Ángel Jacinto Sánchez Ruiz",
              "author_url": "",
              "post_date": "2024-11-02T17:34:08.967000",
              "content": "<p>I'm running a single fold and EPOCH. That error suggests that the crop failed, may be cause bad centers. That early version had no corrections to centers in order to prevent it. If the experiment I'm running right now crashes I'll check it carefully.</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3034894,
              "author_name": "KS",
              "author_url": "",
              "post_date": "2024-11-02T18:24:27.663000",
              "content": "<p>Error appeared in fold=4 ,but in case fold =1,2,3 not appeared </p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3034899,
              "author_name": "Ángel Jacinto Sánchez Ruiz",
              "author_url": "",
              "post_date": "2024-11-02T18:35:53.520000",
              "content": "<p>Testing fold 4…</p>\n<p>EDIT: <a href=\"https://www.kaggle.com/samarkilany\" target=\"_blank\">@samarkilany</a> Yes, I've got same error. I've just updated dataset. Is no the best solution. But will work. And most importantly, won't affect the samples that crop properly. I don't want to change the original code.</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3035517,
              "author_name": "KS",
              "author_url": "",
              "post_date": "2024-11-03T14:32:04.623000",
              "content": "<p>What do you mean? You updated the data.</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3046285,
              "author_name": "Ángel Jacinto Sánchez Ruiz",
              "author_url": "",
              "post_date": "2024-11-15T10:15:41.947000",
              "content": "<p>Not the data. The function that takes samples from it.</p>",
              "votes": 0,
              "replies": []
            }
          ]
        }
      ]
    }
  ],
  "raw_markdown_by_id": {
    "3012577": "Thank you so much to everyone, especially to organizers and people who shared insights. Has been a long and stressful but enjoyable experience. There is a lot to comment and explain, but at the moment  a summary accross the full process.\n\n**Starting point:**\n\nhttps://www.kaggle.com/code/abhinavsuri/anatomy-image-visualization-overview-rsna-raids\n\nThis notebook introduced me perfectly to the problem and gave me the fundamentals of my approach since first contact. Often professionals base their diagnosis on 2D Sagittal T1 analysis for foraminal, 2D Axial T2 analysis for subarticular and 2D Sagittal T2 and Axial T2 analysis for spinal.\n\nThe main problem is that slices doesn't match perfectly between them, at least without metadata. So I've decided to use a flexible architecture to handle them, Transformers.\n\n**2D UNet for ROI localization in images:**\n\nhttps://www.kaggle.com/code/sacuscreed/sagittal-t1-sagittal-level-segmentation\nhttps://www.kaggle.com/code/sacuscreed/sagittal-t2-sagittal-level-segmentation\nhttps://www.kaggle.com/code/sacuscreed/axial-t2-axial-side-segmentation\n\n![Predicted and True levels](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F6a41878578ada30eaeec0096cdfcab49%2Fsagittal_T1_levels.png?generation=1728465530762952&alt=media)\n\n![Predicted and True levels](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2Fc226ff687bf8f99cd3a4b21ec81cfdd9%2Fsagittal_T2_levels.png?generation=1728465554068790&alt=media)\n\n![Predicted and True sides](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F3b7f8383acbf6c293271b0816cf38a6c%2FAxial_T2_sides.png?generation=1728465338817627&alt=media)\n\nThose coordinates together allowed to point backbone slices in Sagittal T1, spine slices in Sagittal T2 and to assign levels to Axial T2 slices. Special thanks to @hengck23 for [2D to 3D proejection for DICOM](https://www.kaggle.com/code/hengck23/2d-to-3d-projection-for-dicom)\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F5ef923d887223d67aaf5e47ea5f48c0c%2Faxial_sagittal_correspondence.png?generation=1728464895653686&alt=media)\n\nIs important to mention that I've only used competition data. By data processing I've been able to impute coordinates to slices that hasn't been labeled. All slices between left and right labels for forminal, all neighbor slices in a range of D//5 for spinal and neighbor slices for subarticular. Increasing considerably the amount of data available. I've also duplicated Axial T2 slices by flipping images and coordinates properly.\n\n**CNN for ROI localization in crops:**\n\nAt first, I started by feeding Transformer \"full-slice sandwiches\" of the corresponding level or side.\n\n@sergiosaharovskiy \"so it means for your pipeline you do not find the centroid, but rather taking the entire axial slice, which gives 0.47 LB overall :D?\" That's exactly what I did.\n\nBut because the above comment and the unsolved problem of effectively downsample big MRIs, with the consequent possible valuable information loss, I've started to try to find ROI also in crop slices.\n\nhttps://www.kaggle.com/code/sacuscreed/sagittal-t1-foramina-discriminator\nhttps://www.kaggle.com/code/sacuscreed/sagittal-t2-spine-discriminator\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F75a56e4cf4ec31a58a20a31b4f3e117a%2Fspinal_discriminator.png?generation=1728467778513712&alt=media)\n\nAgain naive but reasonable label imputation was a key. Explicitely labeled crops were directly trusted. Immediate neighbors were excluded. And remaining crops were labeled as negatives.\n\nAt first the idea was to directly select the crops of interest of each \"sandwich\" but results were inconsistent so finally I've decided to aproximate ROI with DICOM correspondence between MRIs and use this discriminators as starting encoders for Transformer. Which resulted in considerably smoother trainings.\n\n**DICOM for axial level assignation:**\n\nhttps://www.kaggle.com/code/sacuscreed/getting-true-axial-levels\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F56229cd953a8d408f0cc07626df4db3a%2Fplane_assignments.png?generation=1728489253664414&alt=media)\n\nA direct implementation from [[ver.1] demo workflow: 2-stage approach](url). I've been working in a less literal adaptation. But time ran out and this one worked perfectly. Axial T2 slices are assigned to levels as the closer planes to the respective level coordinates in middle Sagittal slice.\n\n**ViT over crops for final predictions:**\n\nhttps://www.kaggle.com/code/sacuscreed/sagittal-t1-foraminal-prediction\nhttps://www.kaggle.com/code/sacuscreed/sagittal-t2-spinal-prediction\nhttps://www.kaggle.com/code/sacuscreed/axial-t2-subarticular-prediction\nhttps://www.kaggle.com/code/sacuscreed/axial-t2-spinal-prediction-1-4\nhttps://www.kaggle.com/code/sacuscreed/axial-t2-spinal-prediction-5\n\nFinally I've trained five fold CV ViTs feeding Transformer with different sequences of crops using ResNet18 as encoder. Sagittal T1 crops for foraminal predictions:\n\n![Sagittal T1 crops](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F470d3c5e37b1c4bba961d689cf276bca%2Fforaminal_crops.png?generation=1728489469181879&alt=media)\n\nSagittal T2 crops for one source of spinal predictions:\n\n![Sagittal T2 crops](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F42eeaa8b3690521d6246cbf6ab872701%2Fspinal_crops.png?generation=1728489501285059&alt=media)\n\nAxial T2 crops for subarticular predictions:\n\n![Axial T2 subarticular crops](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2F9de6ec6c7d3f23fa502fee861fbedae6%2Faxial_subarticular_crops.png?generation=1728489535332345&alt=media)\n\nAnd Axial T2 crops for second source of spinal predictions:\n\n![Axial T2 spinal crops](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8722753%2Ff754e2eb26416596feab21ba760e68a9%2Faxial_spinal_crops.png?generation=1728489574899812&alt=media)\n\nI've been working cyclically between pathologies trying to transfer what I have learned each time to the next one. Trying to unify architectures. The main structure is a Transformer for crops in each level/side followed by a second Transformer between levels and sides. I've been experimenting with different positional encoding:\n\n1) Learnable or not.\n \n2) Distinguishing sides or not.\n\n3) Absolute or relative to a Lmax as normalized position.\n\nI would say that best approach is to absolute encode crops, with not learnable positional encodings and without distinguish sides. That is grouping second Transformer in sequence of 10 (2 for each level) since sides should be equivalent. The diagnosis shouldn't change depending on what side. I've updated this schema for Sagittal T1 and T2 predictions. But I haven't been able to traslate it to Axial T2 ones. In this case although original trainings were very unstable, they achieved at the end better performance. So I kept them.\n\n**Inference:**\n\nhttps://www.kaggle.com/code/sacuscreed/rsna-private-submission-v2\n\n**Old code:**\n\nhttps://www.kaggle.com/code/sacuscreed/old-axial-t2-axial-side-segmentation\nhttps://www.kaggle.com/code/sacuscreed/old-sagittal-t2-segmentation\nhttps://www.kaggle.com/code/sacuscreed/sagittal-t1-direction-training\nhttps://www.kaggle.com/code/sacuscreed/sagittal-t1-axial-side-segmentation\nhttps://www.kaggle.com/code/sacuscreed/sagittal-t2-axial-spine-segmentation",
    "3025146": "Congratulations🥳\nThanks for sharing your solution\nCan you send the  train_split.csv file ?\n"
  }
}