├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── code ├── 0_input_data_to_S3.ipynb ├── 1_data_preprocess_viz.ipynb ├── 2_model_train_deploy_inference.ipynb └── 3_explainability_CAM.ipynb └── img ├── Image.jpg ├── ich-img-1.png ├── ich-img-2.png ├── ich-img-3.png ├── ich_img_1.png ├── ich_img_2.png ├── ich_img_3.png ├── ich_img_4.png ├── ich_img_5.png └── prioritization-steps.jpg /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | 3 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 4 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 5 | opensource-codeofconduct@amazon.com with any additional questions or comments. 6 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | ## Reporting Bugs/Feature Requests 10 | 11 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 12 | 13 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 14 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 15 | 16 | - A reproducible test case or series of steps 17 | - The version of our code being used 18 | - Any modifications you've made relevant to the bug 19 | - Anything unusual about your environment or deployment 20 | 21 | ## Contributing via Pull Requests 22 | 23 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 24 | 25 | 1. You are working against the latest source on the _main_ branch. 26 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 27 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 28 | 29 | To send us a pull request, please: 30 | 31 | 1. Fork the repository. 32 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 33 | 3. Ensure local tests pass. 34 | 4. Commit to your fork using clear commit messages. 35 | 5. Send us a pull request, answering any default questions in the pull request interface. 36 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 37 | 38 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 39 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 40 | 41 | ## Finding contributions to work on 42 | 43 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 44 | 45 | ## Code of Conduct 46 | 47 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 48 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 49 | opensource-codeofconduct@amazon.com with any additional questions or comments. 50 | 51 | ## Security issue notifications 52 | 53 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 54 | 55 | ## Licensing 56 | 57 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 58 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | software and associated documentation files (the "Software"), to deal in the Software 5 | without restriction, including without limitation the rights to use, copy, modify, 6 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 10 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 11 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 12 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 13 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 14 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Explainable Intracranial Hemorrhage Detection for Radiologist Workflow Prioritization 2 | 3 | Intracranial hemorrhage, a severe medical condition occurring within the cranium, necessitates rapid and intensive medical intervention. This condition contributes significantly to stroke cases, which rank as the fifth-leading cause of death in the United States. Timely and accurate identification of the hemorrhage's location and type is paramount for effective patient treatment. To address this urgent medical need, we explore the impact of integrating AI and machine learning in radiology workflows. By using computer vision models and explainable AI to reprioritize worklists, we aim to enhance the efficiency and effectiveness of diagnosing intracranial hemorrhage. This process promises to streamline patient care, reduce the time to diagnosis, and ultimately improve patient outcomes in clinical settings. 4 | ![Worklist prioritization steps](img/prioritization-steps.jpg) 5 | 6 | ## Data Collection and Loading 7 | The ICH data was collected from the [RSNA Intracranial Hemorrhage Detection](https://www.kaggle.com/competitions/rsna-intracranial-hemorrhage-detection/data) challenge which was designed to identify acute intracranial hemorrhage. Intracranial hemorrhage is a serious condition caused by various factors, including trauma and high blood pressure, leading to symptoms that can range from headaches to life-threatening complications. Radiologists are key in detecting and assessing the hemorrhage to guide potential emergency surgical decisions. For this work, we used labeled data for both hemorrhage and non-hemorrhage examples. 8 | ![Examples of ICH](img/ich-img-1.png) 9 | 10 | ## Data Pre-processing 11 | 12 | To start we pre-processed the labels into two classes - `normal` (no-hemorrhage) and `hemorrhage`. This enables us to create a solution with a binary class instead of the multi-class / multi-label approach with different types of ICH. The CT images have a large dynamic range (12-16 bits) that cannot be fully displayed on a monitor. To highlight different intensity ranges, radiologists apply multiple window settings like brain (level 40/width 80), subdural (level 80/width 200), and bone (level 600/width 2800) windows when reviewing scans. These settings make abnormalities more conspicuous. To mimic this workflow, we preprocess each image by applying the three window settings and converting the results to 8-bit grayscale images. The three grayscale images are assembled as the RGB channels of an image and used as input to the 2D CNN classifier. 13 | 14 | ![Data sample](img/ich-img-2.png) 15 | 16 | ## Model Development 17 | The code trains a deep learning model on an intracranial hemorrhage dataset. It attaches a classification layer to a feature extractor model from TensorFlow/PyTorch hub and initializes the layer parameters randomly. The classification layer output matches the number of classes. Fine-tuning minimizes classification error on the input data for deployment. The training data must be formatted into subdirectories per class with .jpg images. The code saves the trained model and a label mapping file to an S3 bucket. It allows setting training job parameters like data path, output path, and instance type. It also sets algorithm hyperparameters. After training, the code can deploy the model for inference. 18 | 19 | ## Explainable Computer Vision with Class Activation Maps 20 | Grad-CAM (Gradient-weighted Class Activation Mapping) is a technique that produces visual explanations for decisions from convolutional neural networks. It uses the gradients flowing into the last convolutional layer to produce a heat map highlighting important regions in the image for predicting the outcome. A key advantage of Grad-CAM is that it can be applied to any CNN-based model after training, without needing to modify the architecture. It computes the gradient of the target class score with respect to the feature maps of the last convolutional layer. These gradients are pooled globally to obtain importance weights, which are used to take a weighted combination of the feature maps to highlight the relevant regions. This provides an intuitive visualization of where the model is focusing to make decisions. We implemented the Grad-CAM using this [library](https://github.com/jacobgil/pytorch-grad-cam). 21 | 22 | ![Grad-CAM](img/ich-img-3.png) 23 | 24 | ## Authors and acknowledgment 25 | Special thanks to Ekta Walia Bhullar, Priya Padate, and Wale Akinfaderin for their contributions to this project and sharing their expertise in this field. 26 | 27 | ## License 28 | This library is licensed under the MIT-0 License. See the LICENSE file. 29 | -------------------------------------------------------------------------------- /code/0_input_data_to_S3.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "5ada48b9-9d3f-424e-a3e8-b3480ceb412b", 6 | "metadata": {}, 7 | "source": [ 8 | "## Import ICH data from Kaggle and upload to S3" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": null, 14 | "id": "d69b0be2-c5c5-4ed6-910d-9989c130c34b", 15 | "metadata": { 16 | "tags": [] 17 | }, 18 | "outputs": [], 19 | "source": [ 20 | "!python3 -m pip install kaggle" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": null, 26 | "id": "dbec69e9-d940-4c5f-bbc0-720443d5e546", 27 | "metadata": { 28 | "tags": [] 29 | }, 30 | "outputs": [], 31 | "source": [ 32 | "import fnmatch\n", 33 | "import os\n", 34 | "import json \n" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": null, 40 | "id": "f57a16c4-cf27-4bb9-9f56-15dabed58b9c", 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "!mkdir ~/.kaggle" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": null, 50 | "id": "d3953564-40ac-4a69-8a90-9469cbf3a327", 51 | "metadata": { 52 | "tags": [] 53 | }, 54 | "outputs": [], 55 | "source": [ 56 | "!touch ~/.kaggle/kaggle.json" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "id": "18e237bd-1685-428c-8848-4433ed10539a", 63 | "metadata": { 64 | "tags": [] 65 | }, 66 | "outputs": [], 67 | "source": [ 68 | "#Define your kaggle API credentials\n", 69 | "kaggle_api_token = {\"username\":\"\",\"key\":\"\"}" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": null, 75 | "id": "7c81c807-dfaf-4dae-9438-95f17349d123", 76 | "metadata": { 77 | "tags": [] 78 | }, 79 | "outputs": [], 80 | "source": [ 81 | "# Writes API Credentials to Kaggle file\n", 82 | "file_path = os.path.expanduser('~/.kaggle/kaggle.json')\n", 83 | "with open(file_path, 'w') as file:\n", 84 | " json.dump(kaggle_api_token, file)" 85 | ] 86 | }, 87 | { 88 | "cell_type": "code", 89 | "execution_count": null, 90 | "id": "5eb9027e-9408-492b-a8b1-5e7530399174", 91 | "metadata": { 92 | "tags": [] 93 | }, 94 | "outputs": [], 95 | "source": [ 96 | "!chmod 600 ~/.kaggle/kaggle.json" 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": null, 102 | "id": "063e63cc-4572-4aab-93fb-9202eeff8cea", 103 | "metadata": { 104 | "tags": [] 105 | }, 106 | "outputs": [], 107 | "source": [ 108 | "!kaggle --version" 109 | ] 110 | }, 111 | { 112 | "cell_type": "code", 113 | "execution_count": null, 114 | "id": "06e30ff3-1a66-4144-931c-425b0f947525", 115 | "metadata": { 116 | "tags": [] 117 | }, 118 | "outputs": [], 119 | "source": [ 120 | "!kaggle competitions download -c rsna-intracranial-hemorrhage-detection" 121 | ] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "execution_count": null, 126 | "id": "3e14d51f-d602-4c00-80b3-971b07edf035", 127 | "metadata": {}, 128 | "outputs": [], 129 | "source": [ 130 | "#Save to S3 Bucket\n", 131 | "%%timeit\n", 132 | "\n", 133 | "!aws s3 sync rsna-intracranial-hemorrhage-detection \"\"" 134 | ] 135 | }, 136 | { 137 | "cell_type": "code", 138 | "execution_count": null, 139 | "id": "e3982e0e-9e82-4008-b452-f1fc27821931", 140 | "metadata": {}, 141 | "outputs": [], 142 | "source": [] 143 | } 144 | ], 145 | "metadata": { 146 | "availableInstances": [ 147 | { 148 | "_defaultOrder": 0, 149 | "_isFastLaunch": true, 150 | "category": "General purpose", 151 | "gpuNum": 0, 152 | "hideHardwareSpecs": false, 153 | "memoryGiB": 4, 154 | "name": "ml.t3.medium", 155 | "vcpuNum": 2 156 | }, 157 | { 158 | "_defaultOrder": 1, 159 | "_isFastLaunch": false, 160 | "category": "General purpose", 161 | "gpuNum": 0, 162 | "hideHardwareSpecs": false, 163 | "memoryGiB": 8, 164 | "name": "ml.t3.large", 165 | "vcpuNum": 2 166 | }, 167 | { 168 | "_defaultOrder": 2, 169 | "_isFastLaunch": false, 170 | "category": "General purpose", 171 | "gpuNum": 0, 172 | "hideHardwareSpecs": false, 173 | "memoryGiB": 16, 174 | "name": "ml.t3.xlarge", 175 | "vcpuNum": 4 176 | }, 177 | { 178 | "_defaultOrder": 3, 179 | "_isFastLaunch": false, 180 | "category": "General purpose", 181 | "gpuNum": 0, 182 | "hideHardwareSpecs": false, 183 | "memoryGiB": 32, 184 | "name": "ml.t3.2xlarge", 185 | "vcpuNum": 8 186 | }, 187 | { 188 | "_defaultOrder": 4, 189 | "_isFastLaunch": true, 190 | "category": "General purpose", 191 | "gpuNum": 0, 192 | "hideHardwareSpecs": false, 193 | "memoryGiB": 8, 194 | "name": "ml.m5.large", 195 | "vcpuNum": 2 196 | }, 197 | { 198 | "_defaultOrder": 5, 199 | "_isFastLaunch": false, 200 | "category": "General purpose", 201 | "gpuNum": 0, 202 | "hideHardwareSpecs": false, 203 | "memoryGiB": 16, 204 | "name": "ml.m5.xlarge", 205 | "vcpuNum": 4 206 | }, 207 | { 208 | "_defaultOrder": 6, 209 | "_isFastLaunch": false, 210 | "category": "General purpose", 211 | "gpuNum": 0, 212 | "hideHardwareSpecs": false, 213 | "memoryGiB": 32, 214 | "name": "ml.m5.2xlarge", 215 | "vcpuNum": 8 216 | }, 217 | { 218 | "_defaultOrder": 7, 219 | "_isFastLaunch": false, 220 | "category": "General purpose", 221 | "gpuNum": 0, 222 | "hideHardwareSpecs": false, 223 | "memoryGiB": 64, 224 | "name": "ml.m5.4xlarge", 225 | "vcpuNum": 16 226 | }, 227 | { 228 | "_defaultOrder": 8, 229 | "_isFastLaunch": false, 230 | "category": "General purpose", 231 | "gpuNum": 0, 232 | "hideHardwareSpecs": false, 233 | "memoryGiB": 128, 234 | "name": "ml.m5.8xlarge", 235 | "vcpuNum": 32 236 | }, 237 | { 238 | "_defaultOrder": 9, 239 | "_isFastLaunch": false, 240 | "category": "General purpose", 241 | "gpuNum": 0, 242 | "hideHardwareSpecs": false, 243 | "memoryGiB": 192, 244 | "name": "ml.m5.12xlarge", 245 | "vcpuNum": 48 246 | }, 247 | { 248 | "_defaultOrder": 10, 249 | "_isFastLaunch": false, 250 | "category": "General purpose", 251 | "gpuNum": 0, 252 | "hideHardwareSpecs": false, 253 | "memoryGiB": 256, 254 | "name": "ml.m5.16xlarge", 255 | "vcpuNum": 64 256 | }, 257 | { 258 | "_defaultOrder": 11, 259 | "_isFastLaunch": false, 260 | "category": "General purpose", 261 | "gpuNum": 0, 262 | "hideHardwareSpecs": false, 263 | "memoryGiB": 384, 264 | "name": "ml.m5.24xlarge", 265 | "vcpuNum": 96 266 | }, 267 | { 268 | "_defaultOrder": 12, 269 | "_isFastLaunch": false, 270 | "category": "General purpose", 271 | "gpuNum": 0, 272 | "hideHardwareSpecs": false, 273 | "memoryGiB": 8, 274 | "name": "ml.m5d.large", 275 | "vcpuNum": 2 276 | }, 277 | { 278 | "_defaultOrder": 13, 279 | "_isFastLaunch": false, 280 | "category": "General purpose", 281 | "gpuNum": 0, 282 | "hideHardwareSpecs": false, 283 | "memoryGiB": 16, 284 | "name": "ml.m5d.xlarge", 285 | "vcpuNum": 4 286 | }, 287 | { 288 | "_defaultOrder": 14, 289 | "_isFastLaunch": false, 290 | "category": "General purpose", 291 | "gpuNum": 0, 292 | "hideHardwareSpecs": false, 293 | "memoryGiB": 32, 294 | "name": "ml.m5d.2xlarge", 295 | "vcpuNum": 8 296 | }, 297 | { 298 | "_defaultOrder": 15, 299 | "_isFastLaunch": false, 300 | "category": "General purpose", 301 | "gpuNum": 0, 302 | "hideHardwareSpecs": false, 303 | "memoryGiB": 64, 304 | "name": "ml.m5d.4xlarge", 305 | "vcpuNum": 16 306 | }, 307 | { 308 | "_defaultOrder": 16, 309 | "_isFastLaunch": false, 310 | "category": "General purpose", 311 | "gpuNum": 0, 312 | "hideHardwareSpecs": false, 313 | "memoryGiB": 128, 314 | "name": "ml.m5d.8xlarge", 315 | "vcpuNum": 32 316 | }, 317 | { 318 | "_defaultOrder": 17, 319 | "_isFastLaunch": false, 320 | "category": "General purpose", 321 | "gpuNum": 0, 322 | "hideHardwareSpecs": false, 323 | "memoryGiB": 192, 324 | "name": "ml.m5d.12xlarge", 325 | "vcpuNum": 48 326 | }, 327 | { 328 | "_defaultOrder": 18, 329 | "_isFastLaunch": false, 330 | "category": "General purpose", 331 | "gpuNum": 0, 332 | "hideHardwareSpecs": false, 333 | "memoryGiB": 256, 334 | "name": "ml.m5d.16xlarge", 335 | "vcpuNum": 64 336 | }, 337 | { 338 | "_defaultOrder": 19, 339 | "_isFastLaunch": false, 340 | "category": "General purpose", 341 | "gpuNum": 0, 342 | "hideHardwareSpecs": false, 343 | "memoryGiB": 384, 344 | "name": "ml.m5d.24xlarge", 345 | "vcpuNum": 96 346 | }, 347 | { 348 | "_defaultOrder": 20, 349 | "_isFastLaunch": false, 350 | "category": "General purpose", 351 | "gpuNum": 0, 352 | "hideHardwareSpecs": true, 353 | "memoryGiB": 0, 354 | "name": "ml.geospatial.interactive", 355 | "supportedImageNames": [ 356 | "sagemaker-geospatial-v1-0" 357 | ], 358 | "vcpuNum": 0 359 | }, 360 | { 361 | "_defaultOrder": 21, 362 | "_isFastLaunch": true, 363 | "category": "Compute optimized", 364 | "gpuNum": 0, 365 | "hideHardwareSpecs": false, 366 | "memoryGiB": 4, 367 | "name": "ml.c5.large", 368 | "vcpuNum": 2 369 | }, 370 | { 371 | "_defaultOrder": 22, 372 | "_isFastLaunch": false, 373 | "category": "Compute optimized", 374 | "gpuNum": 0, 375 | "hideHardwareSpecs": false, 376 | "memoryGiB": 8, 377 | "name": "ml.c5.xlarge", 378 | "vcpuNum": 4 379 | }, 380 | { 381 | "_defaultOrder": 23, 382 | "_isFastLaunch": false, 383 | "category": "Compute optimized", 384 | "gpuNum": 0, 385 | "hideHardwareSpecs": false, 386 | "memoryGiB": 16, 387 | "name": "ml.c5.2xlarge", 388 | "vcpuNum": 8 389 | }, 390 | { 391 | "_defaultOrder": 24, 392 | "_isFastLaunch": false, 393 | "category": "Compute optimized", 394 | "gpuNum": 0, 395 | "hideHardwareSpecs": false, 396 | "memoryGiB": 32, 397 | "name": "ml.c5.4xlarge", 398 | "vcpuNum": 16 399 | }, 400 | { 401 | "_defaultOrder": 25, 402 | "_isFastLaunch": false, 403 | "category": "Compute optimized", 404 | "gpuNum": 0, 405 | "hideHardwareSpecs": false, 406 | "memoryGiB": 72, 407 | "name": "ml.c5.9xlarge", 408 | "vcpuNum": 36 409 | }, 410 | { 411 | "_defaultOrder": 26, 412 | "_isFastLaunch": false, 413 | "category": "Compute optimized", 414 | "gpuNum": 0, 415 | "hideHardwareSpecs": false, 416 | "memoryGiB": 96, 417 | "name": "ml.c5.12xlarge", 418 | "vcpuNum": 48 419 | }, 420 | { 421 | "_defaultOrder": 27, 422 | "_isFastLaunch": false, 423 | "category": "Compute optimized", 424 | "gpuNum": 0, 425 | "hideHardwareSpecs": false, 426 | "memoryGiB": 144, 427 | "name": "ml.c5.18xlarge", 428 | "vcpuNum": 72 429 | }, 430 | { 431 | "_defaultOrder": 28, 432 | "_isFastLaunch": false, 433 | "category": "Compute optimized", 434 | "gpuNum": 0, 435 | "hideHardwareSpecs": false, 436 | "memoryGiB": 192, 437 | "name": "ml.c5.24xlarge", 438 | "vcpuNum": 96 439 | }, 440 | { 441 | "_defaultOrder": 29, 442 | "_isFastLaunch": true, 443 | "category": "Accelerated computing", 444 | "gpuNum": 1, 445 | "hideHardwareSpecs": false, 446 | "memoryGiB": 16, 447 | "name": "ml.g4dn.xlarge", 448 | "vcpuNum": 4 449 | }, 450 | { 451 | "_defaultOrder": 30, 452 | "_isFastLaunch": false, 453 | "category": "Accelerated computing", 454 | "gpuNum": 1, 455 | "hideHardwareSpecs": false, 456 | "memoryGiB": 32, 457 | "name": "ml.g4dn.2xlarge", 458 | "vcpuNum": 8 459 | }, 460 | { 461 | "_defaultOrder": 31, 462 | "_isFastLaunch": false, 463 | "category": "Accelerated computing", 464 | "gpuNum": 1, 465 | "hideHardwareSpecs": false, 466 | "memoryGiB": 64, 467 | "name": "ml.g4dn.4xlarge", 468 | "vcpuNum": 16 469 | }, 470 | { 471 | "_defaultOrder": 32, 472 | "_isFastLaunch": false, 473 | "category": "Accelerated computing", 474 | "gpuNum": 1, 475 | "hideHardwareSpecs": false, 476 | "memoryGiB": 128, 477 | "name": "ml.g4dn.8xlarge", 478 | "vcpuNum": 32 479 | }, 480 | { 481 | "_defaultOrder": 33, 482 | "_isFastLaunch": false, 483 | "category": "Accelerated computing", 484 | "gpuNum": 4, 485 | "hideHardwareSpecs": false, 486 | "memoryGiB": 192, 487 | "name": "ml.g4dn.12xlarge", 488 | "vcpuNum": 48 489 | }, 490 | { 491 | "_defaultOrder": 34, 492 | "_isFastLaunch": false, 493 | "category": "Accelerated computing", 494 | "gpuNum": 1, 495 | "hideHardwareSpecs": false, 496 | "memoryGiB": 256, 497 | "name": "ml.g4dn.16xlarge", 498 | "vcpuNum": 64 499 | }, 500 | { 501 | "_defaultOrder": 35, 502 | "_isFastLaunch": false, 503 | "category": "Accelerated computing", 504 | "gpuNum": 1, 505 | "hideHardwareSpecs": false, 506 | "memoryGiB": 61, 507 | "name": "ml.p3.2xlarge", 508 | "vcpuNum": 8 509 | }, 510 | { 511 | "_defaultOrder": 36, 512 | "_isFastLaunch": false, 513 | "category": "Accelerated computing", 514 | "gpuNum": 4, 515 | "hideHardwareSpecs": false, 516 | "memoryGiB": 244, 517 | "name": "ml.p3.8xlarge", 518 | "vcpuNum": 32 519 | }, 520 | { 521 | "_defaultOrder": 37, 522 | "_isFastLaunch": false, 523 | "category": "Accelerated computing", 524 | "gpuNum": 8, 525 | "hideHardwareSpecs": false, 526 | "memoryGiB": 488, 527 | "name": "ml.p3.16xlarge", 528 | "vcpuNum": 64 529 | }, 530 | { 531 | "_defaultOrder": 38, 532 | "_isFastLaunch": false, 533 | "category": "Accelerated computing", 534 | "gpuNum": 8, 535 | "hideHardwareSpecs": false, 536 | "memoryGiB": 768, 537 | "name": "ml.p3dn.24xlarge", 538 | "vcpuNum": 96 539 | }, 540 | { 541 | "_defaultOrder": 39, 542 | "_isFastLaunch": false, 543 | "category": "Memory Optimized", 544 | "gpuNum": 0, 545 | "hideHardwareSpecs": false, 546 | "memoryGiB": 16, 547 | "name": "ml.r5.large", 548 | "vcpuNum": 2 549 | }, 550 | { 551 | "_defaultOrder": 40, 552 | "_isFastLaunch": false, 553 | "category": "Memory Optimized", 554 | "gpuNum": 0, 555 | "hideHardwareSpecs": false, 556 | "memoryGiB": 32, 557 | "name": "ml.r5.xlarge", 558 | "vcpuNum": 4 559 | }, 560 | { 561 | "_defaultOrder": 41, 562 | "_isFastLaunch": false, 563 | "category": "Memory Optimized", 564 | "gpuNum": 0, 565 | "hideHardwareSpecs": false, 566 | "memoryGiB": 64, 567 | "name": "ml.r5.2xlarge", 568 | "vcpuNum": 8 569 | }, 570 | { 571 | "_defaultOrder": 42, 572 | "_isFastLaunch": false, 573 | "category": "Memory Optimized", 574 | "gpuNum": 0, 575 | "hideHardwareSpecs": false, 576 | "memoryGiB": 128, 577 | "name": "ml.r5.4xlarge", 578 | "vcpuNum": 16 579 | }, 580 | { 581 | "_defaultOrder": 43, 582 | "_isFastLaunch": false, 583 | "category": "Memory Optimized", 584 | "gpuNum": 0, 585 | "hideHardwareSpecs": false, 586 | "memoryGiB": 256, 587 | "name": "ml.r5.8xlarge", 588 | "vcpuNum": 32 589 | }, 590 | { 591 | "_defaultOrder": 44, 592 | "_isFastLaunch": false, 593 | "category": "Memory Optimized", 594 | "gpuNum": 0, 595 | "hideHardwareSpecs": false, 596 | "memoryGiB": 384, 597 | "name": "ml.r5.12xlarge", 598 | "vcpuNum": 48 599 | }, 600 | { 601 | "_defaultOrder": 45, 602 | "_isFastLaunch": false, 603 | "category": "Memory Optimized", 604 | "gpuNum": 0, 605 | "hideHardwareSpecs": false, 606 | "memoryGiB": 512, 607 | "name": "ml.r5.16xlarge", 608 | "vcpuNum": 64 609 | }, 610 | { 611 | "_defaultOrder": 46, 612 | "_isFastLaunch": false, 613 | "category": "Memory Optimized", 614 | "gpuNum": 0, 615 | "hideHardwareSpecs": false, 616 | "memoryGiB": 768, 617 | "name": "ml.r5.24xlarge", 618 | "vcpuNum": 96 619 | }, 620 | { 621 | "_defaultOrder": 47, 622 | "_isFastLaunch": false, 623 | "category": "Accelerated computing", 624 | "gpuNum": 1, 625 | "hideHardwareSpecs": false, 626 | "memoryGiB": 16, 627 | "name": "ml.g5.xlarge", 628 | "vcpuNum": 4 629 | }, 630 | { 631 | "_defaultOrder": 48, 632 | "_isFastLaunch": false, 633 | "category": "Accelerated computing", 634 | "gpuNum": 1, 635 | "hideHardwareSpecs": false, 636 | "memoryGiB": 32, 637 | "name": "ml.g5.2xlarge", 638 | "vcpuNum": 8 639 | }, 640 | { 641 | "_defaultOrder": 49, 642 | "_isFastLaunch": false, 643 | "category": "Accelerated computing", 644 | "gpuNum": 1, 645 | "hideHardwareSpecs": false, 646 | "memoryGiB": 64, 647 | "name": "ml.g5.4xlarge", 648 | "vcpuNum": 16 649 | }, 650 | { 651 | "_defaultOrder": 50, 652 | "_isFastLaunch": false, 653 | "category": "Accelerated computing", 654 | "gpuNum": 1, 655 | "hideHardwareSpecs": false, 656 | "memoryGiB": 128, 657 | "name": "ml.g5.8xlarge", 658 | "vcpuNum": 32 659 | }, 660 | { 661 | "_defaultOrder": 51, 662 | "_isFastLaunch": false, 663 | "category": "Accelerated computing", 664 | "gpuNum": 1, 665 | "hideHardwareSpecs": false, 666 | "memoryGiB": 256, 667 | "name": "ml.g5.16xlarge", 668 | "vcpuNum": 64 669 | }, 670 | { 671 | "_defaultOrder": 52, 672 | "_isFastLaunch": false, 673 | "category": "Accelerated computing", 674 | "gpuNum": 4, 675 | "hideHardwareSpecs": false, 676 | "memoryGiB": 192, 677 | "name": "ml.g5.12xlarge", 678 | "vcpuNum": 48 679 | }, 680 | { 681 | "_defaultOrder": 53, 682 | "_isFastLaunch": false, 683 | "category": "Accelerated computing", 684 | "gpuNum": 4, 685 | "hideHardwareSpecs": false, 686 | "memoryGiB": 384, 687 | "name": "ml.g5.24xlarge", 688 | "vcpuNum": 96 689 | }, 690 | { 691 | "_defaultOrder": 54, 692 | "_isFastLaunch": false, 693 | "category": "Accelerated computing", 694 | "gpuNum": 8, 695 | "hideHardwareSpecs": false, 696 | "memoryGiB": 768, 697 | "name": "ml.g5.48xlarge", 698 | "vcpuNum": 192 699 | }, 700 | { 701 | "_defaultOrder": 55, 702 | "_isFastLaunch": false, 703 | "category": "Accelerated computing", 704 | "gpuNum": 8, 705 | "hideHardwareSpecs": false, 706 | "memoryGiB": 1152, 707 | "name": "ml.p4d.24xlarge", 708 | "vcpuNum": 96 709 | }, 710 | { 711 | "_defaultOrder": 56, 712 | "_isFastLaunch": false, 713 | "category": "Accelerated computing", 714 | "gpuNum": 8, 715 | "hideHardwareSpecs": false, 716 | "memoryGiB": 1152, 717 | "name": "ml.p4de.24xlarge", 718 | "vcpuNum": 96 719 | } 720 | ], 721 | "instance_type": "ml.t3.medium", 722 | "kernelspec": { 723 | "display_name": "Python 3 (Data Science 3.0)", 724 | "language": "python", 725 | "name": "python3__SAGEMAKER_INTERNAL__arn:aws:sagemaker:us-east-1:081325390199:image/sagemaker-data-science-310-v1" 726 | }, 727 | "language_info": { 728 | "codemirror_mode": { 729 | "name": "ipython", 730 | "version": 3 731 | }, 732 | "file_extension": ".py", 733 | "mimetype": "text/x-python", 734 | "name": "python", 735 | "nbconvert_exporter": "python", 736 | "pygments_lexer": "ipython3", 737 | "version": "3.10.6" 738 | } 739 | }, 740 | "nbformat": 4, 741 | "nbformat_minor": 5 742 | } 743 | -------------------------------------------------------------------------------- /code/1_data_preprocess_viz.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "f33bf1a9-0112-43ef-8ccc-d95c3f5f738b", 6 | "metadata": {}, 7 | "source": [ 8 | "## Install and Import Libraries" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": null, 14 | "id": "756fd9c3-442b-439a-96be-e21474e07d2e", 15 | "metadata": { 16 | "tags": [] 17 | }, 18 | "outputs": [], 19 | "source": [ 20 | "!pip install pydicom" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": null, 26 | "id": "267dd170-23d8-4052-b26f-7464d412d296", 27 | "metadata": { 28 | "tags": [] 29 | }, 30 | "outputs": [], 31 | "source": [ 32 | "import glob, pylab, pandas as pd\n", 33 | "import cv2\n", 34 | "import pydicom, numpy as np\n", 35 | "from os import listdir\n", 36 | "from os.path import isfile, join\n", 37 | "import matplotlib.pylab as plt\n", 38 | "import os\n", 39 | "import seaborn as sns\n", 40 | "import tensorflow as tf\n", 41 | "from tqdm import tqdm\n", 42 | "import joblib\n", 43 | "import PIL\n", 44 | "import json\n", 45 | "import seaborn as sns\n", 46 | "from collections import Counter\n", 47 | "from PIL import Image\n", 48 | "import math\n", 49 | "from collections import defaultdict\n", 50 | "from pathlib import Path\n", 51 | "import re\n", 52 | "import logging as l\n", 53 | "from glob import glob\n", 54 | "import argparse" 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "id": "4755c63f-7d27-46e7-8d42-2907d63ed29e", 60 | "metadata": {}, 61 | "source": [ 62 | "## Load and Preprocess Data" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": null, 68 | "id": "a408c695-1fdc-4856-b091-2978f17844ca", 69 | "metadata": { 70 | "tags": [] 71 | }, 72 | "outputs": [], 73 | "source": [ 74 | "#Load and Preprocess labels\n", 75 | "label = pd.read_csv(\"\")\n", 76 | "label = label[label['ID'].str.contains('any')].reset_index(drop=True)\n", 77 | "label['ID'] = label['ID'].str[:-4]\n", 78 | "label['ID'] = label['ID'].astype(str) + '.dcm'" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": null, 84 | "id": "3ac7f9a2-b959-4ed4-bd1d-73bddb3fdbc2", 85 | "metadata": { 86 | "tags": [] 87 | }, 88 | "outputs": [], 89 | "source": [ 90 | "train_images_dir = ''\n", 91 | "train_images = [f for f in listdir(train_images_dir) if isfile(join(train_images_dir, f))]" 92 | ] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "id": "f347eddf-9993-48d5-8c0e-9346147992f6", 97 | "metadata": {}, 98 | "source": [ 99 | "### Plot Sample Data" 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": null, 105 | "id": "19e96d57-04ec-40a7-a66b-096ea47794b1", 106 | "metadata": {}, 107 | "outputs": [], 108 | "source": [ 109 | "fig=plt.figure(figsize=(20, 12))\n", 110 | "columns = 5; rows = 3\n", 111 | "for i in range(1, columns*rows +1):\n", 112 | " ds = pydicom.dcmread(train_images_dir + train_images[i])\n", 113 | " fig.add_subplot(rows, columns, i)\n", 114 | " plt.imshow(ds.pixel_array, cmap=plt.cm.bone)\n", 115 | " fig.add_subplot" 116 | ] 117 | }, 118 | { 119 | "cell_type": "markdown", 120 | "id": "ce6149f2-efff-40ba-aa76-7b176a255736", 121 | "metadata": {}, 122 | "source": [ 123 | "### Plot ICH vs ICH label distribution" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": null, 129 | "id": "0b3160f9-04ec-444c-a1a4-927dea9ff112", 130 | "metadata": { 131 | "tags": [] 132 | }, 133 | "outputs": [], 134 | "source": [ 135 | "plt.style.use('seaborn-bright')\n", 136 | "ax = label['Label'].value_counts().plot(kind='barh', figsize=(11,5),fontsize=14, color=['C0', 'C2']);\n", 137 | "ax.set_alpha(0.8)\n", 138 | "ax.set_xlabel(\"Hemorrhage and No-Hemorrhage Label Counts\", fontsize=18);\n", 139 | "ax.set_xlim(0, 720000)\n", 140 | "#ax.set_yticks(['Hemorrhage', 'No-Hemorrhage'])\n", 141 | "\n", 142 | "labels = [item.get_text() for item in ax.get_yticklabels()]\n", 143 | "labels = ['No-Hemorrhage', 'Hemorrhage']\n", 144 | "ax.set_yticklabels(labels)\n", 145 | "\n", 146 | "# create a list to collect the plt.patches data\n", 147 | "totals = []\n", 148 | "# find the values and append to list\n", 149 | "for i in ax.patches:\n", 150 | " totals.append(i.get_width())\n", 151 | "# set individual bar lables using above list\n", 152 | "total = sum(totals)\n", 153 | "# set individual bar lables using above list\n", 154 | "for i in ax.patches:\n", 155 | " # get_width pulls left or right; get_y pushes up or down\n", 156 | " ax.text(i.get_width()+.3, i.get_y()+.38, \\\n", 157 | " str(round((i.get_width()/total)*100, 2))+'%', fontsize=16,\n", 158 | "color='black')\n", 159 | "# invert for largest on top\n", 160 | "ax.invert_yaxis()\n", 161 | "ax.grid()\n", 162 | "ax.figure.savefig('hemorrhage_label_plot.png', dpi = 300, bbox_inches='tight')" 163 | ] 164 | }, 165 | { 166 | "cell_type": "code", 167 | "execution_count": null, 168 | "id": "1a1e76f5-6c12-44cf-8207-d58ad6cef26a", 169 | "metadata": { 170 | "tags": [] 171 | }, 172 | "outputs": [], 173 | "source": [ 174 | "from sklearn.model_selection import train_test_split\n", 175 | "\n", 176 | "df_train, df_test = train_test_split(df, test_size=0.10, stratify=df[[\"Label\"]])\n", 177 | "\n", 178 | "df_train_1 = df_train['ID'][df_train['Label'] == 1].to_list()\n", 179 | "df_train_0 = df_train['ID'][df_train['Label'] == 0].to_list()\n", 180 | "\n", 181 | "df_test_1 = df_test['ID'][df_test['Label'] == 1].to_list()\n", 182 | "df_test_0 = df_test['ID'][df_test['Label'] == 0].to_list()" 183 | ] 184 | }, 185 | { 186 | "cell_type": "markdown", 187 | "id": "2d0e7f4e-d372-4d41-a029-449ec6afd1a2", 188 | "metadata": {}, 189 | "source": [ 190 | "## Data Processing - Rescale, Resize and Convert to JPG" 191 | ] 192 | }, 193 | { 194 | "cell_type": "code", 195 | "execution_count": null, 196 | "id": "f594bfb0-81f8-4c40-9a2d-2031aec7f19b", 197 | "metadata": {}, 198 | "outputs": [], 199 | "source": [ 200 | "dir_src = ''\n", 201 | "dir_dst_train_0 = ''\n", 202 | "dir_dst_train_1 = ''\n", 203 | "\n", 204 | "def tranfer_train_data(filelist, source, destination):\n", 205 | " for i in filelist[1:]: \n", 206 | " shutil.copy(os.path.join(source, i), destination)" 207 | ] 208 | }, 209 | { 210 | "cell_type": "code", 211 | "execution_count": null, 212 | "id": "e0ad1479-ed47-40cd-98dd-26c99920a5e1", 213 | "metadata": { 214 | "tags": [] 215 | }, 216 | "outputs": [], 217 | "source": [ 218 | "tranfer_train_data(df_train_0, dir_src, dir_dst_train_0)\n", 219 | "tranfer_train_data(df_train_1, dir_src, dir_dst_train_1)" 220 | ] 221 | }, 222 | { 223 | "cell_type": "code", 224 | "execution_count": null, 225 | "id": "dfeb951c-37da-4592-98b1-f6216c92b5fe", 226 | "metadata": { 227 | "tags": [] 228 | }, 229 | "outputs": [], 230 | "source": [ 231 | "import joblib\n", 232 | "import PIL\n", 233 | "from glob import glob\n", 234 | "import pydicom\n", 235 | "import numpy as np\n", 236 | "import pandas as pd\n", 237 | "import os\n", 238 | "import cv2\n", 239 | "import json\n", 240 | "import matplotlib.pyplot as plt\n", 241 | "import seaborn as sns\n", 242 | "from collections import Counter\n", 243 | "from PIL import Image\n", 244 | "import math\n", 245 | "import seaborn as sns\n", 246 | "from collections import defaultdict\n", 247 | "from pathlib import Path\n", 248 | "import cv2\n", 249 | "from tqdm import tqdm\n", 250 | "import re\n", 251 | "import logging as l\n", 252 | "from glob import glob\n", 253 | "import argparse\n", 254 | "\n", 255 | "def get_first_of_dicom_field_as_int(x):\n", 256 | " if type(x) == pydicom.multival.MultiValue:\n", 257 | " return int(x[0])\n", 258 | " return int(x)\n", 259 | "\n", 260 | "def get_id(img_dicom):\n", 261 | " return str(img_dicom.SOPInstanceUID)\n", 262 | "\n", 263 | "def get_metadata_from_dicom(img_dicom):\n", 264 | " metadata = {\n", 265 | " \"window_center\": img_dicom.WindowCenter,\n", 266 | " \"window_width\": img_dicom.WindowWidth,\n", 267 | " \"intercept\": img_dicom.RescaleIntercept,\n", 268 | " \"slope\": img_dicom.RescaleSlope,\n", 269 | " }\n", 270 | " return {k: get_first_of_dicom_field_as_int(v) for k, v in metadata.items()}\n", 271 | "\n", 272 | "def window_image(img, window_center, window_width, intercept, slope):\n", 273 | " img = img * slope + intercept\n", 274 | " img_min = window_center - window_width // 2\n", 275 | " img_max = window_center + window_width // 2\n", 276 | " img[img < img_min] = img_min\n", 277 | " img[img > img_max] = img_max\n", 278 | " return img \n", 279 | "\n", 280 | "def resize(img, new_w, new_h):\n", 281 | " img = PIL.Image.fromarray(img.astype(np.int8), mode=\"L\")\n", 282 | " return img.resize((new_w, new_h), resample=PIL.Image.BICUBIC)\n", 283 | "\n", 284 | "def save_img(img_pil, subfolder, name):\n", 285 | " img_pil.save(subfolder+name+'.jpg')\n", 286 | "\n", 287 | "def normalize_minmax(img):\n", 288 | " mi, ma = img.min(), img.max()\n", 289 | " return (img - mi) / (ma - mi)\n", 290 | "\n", 291 | "def prepare_image(img_path):\n", 292 | " img_dicom = pydicom.read_file(img_path)\n", 293 | " img_id = get_id(img_dicom)\n", 294 | " metadata = get_metadata_from_dicom(img_dicom)\n", 295 | " img = window_image(img_dicom.pixel_array, **metadata)\n", 296 | " img = normalize_minmax(img) * 255\n", 297 | " img = PIL.Image.fromarray(img.astype(np.int8), mode=\"L\")\n", 298 | " return img_id, img\n", 299 | "\n", 300 | "def prepare_and_save(img_path, subfolder):\n", 301 | " try:\n", 302 | " img_id, img_pil = prepare_image(img_path)\n", 303 | " save_img(img_pil, subfolder, img_id)\n", 304 | " except KeyboardInterrupt:\n", 305 | " # Rais interrupt exception so we can stop the cell execution\n", 306 | " # without shutting down the kernel.\n", 307 | " raise\n", 308 | " except:\n", 309 | " l.error('Error processing the image: {'+img_path+'}')\n", 310 | "\n", 311 | "def prepare_images(imgs_path, subfolder):\n", 312 | " for i in tqdm.tqdm(imgs_path):\n", 313 | " prepare_and_save(i, subfolder)\n", 314 | "\n", 315 | "def prepare_images_njobs(img_paths, subfolder, n_jobs=-1):\n", 316 | " joblib.Parallel(n_jobs=n_jobs)(joblib.delayed(prepare_and_save)(i, subfolder) for i in tqdm(img_paths))\n", 317 | "\n", 318 | "if __name__ == '__main__':\n", 319 | " parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.ArgumentDefaultsHelpFormatter)\n", 320 | " parser.add_argument(\"-dcm_path\", \"--dcm_path\", type=str)\n", 321 | " parser.add_argument(\"-jpg_path\", \"--jpg_path\", type=str)\n", 322 | " args = parser.parse_args()\n", 323 | " dcm_path = args.dcm_path\n", 324 | " jpg_path = args.jpg_path\n", 325 | "\n", 326 | " if not os.path.exists(jpg_path):\n", 327 | " os.makedirs(jpg_path)\n", 328 | "\n", 329 | " prepare_images_njobs(glob(dcm_path+'/*'), jpg_path+'/')" 330 | ] 331 | }, 332 | { 333 | "cell_type": "code", 334 | "execution_count": null, 335 | "id": "ff0cc471-abfd-4dbf-b66a-db5fc3aa1037", 336 | "metadata": { 337 | "tags": [] 338 | }, 339 | "outputs": [], 340 | "source": [ 341 | "%%capture\n", 342 | "!python3 prepare_data.py -dcm_path '' -jpg_path ''\n", 343 | "!python3 prepare_data.py -dcm_path '' -jpg_path ''" 344 | ] 345 | }, 346 | { 347 | "cell_type": "code", 348 | "execution_count": null, 349 | "id": "804a30e5-fdcb-4b1d-a85c-438bbaeb56e9", 350 | "metadata": { 351 | "tags": [] 352 | }, 353 | "outputs": [], 354 | "source": [ 355 | "%%capture\n", 356 | "\n", 357 | "!aws s3 sync " 358 | ] 359 | }, 360 | { 361 | "cell_type": "code", 362 | "execution_count": null, 363 | "id": "206d5e7e-f4a9-4710-b374-28d8c3cc09a0", 364 | "metadata": {}, 365 | "outputs": [], 366 | "source": [] 367 | } 368 | ], 369 | "metadata": { 370 | "availableInstances": [ 371 | { 372 | "_defaultOrder": 0, 373 | "_isFastLaunch": true, 374 | "category": "General purpose", 375 | "gpuNum": 0, 376 | "hideHardwareSpecs": false, 377 | "memoryGiB": 4, 378 | "name": "ml.t3.medium", 379 | "vcpuNum": 2 380 | }, 381 | { 382 | "_defaultOrder": 1, 383 | "_isFastLaunch": false, 384 | "category": "General purpose", 385 | "gpuNum": 0, 386 | "hideHardwareSpecs": false, 387 | "memoryGiB": 8, 388 | "name": "ml.t3.large", 389 | "vcpuNum": 2 390 | }, 391 | { 392 | "_defaultOrder": 2, 393 | "_isFastLaunch": false, 394 | "category": "General purpose", 395 | "gpuNum": 0, 396 | "hideHardwareSpecs": false, 397 | "memoryGiB": 16, 398 | "name": "ml.t3.xlarge", 399 | "vcpuNum": 4 400 | }, 401 | { 402 | "_defaultOrder": 3, 403 | "_isFastLaunch": false, 404 | "category": "General purpose", 405 | "gpuNum": 0, 406 | "hideHardwareSpecs": false, 407 | "memoryGiB": 32, 408 | "name": "ml.t3.2xlarge", 409 | "vcpuNum": 8 410 | }, 411 | { 412 | "_defaultOrder": 4, 413 | "_isFastLaunch": true, 414 | "category": "General purpose", 415 | "gpuNum": 0, 416 | "hideHardwareSpecs": false, 417 | "memoryGiB": 8, 418 | "name": "ml.m5.large", 419 | "vcpuNum": 2 420 | }, 421 | { 422 | "_defaultOrder": 5, 423 | "_isFastLaunch": false, 424 | "category": "General purpose", 425 | "gpuNum": 0, 426 | "hideHardwareSpecs": false, 427 | "memoryGiB": 16, 428 | "name": "ml.m5.xlarge", 429 | "vcpuNum": 4 430 | }, 431 | { 432 | "_defaultOrder": 6, 433 | "_isFastLaunch": false, 434 | "category": "General purpose", 435 | "gpuNum": 0, 436 | "hideHardwareSpecs": false, 437 | "memoryGiB": 32, 438 | "name": "ml.m5.2xlarge", 439 | "vcpuNum": 8 440 | }, 441 | { 442 | "_defaultOrder": 7, 443 | "_isFastLaunch": false, 444 | "category": "General purpose", 445 | "gpuNum": 0, 446 | "hideHardwareSpecs": false, 447 | "memoryGiB": 64, 448 | "name": "ml.m5.4xlarge", 449 | "vcpuNum": 16 450 | }, 451 | { 452 | "_defaultOrder": 8, 453 | "_isFastLaunch": false, 454 | "category": "General purpose", 455 | "gpuNum": 0, 456 | "hideHardwareSpecs": false, 457 | "memoryGiB": 128, 458 | "name": "ml.m5.8xlarge", 459 | "vcpuNum": 32 460 | }, 461 | { 462 | "_defaultOrder": 9, 463 | "_isFastLaunch": false, 464 | "category": "General purpose", 465 | "gpuNum": 0, 466 | "hideHardwareSpecs": false, 467 | "memoryGiB": 192, 468 | "name": "ml.m5.12xlarge", 469 | "vcpuNum": 48 470 | }, 471 | { 472 | "_defaultOrder": 10, 473 | "_isFastLaunch": false, 474 | "category": "General purpose", 475 | "gpuNum": 0, 476 | "hideHardwareSpecs": false, 477 | "memoryGiB": 256, 478 | "name": "ml.m5.16xlarge", 479 | "vcpuNum": 64 480 | }, 481 | { 482 | "_defaultOrder": 11, 483 | "_isFastLaunch": false, 484 | "category": "General purpose", 485 | "gpuNum": 0, 486 | "hideHardwareSpecs": false, 487 | "memoryGiB": 384, 488 | "name": "ml.m5.24xlarge", 489 | "vcpuNum": 96 490 | }, 491 | { 492 | "_defaultOrder": 12, 493 | "_isFastLaunch": false, 494 | "category": "General purpose", 495 | "gpuNum": 0, 496 | "hideHardwareSpecs": false, 497 | "memoryGiB": 8, 498 | "name": "ml.m5d.large", 499 | "vcpuNum": 2 500 | }, 501 | { 502 | "_defaultOrder": 13, 503 | "_isFastLaunch": false, 504 | "category": "General purpose", 505 | "gpuNum": 0, 506 | "hideHardwareSpecs": false, 507 | "memoryGiB": 16, 508 | "name": "ml.m5d.xlarge", 509 | "vcpuNum": 4 510 | }, 511 | { 512 | "_defaultOrder": 14, 513 | "_isFastLaunch": false, 514 | "category": "General purpose", 515 | "gpuNum": 0, 516 | "hideHardwareSpecs": false, 517 | "memoryGiB": 32, 518 | "name": "ml.m5d.2xlarge", 519 | "vcpuNum": 8 520 | }, 521 | { 522 | "_defaultOrder": 15, 523 | "_isFastLaunch": false, 524 | "category": "General purpose", 525 | "gpuNum": 0, 526 | "hideHardwareSpecs": false, 527 | "memoryGiB": 64, 528 | "name": "ml.m5d.4xlarge", 529 | "vcpuNum": 16 530 | }, 531 | { 532 | "_defaultOrder": 16, 533 | "_isFastLaunch": false, 534 | "category": "General purpose", 535 | "gpuNum": 0, 536 | "hideHardwareSpecs": false, 537 | "memoryGiB": 128, 538 | "name": "ml.m5d.8xlarge", 539 | "vcpuNum": 32 540 | }, 541 | { 542 | "_defaultOrder": 17, 543 | "_isFastLaunch": false, 544 | "category": "General purpose", 545 | "gpuNum": 0, 546 | "hideHardwareSpecs": false, 547 | "memoryGiB": 192, 548 | "name": "ml.m5d.12xlarge", 549 | "vcpuNum": 48 550 | }, 551 | { 552 | "_defaultOrder": 18, 553 | "_isFastLaunch": false, 554 | "category": "General purpose", 555 | "gpuNum": 0, 556 | "hideHardwareSpecs": false, 557 | "memoryGiB": 256, 558 | "name": "ml.m5d.16xlarge", 559 | "vcpuNum": 64 560 | }, 561 | { 562 | "_defaultOrder": 19, 563 | "_isFastLaunch": false, 564 | "category": "General purpose", 565 | "gpuNum": 0, 566 | "hideHardwareSpecs": false, 567 | "memoryGiB": 384, 568 | "name": "ml.m5d.24xlarge", 569 | "vcpuNum": 96 570 | }, 571 | { 572 | "_defaultOrder": 20, 573 | "_isFastLaunch": false, 574 | "category": "General purpose", 575 | "gpuNum": 0, 576 | "hideHardwareSpecs": true, 577 | "memoryGiB": 0, 578 | "name": "ml.geospatial.interactive", 579 | "supportedImageNames": [ 580 | "sagemaker-geospatial-v1-0" 581 | ], 582 | "vcpuNum": 0 583 | }, 584 | { 585 | "_defaultOrder": 21, 586 | "_isFastLaunch": true, 587 | "category": "Compute optimized", 588 | "gpuNum": 0, 589 | "hideHardwareSpecs": false, 590 | "memoryGiB": 4, 591 | "name": "ml.c5.large", 592 | "vcpuNum": 2 593 | }, 594 | { 595 | "_defaultOrder": 22, 596 | "_isFastLaunch": false, 597 | "category": "Compute optimized", 598 | "gpuNum": 0, 599 | "hideHardwareSpecs": false, 600 | "memoryGiB": 8, 601 | "name": "ml.c5.xlarge", 602 | "vcpuNum": 4 603 | }, 604 | { 605 | "_defaultOrder": 23, 606 | "_isFastLaunch": false, 607 | "category": "Compute optimized", 608 | "gpuNum": 0, 609 | "hideHardwareSpecs": false, 610 | "memoryGiB": 16, 611 | "name": "ml.c5.2xlarge", 612 | "vcpuNum": 8 613 | }, 614 | { 615 | "_defaultOrder": 24, 616 | "_isFastLaunch": false, 617 | "category": "Compute optimized", 618 | "gpuNum": 0, 619 | "hideHardwareSpecs": false, 620 | "memoryGiB": 32, 621 | "name": "ml.c5.4xlarge", 622 | "vcpuNum": 16 623 | }, 624 | { 625 | "_defaultOrder": 25, 626 | "_isFastLaunch": false, 627 | "category": "Compute optimized", 628 | "gpuNum": 0, 629 | "hideHardwareSpecs": false, 630 | "memoryGiB": 72, 631 | "name": "ml.c5.9xlarge", 632 | "vcpuNum": 36 633 | }, 634 | { 635 | "_defaultOrder": 26, 636 | "_isFastLaunch": false, 637 | "category": "Compute optimized", 638 | "gpuNum": 0, 639 | "hideHardwareSpecs": false, 640 | "memoryGiB": 96, 641 | "name": "ml.c5.12xlarge", 642 | "vcpuNum": 48 643 | }, 644 | { 645 | "_defaultOrder": 27, 646 | "_isFastLaunch": false, 647 | "category": "Compute optimized", 648 | "gpuNum": 0, 649 | "hideHardwareSpecs": false, 650 | "memoryGiB": 144, 651 | "name": "ml.c5.18xlarge", 652 | "vcpuNum": 72 653 | }, 654 | { 655 | "_defaultOrder": 28, 656 | "_isFastLaunch": false, 657 | "category": "Compute optimized", 658 | "gpuNum": 0, 659 | "hideHardwareSpecs": false, 660 | "memoryGiB": 192, 661 | "name": "ml.c5.24xlarge", 662 | "vcpuNum": 96 663 | }, 664 | { 665 | "_defaultOrder": 29, 666 | "_isFastLaunch": true, 667 | "category": "Accelerated computing", 668 | "gpuNum": 1, 669 | "hideHardwareSpecs": false, 670 | "memoryGiB": 16, 671 | "name": "ml.g4dn.xlarge", 672 | "vcpuNum": 4 673 | }, 674 | { 675 | "_defaultOrder": 30, 676 | "_isFastLaunch": false, 677 | "category": "Accelerated computing", 678 | "gpuNum": 1, 679 | "hideHardwareSpecs": false, 680 | "memoryGiB": 32, 681 | "name": "ml.g4dn.2xlarge", 682 | "vcpuNum": 8 683 | }, 684 | { 685 | "_defaultOrder": 31, 686 | "_isFastLaunch": false, 687 | "category": "Accelerated computing", 688 | "gpuNum": 1, 689 | "hideHardwareSpecs": false, 690 | "memoryGiB": 64, 691 | "name": "ml.g4dn.4xlarge", 692 | "vcpuNum": 16 693 | }, 694 | { 695 | "_defaultOrder": 32, 696 | "_isFastLaunch": false, 697 | "category": "Accelerated computing", 698 | "gpuNum": 1, 699 | "hideHardwareSpecs": false, 700 | "memoryGiB": 128, 701 | "name": "ml.g4dn.8xlarge", 702 | "vcpuNum": 32 703 | }, 704 | { 705 | "_defaultOrder": 33, 706 | "_isFastLaunch": false, 707 | "category": "Accelerated computing", 708 | "gpuNum": 4, 709 | "hideHardwareSpecs": false, 710 | "memoryGiB": 192, 711 | "name": "ml.g4dn.12xlarge", 712 | "vcpuNum": 48 713 | }, 714 | { 715 | "_defaultOrder": 34, 716 | "_isFastLaunch": false, 717 | "category": "Accelerated computing", 718 | "gpuNum": 1, 719 | "hideHardwareSpecs": false, 720 | "memoryGiB": 256, 721 | "name": "ml.g4dn.16xlarge", 722 | "vcpuNum": 64 723 | }, 724 | { 725 | "_defaultOrder": 35, 726 | "_isFastLaunch": false, 727 | "category": "Accelerated computing", 728 | "gpuNum": 1, 729 | "hideHardwareSpecs": false, 730 | "memoryGiB": 61, 731 | "name": "ml.p3.2xlarge", 732 | "vcpuNum": 8 733 | }, 734 | { 735 | "_defaultOrder": 36, 736 | "_isFastLaunch": false, 737 | "category": "Accelerated computing", 738 | "gpuNum": 4, 739 | "hideHardwareSpecs": false, 740 | "memoryGiB": 244, 741 | "name": "ml.p3.8xlarge", 742 | "vcpuNum": 32 743 | }, 744 | { 745 | "_defaultOrder": 37, 746 | "_isFastLaunch": false, 747 | "category": "Accelerated computing", 748 | "gpuNum": 8, 749 | "hideHardwareSpecs": false, 750 | "memoryGiB": 488, 751 | "name": "ml.p3.16xlarge", 752 | "vcpuNum": 64 753 | }, 754 | { 755 | "_defaultOrder": 38, 756 | "_isFastLaunch": false, 757 | "category": "Accelerated computing", 758 | "gpuNum": 8, 759 | "hideHardwareSpecs": false, 760 | "memoryGiB": 768, 761 | "name": "ml.p3dn.24xlarge", 762 | "vcpuNum": 96 763 | }, 764 | { 765 | "_defaultOrder": 39, 766 | "_isFastLaunch": false, 767 | "category": "Memory Optimized", 768 | "gpuNum": 0, 769 | "hideHardwareSpecs": false, 770 | "memoryGiB": 16, 771 | "name": "ml.r5.large", 772 | "vcpuNum": 2 773 | }, 774 | { 775 | "_defaultOrder": 40, 776 | "_isFastLaunch": false, 777 | "category": "Memory Optimized", 778 | "gpuNum": 0, 779 | "hideHardwareSpecs": false, 780 | "memoryGiB": 32, 781 | "name": "ml.r5.xlarge", 782 | "vcpuNum": 4 783 | }, 784 | { 785 | "_defaultOrder": 41, 786 | "_isFastLaunch": false, 787 | "category": "Memory Optimized", 788 | "gpuNum": 0, 789 | "hideHardwareSpecs": false, 790 | "memoryGiB": 64, 791 | "name": "ml.r5.2xlarge", 792 | "vcpuNum": 8 793 | }, 794 | { 795 | "_defaultOrder": 42, 796 | "_isFastLaunch": false, 797 | "category": "Memory Optimized", 798 | "gpuNum": 0, 799 | "hideHardwareSpecs": false, 800 | "memoryGiB": 128, 801 | "name": "ml.r5.4xlarge", 802 | "vcpuNum": 16 803 | }, 804 | { 805 | "_defaultOrder": 43, 806 | "_isFastLaunch": false, 807 | "category": "Memory Optimized", 808 | "gpuNum": 0, 809 | "hideHardwareSpecs": false, 810 | "memoryGiB": 256, 811 | "name": "ml.r5.8xlarge", 812 | "vcpuNum": 32 813 | }, 814 | { 815 | "_defaultOrder": 44, 816 | "_isFastLaunch": false, 817 | "category": "Memory Optimized", 818 | "gpuNum": 0, 819 | "hideHardwareSpecs": false, 820 | "memoryGiB": 384, 821 | "name": "ml.r5.12xlarge", 822 | "vcpuNum": 48 823 | }, 824 | { 825 | "_defaultOrder": 45, 826 | "_isFastLaunch": false, 827 | "category": "Memory Optimized", 828 | "gpuNum": 0, 829 | "hideHardwareSpecs": false, 830 | "memoryGiB": 512, 831 | "name": "ml.r5.16xlarge", 832 | "vcpuNum": 64 833 | }, 834 | { 835 | "_defaultOrder": 46, 836 | "_isFastLaunch": false, 837 | "category": "Memory Optimized", 838 | "gpuNum": 0, 839 | "hideHardwareSpecs": false, 840 | "memoryGiB": 768, 841 | "name": "ml.r5.24xlarge", 842 | "vcpuNum": 96 843 | }, 844 | { 845 | "_defaultOrder": 47, 846 | "_isFastLaunch": false, 847 | "category": "Accelerated computing", 848 | "gpuNum": 1, 849 | "hideHardwareSpecs": false, 850 | "memoryGiB": 16, 851 | "name": "ml.g5.xlarge", 852 | "vcpuNum": 4 853 | }, 854 | { 855 | "_defaultOrder": 48, 856 | "_isFastLaunch": false, 857 | "category": "Accelerated computing", 858 | "gpuNum": 1, 859 | "hideHardwareSpecs": false, 860 | "memoryGiB": 32, 861 | "name": "ml.g5.2xlarge", 862 | "vcpuNum": 8 863 | }, 864 | { 865 | "_defaultOrder": 49, 866 | "_isFastLaunch": false, 867 | "category": "Accelerated computing", 868 | "gpuNum": 1, 869 | "hideHardwareSpecs": false, 870 | "memoryGiB": 64, 871 | "name": "ml.g5.4xlarge", 872 | "vcpuNum": 16 873 | }, 874 | { 875 | "_defaultOrder": 50, 876 | "_isFastLaunch": false, 877 | "category": "Accelerated computing", 878 | "gpuNum": 1, 879 | "hideHardwareSpecs": false, 880 | "memoryGiB": 128, 881 | "name": "ml.g5.8xlarge", 882 | "vcpuNum": 32 883 | }, 884 | { 885 | "_defaultOrder": 51, 886 | "_isFastLaunch": false, 887 | "category": "Accelerated computing", 888 | "gpuNum": 1, 889 | "hideHardwareSpecs": false, 890 | "memoryGiB": 256, 891 | "name": "ml.g5.16xlarge", 892 | "vcpuNum": 64 893 | }, 894 | { 895 | "_defaultOrder": 52, 896 | "_isFastLaunch": false, 897 | "category": "Accelerated computing", 898 | "gpuNum": 4, 899 | "hideHardwareSpecs": false, 900 | "memoryGiB": 192, 901 | "name": "ml.g5.12xlarge", 902 | "vcpuNum": 48 903 | }, 904 | { 905 | "_defaultOrder": 53, 906 | "_isFastLaunch": false, 907 | "category": "Accelerated computing", 908 | "gpuNum": 4, 909 | "hideHardwareSpecs": false, 910 | "memoryGiB": 384, 911 | "name": "ml.g5.24xlarge", 912 | "vcpuNum": 96 913 | }, 914 | { 915 | "_defaultOrder": 54, 916 | "_isFastLaunch": false, 917 | "category": "Accelerated computing", 918 | "gpuNum": 8, 919 | "hideHardwareSpecs": false, 920 | "memoryGiB": 768, 921 | "name": "ml.g5.48xlarge", 922 | "vcpuNum": 192 923 | }, 924 | { 925 | "_defaultOrder": 55, 926 | "_isFastLaunch": false, 927 | "category": "Accelerated computing", 928 | "gpuNum": 8, 929 | "hideHardwareSpecs": false, 930 | "memoryGiB": 1152, 931 | "name": "ml.p4d.24xlarge", 932 | "vcpuNum": 96 933 | }, 934 | { 935 | "_defaultOrder": 56, 936 | "_isFastLaunch": false, 937 | "category": "Accelerated computing", 938 | "gpuNum": 8, 939 | "hideHardwareSpecs": false, 940 | "memoryGiB": 1152, 941 | "name": "ml.p4de.24xlarge", 942 | "vcpuNum": 96 943 | } 944 | ], 945 | "instance_type": "ml.t3.medium", 946 | "kernelspec": { 947 | "display_name": "Python 3 (TensorFlow 2.11.0 Python 3.9 CPU Optimized)", 948 | "language": "python", 949 | "name": "python3__SAGEMAKER_INTERNAL__arn:aws:sagemaker:us-east-1:081325390199:image/tensorflow-2.11.0-cpu-py39-ubuntu20.04-sagemaker-v1.1" 950 | }, 951 | "language_info": { 952 | "codemirror_mode": { 953 | "name": "ipython", 954 | "version": 3 955 | }, 956 | "file_extension": ".py", 957 | "mimetype": "text/x-python", 958 | "name": "python", 959 | "nbconvert_exporter": "python", 960 | "pygments_lexer": "ipython3", 961 | "version": "3.9.10" 962 | } 963 | }, 964 | "nbformat": 4, 965 | "nbformat_minor": 5 966 | } 967 | -------------------------------------------------------------------------------- /code/2_model_train_deploy_inference.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "f33bf1a9-0112-43ef-8ccc-d95c3f5f738b", 6 | "metadata": { 7 | "jp-MarkdownHeadingCollapsed": true, 8 | "tags": [] 9 | }, 10 | "source": [ 11 | "## Train the Deep Learning Model on the Intracranial Hemorrhage Dataset\n", 12 | "***\n", 13 | "\n", 14 | "The model available for training and fine-tuning attaches a classification layer to the corresponding feature extractor model available on TensorFlow/PyTorch hub, and initializes the layer parameters to random values. The output dimension of the classification layer is determined based on the number of classes in the input data. The fine-tuning step fine-tunes the model parameters. The objective is to minimize classification error on the input data. The model returned by fine-tuning can be further deployed for inference. Below are the instructions for how the training data should be formatted for input to the model. \n", 15 | "\n", 16 | "- **Input:** A directory with as many sub-directories as the number of classes. \n", 17 | " - Each sub-directory should have images belonging to that class in .jpg format. \n", 18 | "- **Output:** A trained model that can be deployed for inference. \n", 19 | " - A label mapping file is saved along with the trained model file on the S3 bucket. \n", 20 | " \n", 21 | "The input directory should look like below if the training data contains images from two classes: hemorrhage and no_hemorrhage. The S3 path should look like\n", 22 | "\n", 23 | " s3://bucket_name/input_directory/\n", 24 | "\n", 25 | "Note the trailing `/` is required. The names of the folders are 'hemorrhage', 'no_hemorrhage', and the .jpg filenames can be anything. The label mapping file that is saved along with the trained model on the S3 bucket maps the folder names 'hemorrhage' and 'hemorrhage' to the indices in the list of class probabilities the model outputs.\n", 26 | "\n", 27 | " input_directory\n", 28 | " |--hemorrhage\n", 29 | " |--ID_1b7a626dd.jpg\n", 30 | " |--ID_050464d4c.jpg\n", 31 | " |--no_hemorrhage\n", 32 | " |--ID_0007a3b49.jpg\n", 33 | " |--ID_00096021a.jpg\n", 34 | "***" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "id": "63ee631d-ed4c-401a-b14b-6e3e1f4dbc2e", 40 | "metadata": {}, 41 | "source": [ 42 | "## Set Up\n", 43 | "Before executing the notebook, there are some initial steps required for setup. This notebook requires ipywidgets." 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": null, 49 | "id": "f109d038-f3ab-45a6-9c77-a5521c218d9d", 50 | "metadata": { 51 | "tags": [] 52 | }, 53 | "outputs": [], 54 | "source": [ 55 | "!pip install ipywidgets==7.0.0 --quiet" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "id": "d705088e-a645-444c-8c69-6122f400ec6d", 61 | "metadata": {}, 62 | "source": [ 63 | "To train and host on Amazon SageMaker, we need to setup and authenticate the use of AWS services. Here, we use the execution role associated with the current notebook instance as the AWS account role with SageMaker access. It has necessary permissions, including access to your data in S3. " 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": null, 69 | "id": "768bf5ce-b94c-4f46-bd72-a0abdc60a88b", 70 | "metadata": { 71 | "tags": [] 72 | }, 73 | "outputs": [], 74 | "source": [ 75 | "import sagemaker, boto3, json\n", 76 | "from sagemaker.session import Session\n", 77 | "\n", 78 | "sagemaker_session = Session()\n", 79 | "aws_role = sagemaker_session.get_caller_identity_arn()\n", 80 | "aws_region = boto3.Session().region_name\n", 81 | "sess = sagemaker.Session()" 82 | ] 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "id": "d830b565-b0fd-4444-ad6d-2aa4d3ef693a", 87 | "metadata": { 88 | "tags": [] 89 | }, 90 | "source": [ 91 | "## Select a Computer Vision Model and Retrieve Training Artifacts\n", 92 | "\n", 93 | "Select the model we'll be using, which is the DenseNet-121 model. A complete list of SageMaker models can also be accessed at [Sagemaker pre-trained Models](https://sagemaker.readthedocs.io/en/stable/doc_utils/pretrainedmodels.html#).\n", 94 | "\n", 95 | "Here, for the selected model, we retrieve the training Docker container, the training algorithm source, the pre-trained base model, and a Python dictionary of the training hyper-parameters that the algorithm accepts with their default values. Note that the `model_version=\"*\"` fetches the lates model. Also, we do need to specify the `training_instance_type` to fetch `train_image_uri`.\n" 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": null, 101 | "id": "267dd170-23d8-4052-b26f-7464d412d296", 102 | "metadata": { 103 | "tags": [] 104 | }, 105 | "outputs": [], 106 | "source": [ 107 | "from sagemaker import image_uris, model_uris, script_uris, hyperparameters\n", 108 | "\n", 109 | "model_id, model_version = \"pytorch-ic-densenet121\", \"*\"\n", 110 | "training_instance_type = \"ml.p3.2xlarge\"\n", 111 | "\n", 112 | "# Retrieve the docker image\n", 113 | "train_image_uri = image_uris.retrieve(\n", 114 | " region=None,\n", 115 | " framework=None,\n", 116 | " model_id=model_id,\n", 117 | " model_version=model_version,\n", 118 | " image_scope=\"training\",\n", 119 | " instance_type=training_instance_type,\n", 120 | ")\n", 121 | "# Retrieve the training script\n", 122 | "train_source_uri = script_uris.retrieve(\n", 123 | " model_id=model_id, model_version=model_version, script_scope=\"training\"\n", 124 | ")\n", 125 | "# Retrieve the pre-trained model tarball to further fine-tune\n", 126 | "train_model_uri = model_uris.retrieve(\n", 127 | " model_id=model_id, model_version=model_version, model_scope=\"training\"\n", 128 | ")" 129 | ] 130 | }, 131 | { 132 | "cell_type": "markdown", 133 | "id": "e2fe9e05-7c9f-4150-8ee0-0eb5482aa21c", 134 | "metadata": {}, 135 | "source": [ 136 | "### Set Training Parameters\n", 137 | "Now that we are done with all the setup that is needed, we are ready to fine-tune our Image Classification model. To begin, let us create a [``sageMaker.estimator.Estimator``](https://sagemaker.readthedocs.io/en/stable/api/training/estimators.html) object. This estimator will launch the training job. There are two kinds of parameters that need to be set for training. \n", 138 | "\n", 139 | "The first one are the parameters for the training job. These include: (i) Training data path. This is S3 folder in which the input data is stored, (ii) Output path: This the s3 folder in which the training output is stored. (iii) Training instance type: This indicates the type of machine on which to run the training. Typically, we use GPU instances for these training. We defined the training instance type above to fetch the correct train_image_uri. \n", 140 | "\n", 141 | "The second set of parameters are algorithm-specific training hyper-parameters.\n" 142 | ] 143 | }, 144 | { 145 | "cell_type": "code", 146 | "execution_count": null, 147 | "id": "d4b9a818-78f5-4bc7-8b82-e23f255228f4", 148 | "metadata": {}, 149 | "outputs": [], 150 | "source": [ 151 | "# Sample training data is available in this bucket\n", 152 | "training_data_bucket = \"re-invent-radiology-demo\"\n", 153 | "training_data_prefix = \"radiology_image_data_model/input_training_data/\"\n", 154 | "\n", 155 | "training_dataset_s3_path = f\"s3://{training_data_bucket}/{training_data_prefix}\"\n", 156 | "\n", 157 | "output_bucket = \"re-invent-radiology-demo\"\n", 158 | "output_prefix = \"radiology_image_data_model/output/\"\n", 159 | "\n", 160 | "s3_output_location = f\"s3://{output_bucket}/{output_prefix}/output\"\n" 161 | ] 162 | }, 163 | { 164 | "cell_type": "markdown", 165 | "id": "cffef382-fc23-4bba-b822-ea77724d567c", 166 | "metadata": { 167 | "tags": [] 168 | }, 169 | "source": [ 170 | "***\n", 171 | "For algorithm specific hyper-parameters, we start by fetching python dictionary of the training hyper-parameters that the algorithm accepts with their default values. This can then be overridden to custom values.\n", 172 | "***" 173 | ] 174 | }, 175 | { 176 | "cell_type": "code", 177 | "execution_count": null, 178 | "id": "de63499c-db14-49b4-b6ee-6cdf099f0408", 179 | "metadata": { 180 | "tags": [] 181 | }, 182 | "outputs": [], 183 | "source": [ 184 | "from sagemaker import hyperparameters\n", 185 | "\n", 186 | "# Retrieve the default hyper-parameters for fine-tuning the model\n", 187 | "hyperparameters = hyperparameters.retrieve_default(model_id=model_id, model_version=model_version)\n", 188 | "\n", 189 | "# [Optional] Override default hyperparameters with custom values\n", 190 | "hyperparameters[\"epochs\"] = \"5\"\n", 191 | "hyperparameters[\"augmentation\"] = \"True\"\n", 192 | "hyperparameters[\"train_only_top_layer\"] = \"False\"\n", 193 | "hyperparameters[\"batch_size\"] = \"32\"\n", 194 | "\n", 195 | "print(hyperparameters)" 196 | ] 197 | }, 198 | { 199 | "cell_type": "markdown", 200 | "id": "e65959ba-6d78-4374-a502-8cda79e68a9f", 201 | "metadata": {}, 202 | "source": [ 203 | "### Train with Automatic Model Tuning ([HPO](https://docs.aws.amazon.com/sagemaker/latest/dg/automatic-model-tuning.html)) \n", 204 | "***\n", 205 | "Amazon SageMaker automatic model tuning, also known as hyperparameter tuning, finds the best version of a model by running many training jobs on your dataset using the algorithm and ranges of hyperparameters that you specify. It then chooses the hyperparameter values that result in a model that performs the best, as measured by a metric that you choose. We will use a [HyperparameterTuner](https://sagemaker.readthedocs.io/en/stable/api/training/tuner.html) object to interact with Amazon SageMaker hyperparameter tuning APIs.\n", 206 | "***" 207 | ] 208 | }, 209 | { 210 | "cell_type": "code", 211 | "execution_count": null, 212 | "id": "b7298e19-40c2-4933-9c54-b0ce596f56cd", 213 | "metadata": {}, 214 | "outputs": [], 215 | "source": [ 216 | "from sagemaker.tuner import ContinuousParameter\n", 217 | "\n", 218 | "# Use AMT for tuning and selecting the best model\n", 219 | "use_amt = False\n", 220 | "\n", 221 | "# Define objective metric per framework, based on which the best model will be selected.\n", 222 | "metric_definitions_per_model = {\n", 223 | " \"tensorflow\": {\n", 224 | " \"metrics\": [{\"Name\": \"val_accuracy\", \"Regex\": \"val_accuracy: ([0-9\\\\.]+)\"}],\n", 225 | " \"type\": \"Maximize\",\n", 226 | " },\n", 227 | " \"pytorch\": {\n", 228 | " \"metrics\": [{\"Name\": \"val_accuracy\", \"Regex\": \"val Acc: ([0-9\\\\.]+)\"}],\n", 229 | " \"type\": \"Maximize\",\n", 230 | " },\n", 231 | "}\n", 232 | "\n", 233 | "# You can select from the hyperparameters supported by the model, and configure ranges of values to be searched for training the optimal model.(https://docs.aws.amazon.com/sagemaker/latest/dg/automatic-model-tuning-define-ranges.html)\n", 234 | "hyperparameter_ranges = {\n", 235 | " \"adam-learning-rate\": ContinuousParameter(0.0001, 0.1, scaling_type=\"Logarithmic\")\n", 236 | "}\n", 237 | "\n", 238 | "# Increase the total number of training jobs run by AMT, for increased accuracy (and training time).\n", 239 | "max_jobs = 6\n", 240 | "# Change parallel training jobs run by AMT to reduce total training time, constrained by your account limits.\n", 241 | "# if max_jobs=max_parallel_jobs then Bayesian search turns to Random.\n", 242 | "max_parallel_jobs = 1" 243 | ] 244 | }, 245 | { 246 | "cell_type": "markdown", 247 | "id": "1ee94815-2719-4afb-b23f-d79d5e7b8ea9", 248 | "metadata": {}, 249 | "source": [ 250 | "### Start Training\n", 251 | "We start by creating the estimator object with all the required assets and then launch the training job.\n" 252 | ] 253 | }, 254 | { 255 | "cell_type": "code", 256 | "execution_count": null, 257 | "id": "33689f3b-22e6-4978-a30d-859d810b6172", 258 | "metadata": { 259 | "tags": [] 260 | }, 261 | "outputs": [], 262 | "source": [ 263 | "from sagemaker.estimator import Estimator\n", 264 | "from sagemaker.utils import name_from_base\n", 265 | "from sagemaker.tuner import HyperparameterTuner\n", 266 | "\n", 267 | "training_job_name = name_from_base(f\"radiology-hemorrhage-{model_id}-transfer-learning\")\n", 268 | "\n", 269 | "# Create SageMaker Estimator instance\n", 270 | "ic_estimator = Estimator(\n", 271 | " role=aws_role,\n", 272 | " image_uri=train_image_uri,\n", 273 | " source_dir=train_source_uri,\n", 274 | " model_uri=train_model_uri,\n", 275 | " entry_point=\"transfer_learning.py\",\n", 276 | " instance_count=1,\n", 277 | " instance_type=training_instance_type,\n", 278 | " max_run=360000,\n", 279 | " hyperparameters=hyperparameters,\n", 280 | " output_path=s3_output_location,\n", 281 | " base_job_name=training_job_name,\n", 282 | ")\n", 283 | "\n", 284 | "if use_amt:\n", 285 | " metric_definitions = next(\n", 286 | " value for key, value in metric_definitions_per_model.items() if model_id.startswith(key)\n", 287 | " )\n", 288 | "\n", 289 | " hp_tuner = HyperparameterTuner(\n", 290 | " ic_estimator,\n", 291 | " metric_definitions[\"metrics\"][0][\"Name\"],\n", 292 | " hyperparameter_ranges,\n", 293 | " metric_definitions[\"metrics\"],\n", 294 | " max_jobs=max_jobs,\n", 295 | " max_parallel_jobs=max_parallel_jobs,\n", 296 | " objective_type=metric_definitions[\"type\"],\n", 297 | " base_tuning_job_name=training_job_name,\n", 298 | " )\n", 299 | "\n", 300 | " # Launch a SageMaker Tuning job to search for the best hyperparameters\n", 301 | " hp_tuner.fit({\"training\": training_dataset_s3_path})\n", 302 | "else:\n", 303 | " # Launch a SageMaker Training job by passing s3 path of the training data\n", 304 | " ic_estimator.fit({\"training\": training_dataset_s3_path}, logs=True)" 305 | ] 306 | }, 307 | { 308 | "cell_type": "markdown", 309 | "id": "ae70d990-5cce-4ff6-87b0-539911d48ece", 310 | "metadata": {}, 311 | "source": [ 312 | "## Deploy & Run Inference on the Model\n", 313 | "\n", 314 | "A trained model does nothing on its own. We now want to use the model to perform inference. We start by retrieving the artifacts for deploying an endpoint.\n" 315 | ] 316 | }, 317 | { 318 | "cell_type": "code", 319 | "execution_count": null, 320 | "id": "00e45932-a7df-4c7e-a59e-0fa6ed18a46a", 321 | "metadata": { 322 | "tags": [] 323 | }, 324 | "outputs": [], 325 | "source": [ 326 | "inference_instance_type = \"ml.p2.xlarge\"\n", 327 | "\n", 328 | "# Retrieve the inference docker container uri\n", 329 | "deploy_image_uri = image_uris.retrieve(\n", 330 | " region=None,\n", 331 | " framework=None,\n", 332 | " image_scope=\"inference\",\n", 333 | " model_id=model_id,\n", 334 | " model_version=model_version,\n", 335 | " instance_type=inference_instance_type,\n", 336 | ")\n", 337 | "# Retrieve the inference script uri\n", 338 | "deploy_source_uri = script_uris.retrieve(\n", 339 | " model_id=model_id, model_version=model_version, script_scope=\"inference\"\n", 340 | ")\n", 341 | "\n", 342 | "endpoint_name = name_from_base(f\"radiology-hemorrhage-FT-{model_id}-\")\n", 343 | "\n", 344 | "# Use the estimator from the previous step to deploy to a SageMaker endpoint\n", 345 | "finetuned_predictor = (hp_tuner if use_amt else ic_estimator).deploy(\n", 346 | " initial_instance_count=1,\n", 347 | " instance_type=inference_instance_type,\n", 348 | " entry_point=\"inference.py\",\n", 349 | " image_uri=deploy_image_uri,\n", 350 | " source_dir=deploy_source_uri,\n", 351 | " endpoint_name=endpoint_name,\n", 352 | ")" 353 | ] 354 | }, 355 | { 356 | "cell_type": "code", 357 | "execution_count": null, 358 | "id": "99647014-7e33-491b-8b91-9d4e2ba2b600", 359 | "metadata": { 360 | "tags": [] 361 | }, 362 | "outputs": [], 363 | "source": [ 364 | "#create a list with the path for a few sample images\n", 365 | "test_images = ['', '']" 366 | ] 367 | }, 368 | { 369 | "cell_type": "markdown", 370 | "id": "ddd90785-0ec3-4955-91f6-c67fd501b069", 371 | "metadata": {}, 372 | "source": [ 373 | "Next, we query the model, parse the response and display the predictions." 374 | ] 375 | }, 376 | { 377 | "cell_type": "code", 378 | "execution_count": null, 379 | "id": "69fb998c-4655-4070-8d7b-74153e18077a", 380 | "metadata": { 381 | "tags": [] 382 | }, 383 | "outputs": [], 384 | "source": [ 385 | "import pandas as pd\n", 386 | "from IPython.core.display import HTML\n", 387 | "combined_df = pd.DataFrame()\n", 388 | "\n", 389 | "for image_filename in test_images:\n", 390 | " with open(image_filename, \"rb\") as file:\n", 391 | " img = file.read()\n", 392 | " query_response = finetuned_predictor.predict(\n", 393 | " img, {\"ContentType\": \"application/x-image\", \"Accept\": \"application/json;verbose\"}\n", 394 | " )\n", 395 | " model_predictions = json.loads(query_response)\n", 396 | " preds = {key: [value for value in values] for key, values in model_predictions.items() if key != 'predicted_label'}\n", 397 | " df = pd.DataFrame(preds)\n", 398 | " df = df[df['probabilities']==df['probabilities'].max()].reset_index(drop = True)\n", 399 | " combined_df = pd.concat([combined_df, df], ignore_index = True)\n", 400 | " predicted_label = model_predictions[\"predicted_label\"]\n", 401 | " display(\n", 402 | " HTML(\n", 403 | " f'{image_filename}'\n", 404 | " f\"
Predicted Label: {predicted_label}
\"\n", 405 | " )\n", 406 | " )" 407 | ] 408 | }, 409 | { 410 | "cell_type": "code", 411 | "execution_count": null, 412 | "id": "06e4da5a-6894-4f4e-b6e4-501b1e1d45f3", 413 | "metadata": {}, 414 | "outputs": [], 415 | "source": [ 416 | "# Delete the SageMaker endpoint and the attached resources\n", 417 | "finetuned_predictor.delete_model()\n", 418 | "finetuned_predictor.delete_endpoint()" 419 | ] 420 | }, 421 | { 422 | "cell_type": "code", 423 | "execution_count": null, 424 | "id": "3df4f39a-cbb1-4742-80b2-8c000c0e5f09", 425 | "metadata": {}, 426 | "outputs": [], 427 | "source": [] 428 | } 429 | ], 430 | "metadata": { 431 | "availableInstances": [ 432 | { 433 | "_defaultOrder": 0, 434 | "_isFastLaunch": true, 435 | "category": "General purpose", 436 | "gpuNum": 0, 437 | "hideHardwareSpecs": false, 438 | "memoryGiB": 4, 439 | "name": "ml.t3.medium", 440 | "vcpuNum": 2 441 | }, 442 | { 443 | "_defaultOrder": 1, 444 | "_isFastLaunch": false, 445 | "category": "General purpose", 446 | "gpuNum": 0, 447 | "hideHardwareSpecs": false, 448 | "memoryGiB": 8, 449 | "name": "ml.t3.large", 450 | "vcpuNum": 2 451 | }, 452 | { 453 | "_defaultOrder": 2, 454 | "_isFastLaunch": false, 455 | "category": "General purpose", 456 | "gpuNum": 0, 457 | "hideHardwareSpecs": false, 458 | "memoryGiB": 16, 459 | "name": "ml.t3.xlarge", 460 | "vcpuNum": 4 461 | }, 462 | { 463 | "_defaultOrder": 3, 464 | "_isFastLaunch": false, 465 | "category": "General purpose", 466 | "gpuNum": 0, 467 | "hideHardwareSpecs": false, 468 | "memoryGiB": 32, 469 | "name": "ml.t3.2xlarge", 470 | "vcpuNum": 8 471 | }, 472 | { 473 | "_defaultOrder": 4, 474 | "_isFastLaunch": true, 475 | "category": "General purpose", 476 | "gpuNum": 0, 477 | "hideHardwareSpecs": false, 478 | "memoryGiB": 8, 479 | "name": "ml.m5.large", 480 | "vcpuNum": 2 481 | }, 482 | { 483 | "_defaultOrder": 5, 484 | "_isFastLaunch": false, 485 | "category": "General purpose", 486 | "gpuNum": 0, 487 | "hideHardwareSpecs": false, 488 | "memoryGiB": 16, 489 | "name": "ml.m5.xlarge", 490 | "vcpuNum": 4 491 | }, 492 | { 493 | "_defaultOrder": 6, 494 | "_isFastLaunch": false, 495 | "category": "General purpose", 496 | "gpuNum": 0, 497 | "hideHardwareSpecs": false, 498 | "memoryGiB": 32, 499 | "name": "ml.m5.2xlarge", 500 | "vcpuNum": 8 501 | }, 502 | { 503 | "_defaultOrder": 7, 504 | "_isFastLaunch": false, 505 | "category": "General purpose", 506 | "gpuNum": 0, 507 | "hideHardwareSpecs": false, 508 | "memoryGiB": 64, 509 | "name": "ml.m5.4xlarge", 510 | "vcpuNum": 16 511 | }, 512 | { 513 | "_defaultOrder": 8, 514 | "_isFastLaunch": false, 515 | "category": "General purpose", 516 | "gpuNum": 0, 517 | "hideHardwareSpecs": false, 518 | "memoryGiB": 128, 519 | "name": "ml.m5.8xlarge", 520 | "vcpuNum": 32 521 | }, 522 | { 523 | "_defaultOrder": 9, 524 | "_isFastLaunch": false, 525 | "category": "General purpose", 526 | "gpuNum": 0, 527 | "hideHardwareSpecs": false, 528 | "memoryGiB": 192, 529 | "name": "ml.m5.12xlarge", 530 | "vcpuNum": 48 531 | }, 532 | { 533 | "_defaultOrder": 10, 534 | "_isFastLaunch": false, 535 | "category": "General purpose", 536 | "gpuNum": 0, 537 | "hideHardwareSpecs": false, 538 | "memoryGiB": 256, 539 | "name": "ml.m5.16xlarge", 540 | "vcpuNum": 64 541 | }, 542 | { 543 | "_defaultOrder": 11, 544 | "_isFastLaunch": false, 545 | "category": "General purpose", 546 | "gpuNum": 0, 547 | "hideHardwareSpecs": false, 548 | "memoryGiB": 384, 549 | "name": "ml.m5.24xlarge", 550 | "vcpuNum": 96 551 | }, 552 | { 553 | "_defaultOrder": 12, 554 | "_isFastLaunch": false, 555 | "category": "General purpose", 556 | "gpuNum": 0, 557 | "hideHardwareSpecs": false, 558 | "memoryGiB": 8, 559 | "name": "ml.m5d.large", 560 | "vcpuNum": 2 561 | }, 562 | { 563 | "_defaultOrder": 13, 564 | "_isFastLaunch": false, 565 | "category": "General purpose", 566 | "gpuNum": 0, 567 | "hideHardwareSpecs": false, 568 | "memoryGiB": 16, 569 | "name": "ml.m5d.xlarge", 570 | "vcpuNum": 4 571 | }, 572 | { 573 | "_defaultOrder": 14, 574 | "_isFastLaunch": false, 575 | "category": "General purpose", 576 | "gpuNum": 0, 577 | "hideHardwareSpecs": false, 578 | "memoryGiB": 32, 579 | "name": "ml.m5d.2xlarge", 580 | "vcpuNum": 8 581 | }, 582 | { 583 | "_defaultOrder": 15, 584 | "_isFastLaunch": false, 585 | "category": "General purpose", 586 | "gpuNum": 0, 587 | "hideHardwareSpecs": false, 588 | "memoryGiB": 64, 589 | "name": "ml.m5d.4xlarge", 590 | "vcpuNum": 16 591 | }, 592 | { 593 | "_defaultOrder": 16, 594 | "_isFastLaunch": false, 595 | "category": "General purpose", 596 | "gpuNum": 0, 597 | "hideHardwareSpecs": false, 598 | "memoryGiB": 128, 599 | "name": "ml.m5d.8xlarge", 600 | "vcpuNum": 32 601 | }, 602 | { 603 | "_defaultOrder": 17, 604 | "_isFastLaunch": false, 605 | "category": "General purpose", 606 | "gpuNum": 0, 607 | "hideHardwareSpecs": false, 608 | "memoryGiB": 192, 609 | "name": "ml.m5d.12xlarge", 610 | "vcpuNum": 48 611 | }, 612 | { 613 | "_defaultOrder": 18, 614 | "_isFastLaunch": false, 615 | "category": "General purpose", 616 | "gpuNum": 0, 617 | "hideHardwareSpecs": false, 618 | "memoryGiB": 256, 619 | "name": "ml.m5d.16xlarge", 620 | "vcpuNum": 64 621 | }, 622 | { 623 | "_defaultOrder": 19, 624 | "_isFastLaunch": false, 625 | "category": "General purpose", 626 | "gpuNum": 0, 627 | "hideHardwareSpecs": false, 628 | "memoryGiB": 384, 629 | "name": "ml.m5d.24xlarge", 630 | "vcpuNum": 96 631 | }, 632 | { 633 | "_defaultOrder": 20, 634 | "_isFastLaunch": false, 635 | "category": "General purpose", 636 | "gpuNum": 0, 637 | "hideHardwareSpecs": true, 638 | "memoryGiB": 0, 639 | "name": "ml.geospatial.interactive", 640 | "supportedImageNames": [ 641 | "sagemaker-geospatial-v1-0" 642 | ], 643 | "vcpuNum": 0 644 | }, 645 | { 646 | "_defaultOrder": 21, 647 | "_isFastLaunch": true, 648 | "category": "Compute optimized", 649 | "gpuNum": 0, 650 | "hideHardwareSpecs": false, 651 | "memoryGiB": 4, 652 | "name": "ml.c5.large", 653 | "vcpuNum": 2 654 | }, 655 | { 656 | "_defaultOrder": 22, 657 | "_isFastLaunch": false, 658 | "category": "Compute optimized", 659 | "gpuNum": 0, 660 | "hideHardwareSpecs": false, 661 | "memoryGiB": 8, 662 | "name": "ml.c5.xlarge", 663 | "vcpuNum": 4 664 | }, 665 | { 666 | "_defaultOrder": 23, 667 | "_isFastLaunch": false, 668 | "category": "Compute optimized", 669 | "gpuNum": 0, 670 | "hideHardwareSpecs": false, 671 | "memoryGiB": 16, 672 | "name": "ml.c5.2xlarge", 673 | "vcpuNum": 8 674 | }, 675 | { 676 | "_defaultOrder": 24, 677 | "_isFastLaunch": false, 678 | "category": "Compute optimized", 679 | "gpuNum": 0, 680 | "hideHardwareSpecs": false, 681 | "memoryGiB": 32, 682 | "name": "ml.c5.4xlarge", 683 | "vcpuNum": 16 684 | }, 685 | { 686 | "_defaultOrder": 25, 687 | "_isFastLaunch": false, 688 | "category": "Compute optimized", 689 | "gpuNum": 0, 690 | "hideHardwareSpecs": false, 691 | "memoryGiB": 72, 692 | "name": "ml.c5.9xlarge", 693 | "vcpuNum": 36 694 | }, 695 | { 696 | "_defaultOrder": 26, 697 | "_isFastLaunch": false, 698 | "category": "Compute optimized", 699 | "gpuNum": 0, 700 | "hideHardwareSpecs": false, 701 | "memoryGiB": 96, 702 | "name": "ml.c5.12xlarge", 703 | "vcpuNum": 48 704 | }, 705 | { 706 | "_defaultOrder": 27, 707 | "_isFastLaunch": false, 708 | "category": "Compute optimized", 709 | "gpuNum": 0, 710 | "hideHardwareSpecs": false, 711 | "memoryGiB": 144, 712 | "name": "ml.c5.18xlarge", 713 | "vcpuNum": 72 714 | }, 715 | { 716 | "_defaultOrder": 28, 717 | "_isFastLaunch": false, 718 | "category": "Compute optimized", 719 | "gpuNum": 0, 720 | "hideHardwareSpecs": false, 721 | "memoryGiB": 192, 722 | "name": "ml.c5.24xlarge", 723 | "vcpuNum": 96 724 | }, 725 | { 726 | "_defaultOrder": 29, 727 | "_isFastLaunch": true, 728 | "category": "Accelerated computing", 729 | "gpuNum": 1, 730 | "hideHardwareSpecs": false, 731 | "memoryGiB": 16, 732 | "name": "ml.g4dn.xlarge", 733 | "vcpuNum": 4 734 | }, 735 | { 736 | "_defaultOrder": 30, 737 | "_isFastLaunch": false, 738 | "category": "Accelerated computing", 739 | "gpuNum": 1, 740 | "hideHardwareSpecs": false, 741 | "memoryGiB": 32, 742 | "name": "ml.g4dn.2xlarge", 743 | "vcpuNum": 8 744 | }, 745 | { 746 | "_defaultOrder": 31, 747 | "_isFastLaunch": false, 748 | "category": "Accelerated computing", 749 | "gpuNum": 1, 750 | "hideHardwareSpecs": false, 751 | "memoryGiB": 64, 752 | "name": "ml.g4dn.4xlarge", 753 | "vcpuNum": 16 754 | }, 755 | { 756 | "_defaultOrder": 32, 757 | "_isFastLaunch": false, 758 | "category": "Accelerated computing", 759 | "gpuNum": 1, 760 | "hideHardwareSpecs": false, 761 | "memoryGiB": 128, 762 | "name": "ml.g4dn.8xlarge", 763 | "vcpuNum": 32 764 | }, 765 | { 766 | "_defaultOrder": 33, 767 | "_isFastLaunch": false, 768 | "category": "Accelerated computing", 769 | "gpuNum": 4, 770 | "hideHardwareSpecs": false, 771 | "memoryGiB": 192, 772 | "name": "ml.g4dn.12xlarge", 773 | "vcpuNum": 48 774 | }, 775 | { 776 | "_defaultOrder": 34, 777 | "_isFastLaunch": false, 778 | "category": "Accelerated computing", 779 | "gpuNum": 1, 780 | "hideHardwareSpecs": false, 781 | "memoryGiB": 256, 782 | "name": "ml.g4dn.16xlarge", 783 | "vcpuNum": 64 784 | }, 785 | { 786 | "_defaultOrder": 35, 787 | "_isFastLaunch": false, 788 | "category": "Accelerated computing", 789 | "gpuNum": 1, 790 | "hideHardwareSpecs": false, 791 | "memoryGiB": 61, 792 | "name": "ml.p3.2xlarge", 793 | "vcpuNum": 8 794 | }, 795 | { 796 | "_defaultOrder": 36, 797 | "_isFastLaunch": false, 798 | "category": "Accelerated computing", 799 | "gpuNum": 4, 800 | "hideHardwareSpecs": false, 801 | "memoryGiB": 244, 802 | "name": "ml.p3.8xlarge", 803 | "vcpuNum": 32 804 | }, 805 | { 806 | "_defaultOrder": 37, 807 | "_isFastLaunch": false, 808 | "category": "Accelerated computing", 809 | "gpuNum": 8, 810 | "hideHardwareSpecs": false, 811 | "memoryGiB": 488, 812 | "name": "ml.p3.16xlarge", 813 | "vcpuNum": 64 814 | }, 815 | { 816 | "_defaultOrder": 38, 817 | "_isFastLaunch": false, 818 | "category": "Accelerated computing", 819 | "gpuNum": 8, 820 | "hideHardwareSpecs": false, 821 | "memoryGiB": 768, 822 | "name": "ml.p3dn.24xlarge", 823 | "vcpuNum": 96 824 | }, 825 | { 826 | "_defaultOrder": 39, 827 | "_isFastLaunch": false, 828 | "category": "Memory Optimized", 829 | "gpuNum": 0, 830 | "hideHardwareSpecs": false, 831 | "memoryGiB": 16, 832 | "name": "ml.r5.large", 833 | "vcpuNum": 2 834 | }, 835 | { 836 | "_defaultOrder": 40, 837 | "_isFastLaunch": false, 838 | "category": "Memory Optimized", 839 | "gpuNum": 0, 840 | "hideHardwareSpecs": false, 841 | "memoryGiB": 32, 842 | "name": "ml.r5.xlarge", 843 | "vcpuNum": 4 844 | }, 845 | { 846 | "_defaultOrder": 41, 847 | "_isFastLaunch": false, 848 | "category": "Memory Optimized", 849 | "gpuNum": 0, 850 | "hideHardwareSpecs": false, 851 | "memoryGiB": 64, 852 | "name": "ml.r5.2xlarge", 853 | "vcpuNum": 8 854 | }, 855 | { 856 | "_defaultOrder": 42, 857 | "_isFastLaunch": false, 858 | "category": "Memory Optimized", 859 | "gpuNum": 0, 860 | "hideHardwareSpecs": false, 861 | "memoryGiB": 128, 862 | "name": "ml.r5.4xlarge", 863 | "vcpuNum": 16 864 | }, 865 | { 866 | "_defaultOrder": 43, 867 | "_isFastLaunch": false, 868 | "category": "Memory Optimized", 869 | "gpuNum": 0, 870 | "hideHardwareSpecs": false, 871 | "memoryGiB": 256, 872 | "name": "ml.r5.8xlarge", 873 | "vcpuNum": 32 874 | }, 875 | { 876 | "_defaultOrder": 44, 877 | "_isFastLaunch": false, 878 | "category": "Memory Optimized", 879 | "gpuNum": 0, 880 | "hideHardwareSpecs": false, 881 | "memoryGiB": 384, 882 | "name": "ml.r5.12xlarge", 883 | "vcpuNum": 48 884 | }, 885 | { 886 | "_defaultOrder": 45, 887 | "_isFastLaunch": false, 888 | "category": "Memory Optimized", 889 | "gpuNum": 0, 890 | "hideHardwareSpecs": false, 891 | "memoryGiB": 512, 892 | "name": "ml.r5.16xlarge", 893 | "vcpuNum": 64 894 | }, 895 | { 896 | "_defaultOrder": 46, 897 | "_isFastLaunch": false, 898 | "category": "Memory Optimized", 899 | "gpuNum": 0, 900 | "hideHardwareSpecs": false, 901 | "memoryGiB": 768, 902 | "name": "ml.r5.24xlarge", 903 | "vcpuNum": 96 904 | }, 905 | { 906 | "_defaultOrder": 47, 907 | "_isFastLaunch": false, 908 | "category": "Accelerated computing", 909 | "gpuNum": 1, 910 | "hideHardwareSpecs": false, 911 | "memoryGiB": 16, 912 | "name": "ml.g5.xlarge", 913 | "vcpuNum": 4 914 | }, 915 | { 916 | "_defaultOrder": 48, 917 | "_isFastLaunch": false, 918 | "category": "Accelerated computing", 919 | "gpuNum": 1, 920 | "hideHardwareSpecs": false, 921 | "memoryGiB": 32, 922 | "name": "ml.g5.2xlarge", 923 | "vcpuNum": 8 924 | }, 925 | { 926 | "_defaultOrder": 49, 927 | "_isFastLaunch": false, 928 | "category": "Accelerated computing", 929 | "gpuNum": 1, 930 | "hideHardwareSpecs": false, 931 | "memoryGiB": 64, 932 | "name": "ml.g5.4xlarge", 933 | "vcpuNum": 16 934 | }, 935 | { 936 | "_defaultOrder": 50, 937 | "_isFastLaunch": false, 938 | "category": "Accelerated computing", 939 | "gpuNum": 1, 940 | "hideHardwareSpecs": false, 941 | "memoryGiB": 128, 942 | "name": "ml.g5.8xlarge", 943 | "vcpuNum": 32 944 | }, 945 | { 946 | "_defaultOrder": 51, 947 | "_isFastLaunch": false, 948 | "category": "Accelerated computing", 949 | "gpuNum": 1, 950 | "hideHardwareSpecs": false, 951 | "memoryGiB": 256, 952 | "name": "ml.g5.16xlarge", 953 | "vcpuNum": 64 954 | }, 955 | { 956 | "_defaultOrder": 52, 957 | "_isFastLaunch": false, 958 | "category": "Accelerated computing", 959 | "gpuNum": 4, 960 | "hideHardwareSpecs": false, 961 | "memoryGiB": 192, 962 | "name": "ml.g5.12xlarge", 963 | "vcpuNum": 48 964 | }, 965 | { 966 | "_defaultOrder": 53, 967 | "_isFastLaunch": false, 968 | "category": "Accelerated computing", 969 | "gpuNum": 4, 970 | "hideHardwareSpecs": false, 971 | "memoryGiB": 384, 972 | "name": "ml.g5.24xlarge", 973 | "vcpuNum": 96 974 | }, 975 | { 976 | "_defaultOrder": 54, 977 | "_isFastLaunch": false, 978 | "category": "Accelerated computing", 979 | "gpuNum": 8, 980 | "hideHardwareSpecs": false, 981 | "memoryGiB": 768, 982 | "name": "ml.g5.48xlarge", 983 | "vcpuNum": 192 984 | }, 985 | { 986 | "_defaultOrder": 55, 987 | "_isFastLaunch": false, 988 | "category": "Accelerated computing", 989 | "gpuNum": 8, 990 | "hideHardwareSpecs": false, 991 | "memoryGiB": 1152, 992 | "name": "ml.p4d.24xlarge", 993 | "vcpuNum": 96 994 | }, 995 | { 996 | "_defaultOrder": 56, 997 | "_isFastLaunch": false, 998 | "category": "Accelerated computing", 999 | "gpuNum": 8, 1000 | "hideHardwareSpecs": false, 1001 | "memoryGiB": 1152, 1002 | "name": "ml.p4de.24xlarge", 1003 | "vcpuNum": 96 1004 | }, 1005 | { 1006 | "_defaultOrder": 57, 1007 | "_isFastLaunch": false, 1008 | "category": "Accelerated computing", 1009 | "gpuNum": 0, 1010 | "hideHardwareSpecs": false, 1011 | "memoryGiB": 32, 1012 | "name": "ml.trn1.2xlarge", 1013 | "vcpuNum": 8 1014 | }, 1015 | { 1016 | "_defaultOrder": 58, 1017 | "_isFastLaunch": false, 1018 | "category": "Accelerated computing", 1019 | "gpuNum": 0, 1020 | "hideHardwareSpecs": false, 1021 | "memoryGiB": 512, 1022 | "name": "ml.trn1.32xlarge", 1023 | "vcpuNum": 128 1024 | }, 1025 | { 1026 | "_defaultOrder": 59, 1027 | "_isFastLaunch": false, 1028 | "category": "Accelerated computing", 1029 | "gpuNum": 0, 1030 | "hideHardwareSpecs": false, 1031 | "memoryGiB": 512, 1032 | "name": "ml.trn1n.32xlarge", 1033 | "vcpuNum": 128 1034 | } 1035 | ], 1036 | "instance_type": "ml.t3.medium", 1037 | "kernelspec": { 1038 | "display_name": "Python 3 (PyTorch 2.0.0 Python 3.10 CPU Optimized)", 1039 | "language": "python", 1040 | "name": "python3__SAGEMAKER_INTERNAL__arn:aws:sagemaker:us-east-1:081325390199:image/pytorch-2.0.0-cpu-py310" 1041 | }, 1042 | "language_info": { 1043 | "codemirror_mode": { 1044 | "name": "ipython", 1045 | "version": 3 1046 | }, 1047 | "file_extension": ".py", 1048 | "mimetype": "text/x-python", 1049 | "name": "python", 1050 | "nbconvert_exporter": "python", 1051 | "pygments_lexer": "ipython3", 1052 | "version": "3.10.8" 1053 | } 1054 | }, 1055 | "nbformat": 4, 1056 | "nbformat_minor": 5 1057 | } 1058 | -------------------------------------------------------------------------------- /code/3_explainability_CAM.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "ab9f0391-e1b3-43f9-a6f2-251835777c12", 6 | "metadata": {}, 7 | "source": [ 8 | "## Model Explainability using Class Activation Maps" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": null, 14 | "id": "40281b71-20f5-42a9-a2b3-d4faf2160ba1", 15 | "metadata": { 16 | "tags": [] 17 | }, 18 | "outputs": [], 19 | "source": [ 20 | "!pip install grad-cam" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": null, 26 | "id": "d0b91719-8058-4e8a-a0ca-6854d8c6d405", 27 | "metadata": { 28 | "tags": [] 29 | }, 30 | "outputs": [], 31 | "source": [ 32 | "from pytorch_grad_cam import GradCAM, HiResCAM, ScoreCAM, GradCAMPlusPlus, AblationCAM, XGradCAM, EigenCAM, FullGrad\n", 33 | "from pytorch_grad_cam.utils.model_targets import ClassifierOutputTarget\n", 34 | "from pytorch_grad_cam.utils.model_targets import BinaryClassifierOutputTarget\n", 35 | "from pytorch_grad_cam.utils.image import show_cam_on_image\n", 36 | "import torch\n", 37 | "from torchvision import transforms\n", 38 | "from PIL import Image\n", 39 | "import numpy as np" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": null, 45 | "id": "2d0f64c8-2454-438b-be9d-eaaf8664179a", 46 | "metadata": {}, 47 | "outputs": [], 48 | "source": [ 49 | "#download model file from S3\n", 50 | "def download_data_from_s3(s3_uri):\n", 51 | " S3Downloader.download(s3_uri=s3_uri,local_path='',sagemaker_session=sagemaker_session)" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": null, 57 | "id": "481aa292-6279-476a-80de-9f088925d69b", 58 | "metadata": {}, 59 | "outputs": [], 60 | "source": [ 61 | "#Load model\n", 62 | "model = torch.load(local_path)" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": null, 68 | "id": "99077eda-c765-4ff0-b5ad-943ff971a921", 69 | "metadata": { 70 | "tags": [] 71 | }, 72 | "outputs": [], 73 | "source": [ 74 | "dict(model.named_modules())" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": null, 80 | "id": "e60ad376-f2ee-4683-a1cc-6870df300dc8", 81 | "metadata": { 82 | "tags": [] 83 | }, 84 | "outputs": [], 85 | "source": [ 86 | "img = Image.open(\"\")\n", 87 | "\n", 88 | "target_layers = [model.features.denseblock4.denselayer16.conv1]\n", 89 | "\n", 90 | "convert_tensor = transforms.Compose([transforms.Grayscale(num_output_channels=3),transforms.ToTensor()])\n", 91 | "input_tensor = convert_tensor(img).unsqueeze(0)\n", 92 | "# Note: input_tensor can be a batch tensor with several images!" 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": null, 98 | "id": "3267fa68-90a6-46f7-94bf-199f8e41d194", 99 | "metadata": {}, 100 | "outputs": [], 101 | "source": [ 102 | "input_tensor.shape" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": null, 108 | "id": "881a9cca-2022-41d8-bc54-ed522bb4819e", 109 | "metadata": { 110 | "tags": [] 111 | }, 112 | "outputs": [], 113 | "source": [ 114 | "rgb_img = np.float32(img) / 255\n", 115 | "rgb_img = np.stack((rgb_img,)*3, axis=-1)" 116 | ] 117 | }, 118 | { 119 | "cell_type": "code", 120 | "execution_count": null, 121 | "id": "ba72e1e9-e404-46bc-b564-d8e9b9158677", 122 | "metadata": { 123 | "tags": [] 124 | }, 125 | "outputs": [], 126 | "source": [ 127 | "rgb_img.shape" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": null, 133 | "id": "a4e8a2e1-1f2e-4d1b-a82a-8cbbbbc6b74c", 134 | "metadata": { 135 | "tags": [] 136 | }, 137 | "outputs": [], 138 | "source": [ 139 | "# Construct the CAM object once, and then re-use it on many images:\n", 140 | "cam = GradCAMPlusPlus(model=model, target_layers=target_layers)\n", 141 | "\n", 142 | "# You can also use it within a with statement, to make sure it is freed,\n", 143 | "# In case you need to re-create it inside an outer loop:\n", 144 | "# with GradCAM(model=model, target_layers=target_layers, use_cuda=args.use_cuda) as cam:\n", 145 | "# ...\n", 146 | "\n", 147 | "# We have to specify the target we want to generate\n", 148 | "# the Class Activation Maps for.\n", 149 | "# If targets is None, the highest scoring category\n", 150 | "# will be used for every image in the batch.\n", 151 | "# Here we use ClassifierOutputTarget, but you can define your own custom targets\n", 152 | "# That are, for example, combinations of categories, or specific outputs in a non standard model.\n", 153 | "\n", 154 | "targets = [ClassifierOutputTarget(1)]\n", 155 | "\n", 156 | "# You can also pass aug_smooth=True and eigen_smooth=True, to apply smoothing.\n", 157 | "grayscale_cam = cam(input_tensor=input_tensor, targets=targets)\n", 158 | "\n", 159 | "# In this example grayscale_cam has only one image in the batch:\n", 160 | "grayscale_cam = grayscale_cam[0, :]\n", 161 | "visualization = show_cam_on_image(rgb_img,grayscale_cam, use_rgb=True)" 162 | ] 163 | }, 164 | { 165 | "cell_type": "code", 166 | "execution_count": null, 167 | "id": "b6baf561-f3d2-459d-8926-cb3e27829c94", 168 | "metadata": { 169 | "tags": [] 170 | }, 171 | "outputs": [], 172 | "source": [ 173 | "Image.fromarray(visualization)" 174 | ] 175 | }, 176 | { 177 | "cell_type": "code", 178 | "execution_count": null, 179 | "id": "f1440dc4-e6e7-415b-9930-3acec577e994", 180 | "metadata": { 181 | "tags": [] 182 | }, 183 | "outputs": [], 184 | "source": [ 185 | "Image.fromarray(visualization).save(\"\")" 186 | ] 187 | }, 188 | { 189 | "cell_type": "code", 190 | "execution_count": null, 191 | "id": "0f8c1116-a489-4977-b6e4-c96b18cf5e1b", 192 | "metadata": {}, 193 | "outputs": [], 194 | "source": [] 195 | } 196 | ], 197 | "metadata": { 198 | "availableInstances": [ 199 | { 200 | "_defaultOrder": 0, 201 | "_isFastLaunch": true, 202 | "category": "General purpose", 203 | "gpuNum": 0, 204 | "hideHardwareSpecs": false, 205 | "memoryGiB": 4, 206 | "name": "ml.t3.medium", 207 | "vcpuNum": 2 208 | }, 209 | { 210 | "_defaultOrder": 1, 211 | "_isFastLaunch": false, 212 | "category": "General purpose", 213 | "gpuNum": 0, 214 | "hideHardwareSpecs": false, 215 | "memoryGiB": 8, 216 | "name": "ml.t3.large", 217 | "vcpuNum": 2 218 | }, 219 | { 220 | "_defaultOrder": 2, 221 | "_isFastLaunch": false, 222 | "category": "General purpose", 223 | "gpuNum": 0, 224 | "hideHardwareSpecs": false, 225 | "memoryGiB": 16, 226 | "name": "ml.t3.xlarge", 227 | "vcpuNum": 4 228 | }, 229 | { 230 | "_defaultOrder": 3, 231 | "_isFastLaunch": false, 232 | "category": "General purpose", 233 | "gpuNum": 0, 234 | "hideHardwareSpecs": false, 235 | "memoryGiB": 32, 236 | "name": "ml.t3.2xlarge", 237 | "vcpuNum": 8 238 | }, 239 | { 240 | "_defaultOrder": 4, 241 | "_isFastLaunch": true, 242 | "category": "General purpose", 243 | "gpuNum": 0, 244 | "hideHardwareSpecs": false, 245 | "memoryGiB": 8, 246 | "name": "ml.m5.large", 247 | "vcpuNum": 2 248 | }, 249 | { 250 | "_defaultOrder": 5, 251 | "_isFastLaunch": false, 252 | "category": "General purpose", 253 | "gpuNum": 0, 254 | "hideHardwareSpecs": false, 255 | "memoryGiB": 16, 256 | "name": "ml.m5.xlarge", 257 | "vcpuNum": 4 258 | }, 259 | { 260 | "_defaultOrder": 6, 261 | "_isFastLaunch": false, 262 | "category": "General purpose", 263 | "gpuNum": 0, 264 | "hideHardwareSpecs": false, 265 | "memoryGiB": 32, 266 | "name": "ml.m5.2xlarge", 267 | "vcpuNum": 8 268 | }, 269 | { 270 | "_defaultOrder": 7, 271 | "_isFastLaunch": false, 272 | "category": "General purpose", 273 | "gpuNum": 0, 274 | "hideHardwareSpecs": false, 275 | "memoryGiB": 64, 276 | "name": "ml.m5.4xlarge", 277 | "vcpuNum": 16 278 | }, 279 | { 280 | "_defaultOrder": 8, 281 | "_isFastLaunch": false, 282 | "category": "General purpose", 283 | "gpuNum": 0, 284 | "hideHardwareSpecs": false, 285 | "memoryGiB": 128, 286 | "name": "ml.m5.8xlarge", 287 | "vcpuNum": 32 288 | }, 289 | { 290 | "_defaultOrder": 9, 291 | "_isFastLaunch": false, 292 | "category": "General purpose", 293 | "gpuNum": 0, 294 | "hideHardwareSpecs": false, 295 | "memoryGiB": 192, 296 | "name": "ml.m5.12xlarge", 297 | "vcpuNum": 48 298 | }, 299 | { 300 | "_defaultOrder": 10, 301 | "_isFastLaunch": false, 302 | "category": "General purpose", 303 | "gpuNum": 0, 304 | "hideHardwareSpecs": false, 305 | "memoryGiB": 256, 306 | "name": "ml.m5.16xlarge", 307 | "vcpuNum": 64 308 | }, 309 | { 310 | "_defaultOrder": 11, 311 | "_isFastLaunch": false, 312 | "category": "General purpose", 313 | "gpuNum": 0, 314 | "hideHardwareSpecs": false, 315 | "memoryGiB": 384, 316 | "name": "ml.m5.24xlarge", 317 | "vcpuNum": 96 318 | }, 319 | { 320 | "_defaultOrder": 12, 321 | "_isFastLaunch": false, 322 | "category": "General purpose", 323 | "gpuNum": 0, 324 | "hideHardwareSpecs": false, 325 | "memoryGiB": 8, 326 | "name": "ml.m5d.large", 327 | "vcpuNum": 2 328 | }, 329 | { 330 | "_defaultOrder": 13, 331 | "_isFastLaunch": false, 332 | "category": "General purpose", 333 | "gpuNum": 0, 334 | "hideHardwareSpecs": false, 335 | "memoryGiB": 16, 336 | "name": "ml.m5d.xlarge", 337 | "vcpuNum": 4 338 | }, 339 | { 340 | "_defaultOrder": 14, 341 | "_isFastLaunch": false, 342 | "category": "General purpose", 343 | "gpuNum": 0, 344 | "hideHardwareSpecs": false, 345 | "memoryGiB": 32, 346 | "name": "ml.m5d.2xlarge", 347 | "vcpuNum": 8 348 | }, 349 | { 350 | "_defaultOrder": 15, 351 | "_isFastLaunch": false, 352 | "category": "General purpose", 353 | "gpuNum": 0, 354 | "hideHardwareSpecs": false, 355 | "memoryGiB": 64, 356 | "name": "ml.m5d.4xlarge", 357 | "vcpuNum": 16 358 | }, 359 | { 360 | "_defaultOrder": 16, 361 | "_isFastLaunch": false, 362 | "category": "General purpose", 363 | "gpuNum": 0, 364 | "hideHardwareSpecs": false, 365 | "memoryGiB": 128, 366 | "name": "ml.m5d.8xlarge", 367 | "vcpuNum": 32 368 | }, 369 | { 370 | "_defaultOrder": 17, 371 | "_isFastLaunch": false, 372 | "category": "General purpose", 373 | "gpuNum": 0, 374 | "hideHardwareSpecs": false, 375 | "memoryGiB": 192, 376 | "name": "ml.m5d.12xlarge", 377 | "vcpuNum": 48 378 | }, 379 | { 380 | "_defaultOrder": 18, 381 | "_isFastLaunch": false, 382 | "category": "General purpose", 383 | "gpuNum": 0, 384 | "hideHardwareSpecs": false, 385 | "memoryGiB": 256, 386 | "name": "ml.m5d.16xlarge", 387 | "vcpuNum": 64 388 | }, 389 | { 390 | "_defaultOrder": 19, 391 | "_isFastLaunch": false, 392 | "category": "General purpose", 393 | "gpuNum": 0, 394 | "hideHardwareSpecs": false, 395 | "memoryGiB": 384, 396 | "name": "ml.m5d.24xlarge", 397 | "vcpuNum": 96 398 | }, 399 | { 400 | "_defaultOrder": 20, 401 | "_isFastLaunch": false, 402 | "category": "General purpose", 403 | "gpuNum": 0, 404 | "hideHardwareSpecs": true, 405 | "memoryGiB": 0, 406 | "name": "ml.geospatial.interactive", 407 | "supportedImageNames": [ 408 | "sagemaker-geospatial-v1-0" 409 | ], 410 | "vcpuNum": 0 411 | }, 412 | { 413 | "_defaultOrder": 21, 414 | "_isFastLaunch": true, 415 | "category": "Compute optimized", 416 | "gpuNum": 0, 417 | "hideHardwareSpecs": false, 418 | "memoryGiB": 4, 419 | "name": "ml.c5.large", 420 | "vcpuNum": 2 421 | }, 422 | { 423 | "_defaultOrder": 22, 424 | "_isFastLaunch": false, 425 | "category": "Compute optimized", 426 | "gpuNum": 0, 427 | "hideHardwareSpecs": false, 428 | "memoryGiB": 8, 429 | "name": "ml.c5.xlarge", 430 | "vcpuNum": 4 431 | }, 432 | { 433 | "_defaultOrder": 23, 434 | "_isFastLaunch": false, 435 | "category": "Compute optimized", 436 | "gpuNum": 0, 437 | "hideHardwareSpecs": false, 438 | "memoryGiB": 16, 439 | "name": "ml.c5.2xlarge", 440 | "vcpuNum": 8 441 | }, 442 | { 443 | "_defaultOrder": 24, 444 | "_isFastLaunch": false, 445 | "category": "Compute optimized", 446 | "gpuNum": 0, 447 | "hideHardwareSpecs": false, 448 | "memoryGiB": 32, 449 | "name": "ml.c5.4xlarge", 450 | "vcpuNum": 16 451 | }, 452 | { 453 | "_defaultOrder": 25, 454 | "_isFastLaunch": false, 455 | "category": "Compute optimized", 456 | "gpuNum": 0, 457 | "hideHardwareSpecs": false, 458 | "memoryGiB": 72, 459 | "name": "ml.c5.9xlarge", 460 | "vcpuNum": 36 461 | }, 462 | { 463 | "_defaultOrder": 26, 464 | "_isFastLaunch": false, 465 | "category": "Compute optimized", 466 | "gpuNum": 0, 467 | "hideHardwareSpecs": false, 468 | "memoryGiB": 96, 469 | "name": "ml.c5.12xlarge", 470 | "vcpuNum": 48 471 | }, 472 | { 473 | "_defaultOrder": 27, 474 | "_isFastLaunch": false, 475 | "category": "Compute optimized", 476 | "gpuNum": 0, 477 | "hideHardwareSpecs": false, 478 | "memoryGiB": 144, 479 | "name": "ml.c5.18xlarge", 480 | "vcpuNum": 72 481 | }, 482 | { 483 | "_defaultOrder": 28, 484 | "_isFastLaunch": false, 485 | "category": "Compute optimized", 486 | "gpuNum": 0, 487 | "hideHardwareSpecs": false, 488 | "memoryGiB": 192, 489 | "name": "ml.c5.24xlarge", 490 | "vcpuNum": 96 491 | }, 492 | { 493 | "_defaultOrder": 29, 494 | "_isFastLaunch": true, 495 | "category": "Accelerated computing", 496 | "gpuNum": 1, 497 | "hideHardwareSpecs": false, 498 | "memoryGiB": 16, 499 | "name": "ml.g4dn.xlarge", 500 | "vcpuNum": 4 501 | }, 502 | { 503 | "_defaultOrder": 30, 504 | "_isFastLaunch": false, 505 | "category": "Accelerated computing", 506 | "gpuNum": 1, 507 | "hideHardwareSpecs": false, 508 | "memoryGiB": 32, 509 | "name": "ml.g4dn.2xlarge", 510 | "vcpuNum": 8 511 | }, 512 | { 513 | "_defaultOrder": 31, 514 | "_isFastLaunch": false, 515 | "category": "Accelerated computing", 516 | "gpuNum": 1, 517 | "hideHardwareSpecs": false, 518 | "memoryGiB": 64, 519 | "name": "ml.g4dn.4xlarge", 520 | "vcpuNum": 16 521 | }, 522 | { 523 | "_defaultOrder": 32, 524 | "_isFastLaunch": false, 525 | "category": "Accelerated computing", 526 | "gpuNum": 1, 527 | "hideHardwareSpecs": false, 528 | "memoryGiB": 128, 529 | "name": "ml.g4dn.8xlarge", 530 | "vcpuNum": 32 531 | }, 532 | { 533 | "_defaultOrder": 33, 534 | "_isFastLaunch": false, 535 | "category": "Accelerated computing", 536 | "gpuNum": 4, 537 | "hideHardwareSpecs": false, 538 | "memoryGiB": 192, 539 | "name": "ml.g4dn.12xlarge", 540 | "vcpuNum": 48 541 | }, 542 | { 543 | "_defaultOrder": 34, 544 | "_isFastLaunch": false, 545 | "category": "Accelerated computing", 546 | "gpuNum": 1, 547 | "hideHardwareSpecs": false, 548 | "memoryGiB": 256, 549 | "name": "ml.g4dn.16xlarge", 550 | "vcpuNum": 64 551 | }, 552 | { 553 | "_defaultOrder": 35, 554 | "_isFastLaunch": false, 555 | "category": "Accelerated computing", 556 | "gpuNum": 1, 557 | "hideHardwareSpecs": false, 558 | "memoryGiB": 61, 559 | "name": "ml.p3.2xlarge", 560 | "vcpuNum": 8 561 | }, 562 | { 563 | "_defaultOrder": 36, 564 | "_isFastLaunch": false, 565 | "category": "Accelerated computing", 566 | "gpuNum": 4, 567 | "hideHardwareSpecs": false, 568 | "memoryGiB": 244, 569 | "name": "ml.p3.8xlarge", 570 | "vcpuNum": 32 571 | }, 572 | { 573 | "_defaultOrder": 37, 574 | "_isFastLaunch": false, 575 | "category": "Accelerated computing", 576 | "gpuNum": 8, 577 | "hideHardwareSpecs": false, 578 | "memoryGiB": 488, 579 | "name": "ml.p3.16xlarge", 580 | "vcpuNum": 64 581 | }, 582 | { 583 | "_defaultOrder": 38, 584 | "_isFastLaunch": false, 585 | "category": "Accelerated computing", 586 | "gpuNum": 8, 587 | "hideHardwareSpecs": false, 588 | "memoryGiB": 768, 589 | "name": "ml.p3dn.24xlarge", 590 | "vcpuNum": 96 591 | }, 592 | { 593 | "_defaultOrder": 39, 594 | "_isFastLaunch": false, 595 | "category": "Memory Optimized", 596 | "gpuNum": 0, 597 | "hideHardwareSpecs": false, 598 | "memoryGiB": 16, 599 | "name": "ml.r5.large", 600 | "vcpuNum": 2 601 | }, 602 | { 603 | "_defaultOrder": 40, 604 | "_isFastLaunch": false, 605 | "category": "Memory Optimized", 606 | "gpuNum": 0, 607 | "hideHardwareSpecs": false, 608 | "memoryGiB": 32, 609 | "name": "ml.r5.xlarge", 610 | "vcpuNum": 4 611 | }, 612 | { 613 | "_defaultOrder": 41, 614 | "_isFastLaunch": false, 615 | "category": "Memory Optimized", 616 | "gpuNum": 0, 617 | "hideHardwareSpecs": false, 618 | "memoryGiB": 64, 619 | "name": "ml.r5.2xlarge", 620 | "vcpuNum": 8 621 | }, 622 | { 623 | "_defaultOrder": 42, 624 | "_isFastLaunch": false, 625 | "category": "Memory Optimized", 626 | "gpuNum": 0, 627 | "hideHardwareSpecs": false, 628 | "memoryGiB": 128, 629 | "name": "ml.r5.4xlarge", 630 | "vcpuNum": 16 631 | }, 632 | { 633 | "_defaultOrder": 43, 634 | "_isFastLaunch": false, 635 | "category": "Memory Optimized", 636 | "gpuNum": 0, 637 | "hideHardwareSpecs": false, 638 | "memoryGiB": 256, 639 | "name": "ml.r5.8xlarge", 640 | "vcpuNum": 32 641 | }, 642 | { 643 | "_defaultOrder": 44, 644 | "_isFastLaunch": false, 645 | "category": "Memory Optimized", 646 | "gpuNum": 0, 647 | "hideHardwareSpecs": false, 648 | "memoryGiB": 384, 649 | "name": "ml.r5.12xlarge", 650 | "vcpuNum": 48 651 | }, 652 | { 653 | "_defaultOrder": 45, 654 | "_isFastLaunch": false, 655 | "category": "Memory Optimized", 656 | "gpuNum": 0, 657 | "hideHardwareSpecs": false, 658 | "memoryGiB": 512, 659 | "name": "ml.r5.16xlarge", 660 | "vcpuNum": 64 661 | }, 662 | { 663 | "_defaultOrder": 46, 664 | "_isFastLaunch": false, 665 | "category": "Memory Optimized", 666 | "gpuNum": 0, 667 | "hideHardwareSpecs": false, 668 | "memoryGiB": 768, 669 | "name": "ml.r5.24xlarge", 670 | "vcpuNum": 96 671 | }, 672 | { 673 | "_defaultOrder": 47, 674 | "_isFastLaunch": false, 675 | "category": "Accelerated computing", 676 | "gpuNum": 1, 677 | "hideHardwareSpecs": false, 678 | "memoryGiB": 16, 679 | "name": "ml.g5.xlarge", 680 | "vcpuNum": 4 681 | }, 682 | { 683 | "_defaultOrder": 48, 684 | "_isFastLaunch": false, 685 | "category": "Accelerated computing", 686 | "gpuNum": 1, 687 | "hideHardwareSpecs": false, 688 | "memoryGiB": 32, 689 | "name": "ml.g5.2xlarge", 690 | "vcpuNum": 8 691 | }, 692 | { 693 | "_defaultOrder": 49, 694 | "_isFastLaunch": false, 695 | "category": "Accelerated computing", 696 | "gpuNum": 1, 697 | "hideHardwareSpecs": false, 698 | "memoryGiB": 64, 699 | "name": "ml.g5.4xlarge", 700 | "vcpuNum": 16 701 | }, 702 | { 703 | "_defaultOrder": 50, 704 | "_isFastLaunch": false, 705 | "category": "Accelerated computing", 706 | "gpuNum": 1, 707 | "hideHardwareSpecs": false, 708 | "memoryGiB": 128, 709 | "name": "ml.g5.8xlarge", 710 | "vcpuNum": 32 711 | }, 712 | { 713 | "_defaultOrder": 51, 714 | "_isFastLaunch": false, 715 | "category": "Accelerated computing", 716 | "gpuNum": 1, 717 | "hideHardwareSpecs": false, 718 | "memoryGiB": 256, 719 | "name": "ml.g5.16xlarge", 720 | "vcpuNum": 64 721 | }, 722 | { 723 | "_defaultOrder": 52, 724 | "_isFastLaunch": false, 725 | "category": "Accelerated computing", 726 | "gpuNum": 4, 727 | "hideHardwareSpecs": false, 728 | "memoryGiB": 192, 729 | "name": "ml.g5.12xlarge", 730 | "vcpuNum": 48 731 | }, 732 | { 733 | "_defaultOrder": 53, 734 | "_isFastLaunch": false, 735 | "category": "Accelerated computing", 736 | "gpuNum": 4, 737 | "hideHardwareSpecs": false, 738 | "memoryGiB": 384, 739 | "name": "ml.g5.24xlarge", 740 | "vcpuNum": 96 741 | }, 742 | { 743 | "_defaultOrder": 54, 744 | "_isFastLaunch": false, 745 | "category": "Accelerated computing", 746 | "gpuNum": 8, 747 | "hideHardwareSpecs": false, 748 | "memoryGiB": 768, 749 | "name": "ml.g5.48xlarge", 750 | "vcpuNum": 192 751 | }, 752 | { 753 | "_defaultOrder": 55, 754 | "_isFastLaunch": false, 755 | "category": "Accelerated computing", 756 | "gpuNum": 8, 757 | "hideHardwareSpecs": false, 758 | "memoryGiB": 1152, 759 | "name": "ml.p4d.24xlarge", 760 | "vcpuNum": 96 761 | }, 762 | { 763 | "_defaultOrder": 56, 764 | "_isFastLaunch": false, 765 | "category": "Accelerated computing", 766 | "gpuNum": 8, 767 | "hideHardwareSpecs": false, 768 | "memoryGiB": 1152, 769 | "name": "ml.p4de.24xlarge", 770 | "vcpuNum": 96 771 | } 772 | ], 773 | "instance_type": "ml.t3.medium", 774 | "kernelspec": { 775 | "display_name": "Python 3 (PyTorch 2.0.0 Python 3.10 CPU Optimized)", 776 | "language": "python", 777 | "name": "python3__SAGEMAKER_INTERNAL__arn:aws:sagemaker:us-east-1:081325390199:image/pytorch-2.0.0-cpu-py310" 778 | }, 779 | "language_info": { 780 | "codemirror_mode": { 781 | "name": "ipython", 782 | "version": 3 783 | }, 784 | "file_extension": ".py", 785 | "mimetype": "text/x-python", 786 | "name": "python", 787 | "nbconvert_exporter": "python", 788 | "pygments_lexer": "ipython3", 789 | "version": "3.10.8" 790 | } 791 | }, 792 | "nbformat": 4, 793 | "nbformat_minor": 5 794 | } 795 | -------------------------------------------------------------------------------- /img/Image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/radiology-worklist-ich-detection/a14ea8af4d7aea4e1e99a12dd393d87072823196/img/Image.jpg -------------------------------------------------------------------------------- /img/ich-img-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/radiology-worklist-ich-detection/a14ea8af4d7aea4e1e99a12dd393d87072823196/img/ich-img-1.png -------------------------------------------------------------------------------- /img/ich-img-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/radiology-worklist-ich-detection/a14ea8af4d7aea4e1e99a12dd393d87072823196/img/ich-img-2.png -------------------------------------------------------------------------------- /img/ich-img-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/radiology-worklist-ich-detection/a14ea8af4d7aea4e1e99a12dd393d87072823196/img/ich-img-3.png -------------------------------------------------------------------------------- /img/ich_img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/radiology-worklist-ich-detection/a14ea8af4d7aea4e1e99a12dd393d87072823196/img/ich_img_1.png -------------------------------------------------------------------------------- /img/ich_img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/radiology-worklist-ich-detection/a14ea8af4d7aea4e1e99a12dd393d87072823196/img/ich_img_2.png -------------------------------------------------------------------------------- /img/ich_img_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/radiology-worklist-ich-detection/a14ea8af4d7aea4e1e99a12dd393d87072823196/img/ich_img_3.png -------------------------------------------------------------------------------- /img/ich_img_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/radiology-worklist-ich-detection/a14ea8af4d7aea4e1e99a12dd393d87072823196/img/ich_img_4.png -------------------------------------------------------------------------------- /img/ich_img_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/radiology-worklist-ich-detection/a14ea8af4d7aea4e1e99a12dd393d87072823196/img/ich_img_5.png -------------------------------------------------------------------------------- /img/prioritization-steps.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/radiology-worklist-ich-detection/a14ea8af4d7aea4e1e99a12dd393d87072823196/img/prioritization-steps.jpg --------------------------------------------------------------------------------