{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"#import monai\n!pip install /kaggle/input/my-lib/monai-1.1.0-202212191849-py3-none-any.whl","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-12-29T05:58:20.98201Z","iopub.execute_input":"2022-12-29T05:58:20.982434Z","iopub.status.idle":"2022-12-29T05:58:31.494055Z","shell.execute_reply.started":"2022-12-29T05:58:20.982398Z","shell.execute_reply":"2022-12-29T05:58:31.492906Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nimport os\nimport shutil\nimport tempfile\nimport matplotlib.pyplot as plt\nimport PIL\nimport torch\nfrom torchvision.io import read_image\nimport numpy as np\nimport pandas as pd\nfrom sklearn.metrics import classification_report\n\nfrom torch.utils.tensorboard import SummaryWriter\n\nfrom monai.apps import download_and_extract\nfrom monai.config import print_config\nfrom monai.data import decollate_batch, DataLoader\nfrom monai.metrics import ROCAUCMetric, ConfusionMatrixMetric\nfrom monai.networks.nets import DenseNet121\nfrom monai.transforms import (\n    Activations,\n    EnsureChannelFirst,\n    AsDiscrete,\n    Compose,\n    LoadImage,\n    RandFlip,\n    RandRotate,\n    RandZoom,\n    ScaleIntensity,\n)\nfrom torchvision.transforms import Resize\nfrom monai.utils import set_determinism\n\nprint_config()","metadata":{"execution":{"iopub.status.busy":"2022-12-29T05:58:31.496507Z","iopub.execute_input":"2022-12-29T05:58:31.497192Z","iopub.status.idle":"2022-12-29T05:58:37.553237Z","shell.execute_reply.started":"2022-12-29T05:58:31.497148Z","shell.execute_reply":"2022-12-29T05:58:37.552304Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"directory = os.environ.get(\"temp\")\nroot_dir = tempfile.mkdtemp() if directory is None else directory\nprint(root_dir)","metadata":{"execution":{"iopub.status.busy":"2022-12-29T05:58:37.554547Z","iopub.execute_input":"2022-12-29T05:58:37.555454Z","iopub.status.idle":"2022-12-29T05:58:37.564141Z","shell.execute_reply.started":"2022-12-29T05:58:37.555415Z","shell.execute_reply":"2022-12-29T05:58:37.563344Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_dir = os.path.join(root_dir, \"/kaggle/input/rsna-breast-cancer-processing/img_512/\")\nprint(\"Data: \",data_dir)\nlabel_dir = os.path.join(root_dir, \"/kaggle/input/rsna-breast-cancer-detection/train.csv\")\nprint(\"Label: \",label_dir)","metadata":{"execution":{"iopub.status.busy":"2022-12-29T05:58:37.566779Z","iopub.execute_input":"2022-12-29T05:58:37.56715Z","iopub.status.idle":"2022-12-29T05:58:37.577911Z","shell.execute_reply.started":"2022-12-29T05:58:37.567106Z","shell.execute_reply":"2022-12-29T05:58:37.577034Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_transforms = Compose(\n    [\n        LoadImage(image_only=True),\n        EnsureChannelFirst(),\n        ScaleIntensity(),\n        Resize((256,256)),\n        RandRotate(range_x=np.pi / 12, prob=0.5, keep_size=True),\n        RandFlip(spatial_axis=0, prob=0.5),\n        RandZoom(min_zoom=0.9, max_zoom=1.1, prob=0.5),\n    ]\n)\n\nval_transforms = Compose(\n    [LoadImage(image_only=True), EnsureChannelFirst(), ScaleIntensity()])\n\ny_pred_trans = Compose([Activations(softmax=True)])\ny_trans = Compose([AsDiscrete(to_onehot=2)])","metadata":{"execution":{"iopub.status.busy":"2022-12-29T05:58:37.579276Z","iopub.execute_input":"2022-12-29T05:58:37.579621Z","iopub.status.idle":"2022-12-29T05:58:37.600068Z","shell.execute_reply.started":"2022-12-29T05:58:37.579587Z","shell.execute_reply":"2022-12-29T05:58:37.599165Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\nimage_folder = \"/kaggle/input/rsna-breast-cancer-processing/img_512/\"\nlabels = pd.read_csv(\"/kaggle/input/rsna-breast-cancer-detection/train.csv\")\ntrainlb, validlb = train_test_split(labels, test_size=0.2)\ntest = \"/kaggle/working/test\"","metadata":{"execution":{"iopub.status.busy":"2022-12-29T05:58:37.601564Z","iopub.execute_input":"2022-12-29T05:58:37.603053Z","iopub.status.idle":"2022-12-29T05:58:37.745244Z","shell.execute_reply.started":"2022-12-29T05:58:37.603018Z","shell.execute_reply":"2022-12-29T05:58:37.744103Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class BREASTDataset(torch.utils.data.Dataset):\n    def __init__(self, image_folder, labels, transforms, type=\"train\"):\n        self.labels = labels\n        self.image_folder = image_folder\n        self.transforms = transforms\n\n    def __len__(self):\n        return len(self.labels)\n\n    def __getitem__(self, index):\n        patient_id = self.labels.iloc[index]['patient_id']\n        image_id = self.labels.iloc[index]['image_id']\n        img_path = f\"{self.image_folder}/{patient_id}_{image_id}.jpg\"\n#         image = read_image(img_path)\n        label = self.labels.iloc[index][\"cancer\"]\n        label = torch.as_tensor(label)\n        label = torch.nn.functional.one_hot(label,2).float()\n        return self.transforms(img_path), label\n\n\ntrain_ds = BREASTDataset(image_folder, trainlb, train_transforms)\nvalid_ds = BREASTDataset(image_folder, validlb, train_transforms)\n\ntrain_loader = DataLoader(train_ds, batch_size=64, shuffle=True)\nvalid_loader = DataLoader(valid_ds, batch_size=64, shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2022-12-29T05:58:37.746527Z","iopub.execute_input":"2022-12-29T05:58:37.747131Z","iopub.status.idle":"2022-12-29T05:58:37.764167Z","shell.execute_reply.started":"2022-12-29T05:58:37.747094Z","shell.execute_reply":"2022-12-29T05:58:37.763045Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# next(iter(valid_loader))","metadata":{"execution":{"iopub.status.busy":"2022-12-29T05:58:37.765312Z","iopub.execute_input":"2022-12-29T05:58:37.765839Z","iopub.status.idle":"2022-12-29T05:58:37.771016Z","shell.execute_reply.started":"2022-12-29T05:58:37.765805Z","shell.execute_reply":"2022-12-29T05:58:37.769969Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n# Create DenseNet121, CrossEntropyLoss and Adam optimizer\nmodel = torch.nn.Sequential(\n    DenseNet121(spatial_dims=2, in_channels=1, out_channels=2),\n    torch.nn.Softmax(1)).to(device)","metadata":{"execution":{"iopub.status.busy":"2022-12-29T05:58:37.773994Z","iopub.execute_input":"2022-12-29T05:58:37.774642Z","iopub.status.idle":"2022-12-29T05:58:41.144985Z","shell.execute_reply.started":"2022-12-29T05:58:37.774607Z","shell.execute_reply":"2022-12-29T05:58:41.143967Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# loss_function = torch.nn.CrossEntropyLoss()\nloss_function = torch.nn.BCEWithLogitsLoss()  # also works with this data\n\noptimizer = torch.optim.Adam(model.parameters(), 1e-4)\n\n# start a typical PyTorch training\nval_interval = 2\nbest_metric = -1\nbest_metric_epoch = -1\nepoch_loss_values = []\nmetric_values = []\nwriter = SummaryWriter()\nmax_epochs = 8","metadata":{"execution":{"iopub.status.busy":"2022-12-29T05:58:41.15158Z","iopub.execute_input":"2022-12-29T05:58:41.154238Z","iopub.status.idle":"2022-12-29T05:58:45.548452Z","shell.execute_reply.started":"2022-12-29T05:58:41.154184Z","shell.execute_reply":"2022-12-29T05:58:45.547416Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nfor epoch in range(max_epochs):\n    print(\"-\" * 10)\n    print(f\"epoch {epoch + 1}/{max_epochs}\")\n    model.train()\n    epoch_loss = 0\n    step = 0\n\n    for batch_data in train_loader:\n        step += 1\n        inputs, labels = batch_data[0].to(device), batch_data[1].to(device)\n        optimizer.zero_grad()\n        outputs = model(inputs)\n        loss = loss_function(outputs, labels)\n        loss.backward()\n        optimizer.step()\n        epoch_loss += loss.item()\n        epoch_len = len(train_ds) // train_loader.batch_size\n        print(f\"{step}/{epoch_len}, train_loss: {loss.item():.4f}\")\n        writer.add_scalar(\"train_loss\", loss.item(), epoch_len * epoch + step)\n\n    epoch_loss /= step\n    epoch_loss_values.append(epoch_loss)\n    print(f\"epoch {epoch + 1} average loss: {epoch_loss:.4f}\")\n\n    if (epoch + 1) % val_interval == 0:\n        model.eval()\n\n        num_correct = 0.0\n        metric_count = 0\n        for val_data in valid_loader:\n            val_images, val_labels = val_data[0].to(device), val_data[1].to(device)\n            with torch.no_grad():\n                val_outputs = model(val_images)\n                value = torch.eq(val_outputs.argmax(dim=1), val_labels.argmax(dim=1))\n                metric_count += len(value)\n                num_correct += value.sum().item()\n\n        metric = num_correct / metric_count\n        metric_values.append(metric)\n\n        if metric > best_metric:\n            best_metric = metric\n            best_metric_epoch = epoch + 1\n            torch.save(model.state_dict(), \"best_metric_model_classification3d_array.pth\")\n            print(\"saved new best metric model\")\n\n        print(f\"Current epoch: {epoch+1} current accuracy: {metric:.4f} \")\n        print(f\"Best accuracy: {best_metric:.4f} at epoch {best_metric_epoch}\")\n        writer.add_scalar(\"val_accuracy\", metric, epoch + 1)\n\nprint(f\"Training completed, best_metric: {best_metric:.4f} at epoch: {best_metric_epoch}\")\nwriter.close()","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2022-12-29T05:58:45.551602Z","iopub.execute_input":"2022-12-29T05:58:45.552785Z","iopub.status.idle":"2022-12-29T05:59:15.66775Z","shell.execute_reply.started":"2022-12-29T05:58:45.552747Z","shell.execute_reply":"2022-12-29T05:59:15.666153Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Convert test set","metadata":{}},{"cell_type":"code","source":"import SimpleITK as sitk\nimport os\nimport multiprocessing\ndef convert_image(input_file_name,output_file_name, new_width=None):\n    try:\n        image_file_reader = sitk.ImageFileReader()\n        image_file_reader.SetImageIO(\"GDCMImageIO\")\n        image_file_reader.SetFileName(input_file_name)\n        image_file_reader.ReadImageInformation()\n        image_size = list(image_file_reader.GetSize())\n        if len(image_size) == 3 and image_size[2] == 1:\n            image_size[2] = 0\n        image_file_reader.SetExtractSize(image_size)\n        image = image_file_reader.Execute()\n        if new_width:\n            original_size = image.GetSize()\n            original_spacing = image.GetSpacing()\n            new_spacing = [\n                (original_size[0] - 1) * original_spacing[0] / (new_width - 1)\n            ] * 2\n            new_size = [\n                new_width,\n                int(\n                    (original_size[1] - 1)\n                    * original_spacing[1]\n                    / new_spacing[1]\n                ),\n            ]\n            image = sitk.Resample(\n                image1=image,\n                size=new_size,\n                transform=sitk.Transform(),\n                interpolator=sitk.sitkLinear,\n                outputOrigin=image.GetOrigin(),\n                outputSpacing=new_spacing,\n                outputDirection=image.GetDirection(),\n                defaultPixelValue=0,\n                outputPixelType=image.GetPixelID(),\n            )\n        if image.GetNumberOfComponentsPerPixel() == 1:\n            image = sitk.RescaleIntensity(image, 0, 255)\n            if (\n                image_file_reader.GetMetaData(\"0028|0004\").strip() == \"MONOCHROME1\"\n            ):\n                image = sitk.InvertIntensity(image, maximum=255)\n            image = sitk.Cast(image, sitk.sitkUInt8)\n        sitk.WriteImage(image, output_file_name)\n        print(output_file_name)\n        return True\n    except BaseException:\n        return False\n    \n    \n!mkdir /kaggle/working/test\nPATH = \"/kaggle/input/rsna-breast-cancer-detection/test_images/10008\"\n\nfor i in os.listdir(PATH):\n    name = i.split(\".dcm\")[0]\n    convert_image(f\"{PATH}/{i}\",f\"/kaggle/working/test/10008_{name}.png\",512)","metadata":{"execution":{"iopub.status.busy":"2022-12-29T05:59:18.732946Z","iopub.execute_input":"2022-12-29T05:59:18.733426Z","iopub.status.idle":"2022-12-29T05:59:24.244782Z","shell.execute_reply.started":"2022-12-29T05:59:18.733393Z","shell.execute_reply":"2022-12-29T05:59:24.243473Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image = PIL.Image.open(\"/kaggle/working/test/10008_1591370361.png\")\nplt.imshow(image)","metadata":{"execution":{"iopub.status.busy":"2022-12-29T05:59:24.250337Z","iopub.execute_input":"2022-12-29T05:59:24.252651Z","iopub.status.idle":"2022-12-29T05:59:24.578958Z","shell.execute_reply.started":"2022-12-29T05:59:24.252608Z","shell.execute_reply":"2022-12-29T05:59:24.577964Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Try predict","metadata":{}},{"cell_type":"code","source":"test_folder = \"/kaggle/working/test\"\ntest_labels =  \"/kaggle/input/rsna-breast-cancer-detection/test.csv\"\ntest_ds = BREASTDataset(test_folder, test_labels, train_transforms)\n# test_loader = DataLoader(test_ds, batch_size=1, shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2022-12-29T05:59:24.583377Z","iopub.execute_input":"2022-12-29T05:59:24.585684Z","iopub.status.idle":"2022-12-29T05:59:24.592629Z","shell.execute_reply.started":"2022-12-29T05:59:24.585644Z","shell.execute_reply":"2022-12-29T05:59:24.591697Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df = pd.read_csv(\"/kaggle/input/rsna-breast-cancer-detection/test.csv\")\ntest_path = \"/kaggle/working/test\"\npredict = []\nfor idx, row in test_df.iterrows():\n#     print(f\"{row['patient_id']}_{row['image_id']}.jpg\")\n    item = f\"{row['patient_id']}_{row['image_id']}.png\"\n    image = train_transforms(f\"{test_path}/{item}\")\n    image = torch.unsqueeze(image, 0).to(device)\n    pred = model(image)[0]\n    predict.append([row[\"prediction_id\"],pred[1].item()])","metadata":{"execution":{"iopub.status.busy":"2022-12-29T05:59:24.598992Z","iopub.execute_input":"2022-12-29T05:59:24.601789Z","iopub.status.idle":"2022-12-29T05:59:25.007153Z","shell.execute_reply.started":"2022-12-29T05:59:24.601748Z","shell.execute_reply":"2022-12-29T05:59:25.006101Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predict = pd.DataFrame(predict,columns=[\"prediction_id\",\"cancer\"])","metadata":{"execution":{"iopub.status.busy":"2022-12-29T05:59:25.012475Z","iopub.execute_input":"2022-12-29T05:59:25.014784Z","iopub.status.idle":"2022-12-29T05:59:25.023017Z","shell.execute_reply.started":"2022-12-29T05:59:25.014742Z","shell.execute_reply":"2022-12-29T05:59:25.022063Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predict.to_csv(\"/kaggle/working/submission.csv\")","metadata":{"execution":{"iopub.status.busy":"2022-12-29T05:59:25.027935Z","iopub.execute_input":"2022-12-29T05:59:25.030689Z","iopub.status.idle":"2022-12-29T05:59:25.040282Z","shell.execute_reply.started":"2022-12-29T05:59:25.03065Z","shell.execute_reply":"2022-12-29T05:59:25.039324Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}