{"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 numpy as np\nimport cv2\nfrom pydicom import dcmread\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom IPython.display import clear_output\nimport os\nfrom matplotlib.patches import Rectangle\nimport torch\nfrom torch import nn\nfrom torch.utils import data\nfrom torch.utils.data import TensorDataset, DataLoader\nfrom torchvision import transforms\nimport torchvision\nfrom torch.utils.data import DataLoader, Dataset\nfrom sklearn.metrics import accuracy_score, mean_squared_error","metadata":{"execution":{"iopub.status.busy":"2023-05-10T09:53:47.279603Z","iopub.execute_input":"2023-05-10T09:53:47.280173Z","iopub.status.idle":"2023-05-10T09:53:51.642828Z","shell.execute_reply.started":"2023-05-10T09:53:47.280127Z","shell.execute_reply":"2023-05-10T09:53:51.641745Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Innlasting av data\n**Last inn trening/validering og test data og fyll inn NaN verdier med 0**","metadata":{}},{"cell_type":"code","source":"data = pd.read_csv('/kaggle/input/rsna-pneumonia-detection-challenge/stage_2_train_labels.csv')\ndata = data.fillna(0)","metadata":{"execution":{"iopub.status.busy":"2023-05-10T09:53:56.525388Z","iopub.execute_input":"2023-05-10T09:53:56.525930Z","iopub.status.idle":"2023-05-10T09:53:56.591056Z","shell.execute_reply.started":"2023-05-10T09:53:56.525895Z","shell.execute_reply":"2023-05-10T09:53:56.590039Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Vi må så matche pasient ID med deres korresponderende bilde path","metadata":{}},{"cell_type":"code","source":"data['path'] = data['patientId'].apply(lambda x: f'/kaggle/input/rsna-pneumonia-detection-challenge/stage_2_train_images/{x}.dcm')","metadata":{"execution":{"iopub.status.busy":"2023-05-10T09:54:00.950528Z","iopub.execute_input":"2023-05-10T09:54:00.951097Z","iopub.status.idle":"2023-05-10T09:54:00.986347Z","shell.execute_reply.started":"2023-05-10T09:54:00.951049Z","shell.execute_reply":"2023-05-10T09:54:00.985314Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Vi må beregne maksimum og minimumsverdier for de ulike parameterne hos bounding boxene slik at vi senere kan normalisere dem. Normaliseringen av parameterne individuelt vil føre til en lavere MSE som gjør at modellen vår ikke vektlegger én parameter mer enn en annen. Det vil også gjøre at treningen vil gå raskere.","metadata":{}},{"cell_type":"code","source":"x_max, x_min = data['x'].max(), data['x'].min()\ny_max, y_min = data['y'].max(), data['y'].min()\nwidth_max, width_min = data['width'].max(), data['width'].min()\nheight_max, height_min = data['height'].max(), data['height'].min()","metadata":{"execution":{"iopub.status.busy":"2023-05-10T09:54:06.217490Z","iopub.execute_input":"2023-05-10T09:54:06.217950Z","iopub.status.idle":"2023-05-10T09:54:06.230620Z","shell.execute_reply.started":"2023-05-10T09:54:06.217904Z","shell.execute_reply":"2023-05-10T09:54:06.229070Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\nLa oss så printe datasettet våres.","metadata":{}},{"cell_type":"code","source":"data","metadata":{"execution":{"iopub.status.busy":"2023-05-10T09:54:09.959331Z","iopub.execute_input":"2023-05-10T09:54:09.960479Z","iopub.status.idle":"2023-05-10T09:54:09.989612Z","shell.execute_reply.started":"2023-05-10T09:54:09.960418Z","shell.execute_reply":"2023-05-10T09:54:09.988337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Vi deler data inn i test, validering og test data med en ratio på 60/20/20. ","metadata":{}},{"cell_type":"code","source":"train_data, val_data, test_data = np.split(data.sample(frac=1, random_state=42),[int(.6*len(data)), int(.8*len(data))])\ntrain_data, val_data, test_data = train_data.reset_index(), val_data.reset_index(), test_data.reset_index()","metadata":{"execution":{"iopub.status.busy":"2023-05-10T09:56:45.812069Z","iopub.execute_input":"2023-05-10T09:56:45.812466Z","iopub.status.idle":"2023-05-10T09:56:45.831854Z","shell.execute_reply.started":"2023-05-10T09:56:45.812430Z","shell.execute_reply":"2023-05-10T09:56:45.830908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Bildedata\nLa oss se på noen av treningsbildene i datasettet vårt. Vi kan observere at opasiteten er høyere på bildene hvor pneumoni er påvist","metadata":{}},{"cell_type":"code","source":"fig, axes = plt.subplots(3, 3, figsize=(10, 10))\n\nfor i, ax in enumerate(axes.flat):\n\n    dcm = dcmread(train_data['path'][i])\n    target = train_data['Target'][i]\n    x = train_data[\"x\"][i]\n    y = train_data[\"y\"][i]\n    width = train_data[\"width\"][i]\n    height = train_data[\"height\"][i]\n    \n    ax.imshow(dcm.pixel_array, cmap='bone')\n    \n    if target == 1:\n        ax.set_title('Pneumonia')\n        # Add rectangle to image\n        rect = Rectangle((x, y), width, height, linewidth=1, edgecolor='r', facecolor='none')\n        ax.add_patch(rect)\n        rect = Rectangle((0, 0), dcm.Columns, dcm.Rows, linewidth=5, edgecolor='r', facecolor='none')\n        ax.add_patch(rect)\n    else:\n        ax.set_title('Healthy')\n        rect = Rectangle((0, 0), dcm.Columns, dcm.Rows, linewidth=5, edgecolor='g', facecolor='none')\n        ax.add_patch(rect)\n    ax.axis(\"off\")\n","metadata":{"execution":{"iopub.status.busy":"2023-05-10T09:58:27.100865Z","iopub.execute_input":"2023-05-10T09:58:27.101508Z","iopub.status.idle":"2023-05-10T09:58:28.639813Z","shell.execute_reply.started":"2023-05-10T09:58:27.101466Z","shell.execute_reply":"2023-05-10T09:58:28.637817Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Preprossesering av bilder\n\nVi lager vår egen preprosseserings klasse hvor vi vil justere bildene, samt en transformasjon for bounding box som vil ta seg av normaliseringen og denormaliseringen av bildene. Det er viktig å normalisere bounding box for å redusere MSE slik at modellen vår ikke vil vektlegge noen områder mer enn andre. I tillegg vil dette øke hvor rask modellen er.","metadata":{}},{"cell_type":"code","source":"class ImageTransform(object):\n    \n    def __call__(self, image):\n        image = image.pixel_array / 255\n        image = cv2.resize(image, (224, 224))\n        image =  np.expand_dims(image, -1)\n        image = image.transpose((2, 0, 1))\n        return image\n\nclass BboxTransform(object):\n    \n    def __init__(self, x_max, x_min, y_max, y_min, width_max, width_min, height_max, height_min):\n        self.x_max = x_max\n        self.x_min = x_min\n        self.y_max = y_max\n        self.y_min = y_min\n        self.width_max = width_max\n        self.width_min = width_min\n        self.height_max = height_max\n        self.height_min = height_min\n    \n    def __call__(self, bbox):\n        bbox[0] = self._normalize(bbox[0], self.x_max, self.x_min)\n        bbox[1] = self._normalize(bbox[1], self.y_max, self.y_min)\n        bbox[2] = self._normalize(bbox[2], self.width_max, self.width_min)\n        bbox[3] = self._normalize(bbox[3], self.height_max, self.height_min)\n        return bbox\n    \n    def invert(self, bbox):\n        bbox[0] = self._invert(bbox[0], self.x_max, self.x_min)\n        bbox[1] = self._invert(bbox[1], self.y_max, self.y_min)\n        bbox[2] = self._invert(bbox[2], self.width_max, self.width_min)\n        bbox[3] = self._invert(bbox[3], self.height_max, self.height_min)\n        return bbox\n        \n    \n    def _normalize(self, val, maximum, minimum):\n        return (val - minimum)/(maximum - minimum)\n    \n    def _invert(self, val, maximum, minimum):\n        return val * (maximum-minimum) + minimum\n","metadata":{"execution":{"iopub.status.busy":"2023-05-09T13:29:58.480085Z","iopub.execute_input":"2023-05-09T13:29:58.480804Z","iopub.status.idle":"2023-05-09T13:29:58.505009Z","shell.execute_reply.started":"2023-05-09T13:29:58.480766Z","shell.execute_reply":"2023-05-09T13:29:58.503705Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Vi lager også en egen Dataset klasse som arver fra PyTorchs Dataset klasse for å dele dataen vår inn i ønskede grupper med bildet target og bounding box for seg selv.","metadata":{}},{"cell_type":"code","source":"\nclass MyDataset(Dataset):\n\n    def __init__(self, data, image_transform, bbox_transform):\n        self.data = data\n        self.image_transform = image_transform\n        self.bbox_transform = bbox_transform\n\n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, idx):\n        if torch.is_tensor(idx):\n            idx = idx.tolist()\n        image = dcmread(self.data.iloc[idx, 6])\n        targets = self.data.iloc[idx, 1:6]\n        targets = torch.Tensor(targets)\n        image = self.image_transform(image)\n        image = torch.Tensor(image)\n        target = targets[4].type(torch.LongTensor)\n        bbox = self.bbox_transform(targets[:4])\n        image = torch.Tensor(image)\n        return {'image' : image, 'target' : target, 'bbox' : bbox}\n\n","metadata":{"execution":{"iopub.status.busy":"2023-05-09T13:29:58.507455Z","iopub.execute_input":"2023-05-09T13:29:58.509565Z","iopub.status.idle":"2023-05-09T13:29:58.521392Z","shell.execute_reply.started":"2023-05-09T13:29:58.509527Z","shell.execute_reply":"2023-05-09T13:29:58.520266Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"I denne oppgaven har vi valgt å bruke et Residual Network (ResNet). Nettverket består av ett convolutional lag med batchnoramlisering og ReLU aktiveringsfunksjon, etterfølgt av et 3x3 pooling lag. Deretter kommer 4 lag som hver er en ResidualBlock. Hver blokk består igjen av to convolutional lag. Til slutt er det ett fully connected lag, og i tillegg vil target gå gjennom en SoftMax aktiversingsfunksjon.","metadata":{}},{"cell_type":"code","source":"class ResidualBlock(nn.Module):\n    def __init__(self, in_channels, out_channels, stride = 1, downsample = None):\n        super(ResidualBlock, self).__init__()\n        self.conv1 = nn.Sequential(\n                        nn.Conv2d(in_channels, out_channels, kernel_size = 3, stride = stride, padding = 1),\n                        nn.BatchNorm2d(out_channels),\n                        nn.ReLU())\n        self.conv2 = nn.Sequential(\n                        nn.Conv2d(out_channels, out_channels, kernel_size = 3, stride = 1, padding = 1),\n                        nn.BatchNorm2d(out_channels))\n        self.downsample = downsample\n        self.relu = nn.ReLU()\n        self.out_channels = out_channels\n        \n    def forward(self, x):\n        residual = x\n        out = self.conv1(x)\n        out = self.conv2(out)\n        if self.downsample:\n            residual = self.downsample(x)\n        out += residual\n        out = self.relu(out)\n        return out","metadata":{"execution":{"iopub.status.busy":"2023-05-09T13:29:58.538324Z","iopub.execute_input":"2023-05-09T13:29:58.539292Z","iopub.status.idle":"2023-05-09T13:29:58.550060Z","shell.execute_reply.started":"2023-05-09T13:29:58.539256Z","shell.execute_reply":"2023-05-09T13:29:58.548991Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ResNet(nn.Module):\n    def __init__(self, out_features, block = ResidualBlock, layers = [3, 4, 6, 3],softmax = None):\n        super(ResNet, self).__init__()\n        self.inplanes = 64\n        self.conv1 = nn.Sequential(\n                        nn.LazyConv2d(out_channels = 64, kernel_size = 7, stride = 2, padding = 3),\n                        nn.BatchNorm2d(64),\n                        nn.ReLU())\n        self.maxpool = nn.MaxPool2d(kernel_size = 3, stride = 2, padding = 1)\n        self.layer0 = self._make_layer(block, 64, layers[0], stride = 1)\n        self.layer1 = self._make_layer(block, 128, layers[1], stride = 2)\n        self.layer2 = self._make_layer(block, 256, layers[2], stride = 2)\n        self.layer3 = self._make_layer(block, 512, layers[3], stride = 2)\n        self.avgpool = nn.AvgPool2d(7, stride=1)\n        self.fc = nn.LazyLinear(out_features = out_features)\n        self.softmax = softmax\n        \n    def _make_layer(self, block, planes, blocks, stride=1):\n        downsample = None\n        if stride != 1 or self.inplanes != planes:\n            \n            downsample = nn.Sequential(\n                nn.Conv2d(self.inplanes, planes, kernel_size=1, stride=stride),\n                nn.BatchNorm2d(planes),\n            )\n        layers = []\n        layers.append(block(self.inplanes, planes, stride, downsample))\n        self.inplanes = planes\n        for i in range(1, blocks):\n            layers.append(block(self.inplanes, planes))\n\n        return nn.Sequential(*layers)\n    \n    \n    def forward(self, x):\n        x = self.conv1(x)\n        x = self.maxpool(x)\n        x = self.layer0(x)\n        x = self.layer1(x)\n        x = self.layer2(x)\n        x = self.layer3(x)\n        x = self.avgpool(x)\n        x = x.view(x.size(0), -1)\n        x = self.fc(x)\n        if self.softmax:\n            x = self.softmax(x)\n        return x","metadata":{"execution":{"iopub.status.busy":"2023-05-09T13:29:58.551435Z","iopub.execute_input":"2023-05-09T13:29:58.552408Z","iopub.status.idle":"2023-05-09T13:29:58.570681Z","shell.execute_reply.started":"2023-05-09T13:29:58.552373Z","shell.execute_reply":"2023-05-09T13:29:58.569626Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Vi lager en egen Model klasse hvor trening, validering og predikering vil foregå. Hovedsaklig for å ha mulighet til å justere hyperparametre enkelt og kunne lagre og laste inn modellen vår for å slippe å trene unødvendig antall ganger.","metadata":{}},{"cell_type":"code","source":"class Model:\n\n    def __init__(self, train_data, val_data = None, train = False, class_filename = 'trained_class_model.pt',\n                 regression_filename = 'trained_regression_model.pt',epochs = 10, batch_size = 64, learning_rate = 0.01, momentum = 0.9, save = True):\n                \n        self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n        self.class_filename = class_filename\n        self.regression_filename = regression_filename\n        self.save = save\n    \n        self.batch_size = batch_size\n        self.learning_rate = learning_rate\n        self.momentum = momentum\n        self.epochs = epochs\n        \n        self.image_transform = ImageTransform()\n        self.bbox_transform = BboxTransform(x_max, x_min, y_max, y_min, width_max, width_min, height_max, height_min)\n        \n        self.train_data = train_data\n        self.train_dataset = MyDataset(train_data, image_transform = self.image_transform, bbox_transform = self.bbox_transform)\n        self.train_loader = DataLoader(self.train_dataset, shuffle=True, batch_size=self.batch_size, num_workers = 2)\n        \n        \n        self.val_data = val_data\n        if self.val_data is not None:\n            self.val_dataset = MyDataset(val_data, image_transform = self.image_transform, bbox_transform = self.bbox_transform)\n            self.val_loader = DataLoader(self.val_dataset, shuffle=True, batch_size=self.batch_size, num_workers = 2)\n            \n        \n                                    \n        self.class_model = ResNet(out_features = 2, softmax = nn.Softmax(dim = 1))\n        self.regression_model = ResNet(out_features = 4, softmax = None)\n        self.class_model = self.class_model.to(self.device)\n        self.regression_model = self.regression_model.to(self.device)\n        \n        if train:\n            self._fit()\n        else:\n            self.class_model.load_state_dict(torch.load(self.class_filename))\n            self.regression_model.load_state_dict(torch.load(self.regression_filename))\n            self.class_model = self.class_model.to(self.device)\n            self.regression_model = self.regression_model.to(self.device)\n            \n        self.class_loss_function = None\n        self.regression_loss_function = None\n        self.class_optimizer = None\n        self.regression_optimizer = None\n        \n    \n    def _fit(self):\n\n        self.class_loss_function = nn.CrossEntropyLoss() \n        self.regression_loss_function = nn.MSELoss()\n        \n        self.class_optimizer = torch.optim.SGD(self.class_model.parameters(), lr=self.learning_rate, momentum = self.momentum)\n        self.regression_optimizer = torch.optim.SGD(self.regression_model.parameters(), lr=self.learning_rate, momentum = self.momentum)\n\n        print(f' Starting training with Epochs = {self.epochs},  Batch size = {self.batch_size},  Learning rate = {self.learning_rate} ')\n\n        for epoch in range(self.epochs):\n            running_loss, train_mse, train_accuracy = self._train_one_epoch()\n            print(f'EPOCH: {epoch + 1}   Training loss: {running_loss}  Training MSE: {train_mse}, Training accuracy: {train_accuracy}')\n            if self.val_data is not None:\n                val_mse, val_accuracy = self._val_one_epoch()\n                print(f'EPOCH: {epoch + 1}   Validation MSE: {val_mse}  Validation accuracy: {val_accuracy}  ')\n            \n\n        if self.save:\n            torch.save(self.class_model.state_dict(), self.class_filename)\n            torch.save(self.regression_model.state_dict(), self.regression_filename)\n            \n        \n    \n    def _val_one_epoch(self):\n\n        self.class_model.eval()\n        self.regression_model.eval()\n        running_mse = 0\n        correct = 0\n\n        for i_batch, data_batch in enumerate(self.val_loader):\n            image = data_batch['image'].to(self.device)\n            target = data_batch['target'].to(self.device)\n            bbox = data_batch['bbox'].to(self.device)\n            \n            with torch.no_grad():\n                class_output = self.class_model(image)\n                regression_output = self.regression_model(image)\n                running_mse += ((torch.pow((regression_output - bbox), 2)).sum())\n                pred = torch.argmax(class_output, dim = 1)\n                correct += (pred == target).sum()\n        \n        val_mse = running_mse / len(self.val_dataset)\n        val_accuracy = correct / len(self.val_dataset)\n        return val_mse, val_accuracy\n\n    \n\n    def _train_one_epoch(self):\n\n        running_loss = 0\n        running_mse = 0\n        correct = 0\n\n        self.class_model.train()\n        self.regression_model.train()\n        \n        for i_batch, data_batch in enumerate(self.train_loader):\n\n            image = data_batch['image'].to(self.device)\n            target = data_batch['target'].to(self.device)\n            bbox = data_batch['bbox'].to(self.device)\n            \n            # Zero your gradients for every batch\n            self.class_optimizer.zero_grad()\n            self.regression_optimizer.zero_grad()\n            \n            # Make predictions for this batch\n            class_output = self.class_model(image)\n            regression_output = self.regression_model(image)\n\n            # Compute the loss and its gradients\n            class_loss = self.class_loss_function(class_output, target)\n            regression_loss = self.regression_loss_function(regression_output, bbox)\n            \n            loss = class_loss + regression_loss\n            \n            loss.backward()\n            \n            # Adjust learning weights\n            self.class_optimizer.step()\n            self.regression_optimizer.step()\n            \n            # Gather data and report\n            running_loss += loss.item()\n            running_mse += ((torch.pow((regression_output - bbox), 2)).sum())\n            pred = torch.argmax(class_output, dim = 1)\n            correct += (pred == target).sum()\n            \n        train_mse = running_mse / len(self.train_dataset)\n        train_accuracy = correct / len(self.train_dataset)\n        return running_loss, train_mse, train_accuracy\n    \n\n    def predict_from_data(self, test_data):\n        self.class_model.eval()\n        self.regression_model.eval()\n        test_dataset = MyDataset(test_data, self.image_transform, self.bbox_transform)\n        test_loader = DataLoader(test_dataset, batch_size = 1)\n        preds = {'Target': [], 'Confidence': [], 'x':[],'y':[],'width':[],'height':[]}\n        \n        for i, data in enumerate(test_loader):\n            with torch.no_grad():\n                test_image = data['image']\n                test_image = test_image.to(self.device)\n                class_out = self.class_model(test_image)\n                confidence = class_out.cpu().numpy()[:, 1][0]\n                \n                preds['Confidence'].append(confidence)\n                \n                if (confidence < 0.5):\n                    preds['x'].append(0)\n                    preds['y'].append(0)\n                    preds['width'].append(0)\n                    preds['height'].append(0)\n                \n                else:\n                    regression_out = self.regression_model(test_image)\n                    regression_out = regression_out.cpu().numpy()[0]\n                    regression_out = self.bbox_transform.invert(regression_out)\n                    preds['x'].append(regression_out[0])\n                    preds['y'].append(regression_out[1])\n                    preds['width'].append(regression_out[2])\n                    preds['height'].append(regression_out[3])\n\n            \n                class_pred = torch.argmax(class_out, dim = 1).cpu().numpy()[0]\n                preds['Target'].append(class_pred)\n        \n        preds_data = pd.DataFrame.from_dict(preds)\n        return preds_data\n    \n    def submit_from_filenames(self, folder, test_filenames):\n        \n        self.class_model.eval()\n        self.regression_model.eval()\n        \n        preds = {}\n        \n        for filename in test_filenames:\n            \n            path = f'{folder}/{filename}'\n      \n            patient_id = filename.split('.')[0]\n            \n            prediction_string = ''\n            \n            with torch.no_grad():\n                test_image = dcmread(path)\n                test_image = self.image_transform(test_image)\n                test_image = torch.Tensor(test_image)\n                test_image = test_image.to(self.device)\n                \n                class_out = self.class_model(test_image.unsqueeze(0))\n                confidence = class_out.cpu().numpy()[:, 1][0]\n                \n                if (confidence >= 0.5):\n                    regression_out = self.regression_model(test_image.unsqueeze(0))\n                    regression_out = regression_out.cpu().numpy()[0]\n                    regression_out = self.bbox_transform.invert(regression_out)\n                    x = regression_out[0]\n                    y = regression_out[1]\n                    width = regression_out[2]\n                    height = regression_out[3]\n                    prediction_string += str(confidence) + ' ' + str(x) + ' ' + str(y) + ' ' + str(width) + ' ' + str(height) + ' '\n                preds[patient_id] = prediction_string\n    \n                \n        preds_data = pd.DataFrame.from_dict(preds, orient='index')\n        preds_data.index.names = ['patientId']\n        preds_data.columns = ['PredictionString']\n        preds_data.to_csv('submission.csv')\n\n        ","metadata":{"execution":{"iopub.status.busy":"2023-05-09T13:29:58.572135Z","iopub.execute_input":"2023-05-09T13:29:58.572903Z","iopub.status.idle":"2023-05-09T13:29:58.629023Z","shell.execute_reply.started":"2023-05-09T13:29:58.572868Z","shell.execute_reply":"2023-05-09T13:29:58.627261Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Trening + Validering","metadata":{}},{"cell_type":"markdown","source":"Beste valdiation accuracy på 83% ble oppnådd ved å bruke learning rate på 0.0001, 11 epochs og en batchsize på 64","metadata":{}},{"cell_type":"code","source":"val_model = Model(train_data = train_data, val_data = val_data, train=True, batch_size = 64, learning_rate = 0.0001, epochs = 11)","metadata":{"execution":{"iopub.status.busy":"2023-05-09T13:29:58.632958Z","iopub.execute_input":"2023-05-09T13:29:58.633881Z","iopub.status.idle":"2023-05-09T13:29:58.638451Z","shell.execute_reply.started":"2023-05-09T13:29:58.633842Z","shell.execute_reply":"2023-05-09T13:29:58.637343Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Testing","metadata":{}},{"cell_type":"markdown","source":"Vi må kombinere test og valideringsdata og retrene modellen vår før vi kan teste på test data","metadata":{}},{"cell_type":"code","source":"all_train_data = pd.concat([train_data, val_data])\nall_train_data = all_train_data.reset_index()\ntest_model = Model(train_data = all_train_data, batch_size = 64, learning_rate = 0.0001, epochs = 11)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_pred = test_model.predict_from_data(test_data)","metadata":{"execution":{"iopub.status.busy":"2023-05-09T13:33:12.740321Z","iopub.execute_input":"2023-05-09T13:33:12.740705Z","iopub.status.idle":"2023-05-09T13:33:12.757615Z","shell.execute_reply.started":"2023-05-09T13:33:12.740668Z","shell.execute_reply":"2023-05-09T13:33:12.756414Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Vi printer validerings accuracy og MSE","metadata":{}},{"cell_type":"code","source":"test_accuracy = accuracy_score(test_data['Target'].values, test_pred['Target'].values)\ntest_mse = mean_squared_error(test_data[['x', 'y', 'width', 'height']].values, test_pred[['x', 'y', 'width', 'height']].values)\nprint(f'Validation accuracy: {accuracy}   Validation MSE: {mse}')","metadata":{"execution":{"iopub.status.busy":"2023-05-09T13:33:12.783730Z","iopub.execute_input":"2023-05-09T13:33:12.784718Z","iopub.status.idle":"2023-05-09T13:33:12.796251Z","shell.execute_reply.started":"2023-05-09T13:33:12.784604Z","shell.execute_reply":"2023-05-09T13:33:12.795081Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Før modellen er ferdigstilt må trening- og valideringsdata rekombineres og modellen skal trenes på all tilgjengelig data.","metadata":{}},{"cell_type":"code","source":"final_model = Model(train_data = train_data, epochs = 11, batch_size = 64, learning_rate = 0.0001, train=True)","metadata":{"execution":{"iopub.status.busy":"2023-05-09T13:50:37.815573Z","iopub.execute_input":"2023-05-09T13:50:37.816384Z","iopub.status.idle":"2023-05-09T14:31:15.746297Z","shell.execute_reply.started":"2023-05-09T13:50:37.816347Z","shell.execute_reply":"2023-05-09T14:31:15.745102Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"prediction_df = final_model.predict_from_data(val_data)\naccuracy = accuracy_score(val_data['Target'].values, prediction_df['Target'].values)\nmse = mean_squared_error(val_data[['x', 'y', 'width', 'height']].values, prediction_df[['x', 'y', 'width', 'height']].values)\nprint(f'Validation accuracy: {accuracy}   Validation MSE: {mse}')","metadata":{"execution":{"iopub.status.busy":"2023-05-09T14:36:37.963341Z","iopub.execute_input":"2023-05-09T14:36:37.964044Z","iopub.status.idle":"2023-05-09T14:39:51.494574Z","shell.execute_reply.started":"2023-05-09T14:36:37.964004Z","shell.execute_reply":"2023-05-09T14:39:51.493368Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"folder = '/kaggle/input/rsna-pneumonia-detection-challenge/stage_2_test_images'\ntest_filenames = os.listdir(folder)\nfinal_model.submit_from_filenames(folder, test_filenames)","metadata":{"execution":{"iopub.status.busy":"2023-05-09T14:32:03.010138Z","iopub.execute_input":"2023-05-09T14:32:03.010676Z","iopub.status.idle":"2023-05-09T14:33:23.669443Z","shell.execute_reply.started":"2023-05-09T14:32:03.010632Z","shell.execute_reply":"2023-05-09T14:33:23.668432Z"},"trusted":true},"execution_count":null,"outputs":[]}]}