{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"!  pip install --upgrade efficientnet-pytorch","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install torch-lr-finder","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import sys, os\nimport pandas as pd\nimport numpy as np\nimport os\nimport cv2\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport torch\nimport torchvision\nfrom torch.utils.data import Dataset, DataLoader\nimport torchvision.transforms as transforms\nfrom PIL import Image\nimport torch.nn.functional as F\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.optim.lr_scheduler import ReduceLROnPlateau\nfrom albumentations import *\nfrom tqdm.notebook import tnrange, tqdm\nfrom torchvision import models\nfrom efficientnet_pytorch import EfficientNet\nimport random\nfrom sklearn.preprocessing import MinMaxScaler\nimport albumentations as A","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\ndevice","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_images_path = '../input/jpeg-melanoma-256x256/train/'\ntest_images_path = '../input/siim-isic-melanoma-classification/jpeg/test/'\ntrain_csv_path = '../input/jpeg-melanoma-256x256/train.csv'\ntest_csv_path = '../input/siim-isic-melanoma-classification/test.csv'  ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df_0 = pd.read_csv(train_csv_path)\ntrain_df_0.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def balance_df(df, class_name = ''):   \n    max_size = df[class_name].value_counts().max()\n    lst = [df]\n    for class_index, group in df.groupby(class_name):\n        lst.append(group.sample(max_size-len(group), replace=True))\n    frame_new = pd.concat(lst)\n    df_balanced=frame_new\n    return(df_balanced)\n\ntrain_df = balance_df(train_df_0, 'target')\ntrain_df['target'].value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def fill_missing_vals_w_mean(df, list_of_att):\n    for att in list_of_att:\n        df[att]=df[att].fillna(df[att].mean())\n        \n    return(df)\n        ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def drop_columns(df, list_of_columns):\n    for column_ in list_of_columns:\n        df.drop([column_], axis=1, inplace=True)\n    return(df)\n\ncols_drop = ['diagnosis', \n             'patient_id']\n\ntrain_df = drop_columns(train_df, cols_drop)\ntrain_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def scale_columns(df, list_of_cols):\n    \n    for x in list_of_cols:\n        float_array = df[x].values.astype(float)\n        min_max_scaler = MinMaxScaler()\n        scaled_array = min_max_scaler.fit_transform(float_array.reshape(-1, 1))\n        df[x] = scaled_array\n    return(df)\n    \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#conv categorical in train_df\ndef convert_categorical(category, df):\n    s = str(category)\n    df = pd.get_dummies(df, columns=[s])\n    return df\n\n\ndef encode_df(df):\n    \n    df_encoded = convert_categorical('sex', df)\n    df_encoded = convert_categorical('anatom_site_general_challenge', df_encoded)\n    df_encoded1 = convert_categorical('benign_malignant', df_encoded)\n    return(df_encoded1)\n\n\ndf_encoded = encode_df(train_df)\ndf_encoded = drop_columns(df_encoded, ['sex_female', \n                                       'benign_malignant_benign'])\ndf_encoded = fill_missing_vals_w_mean(df_encoded, ['age_approx'])\n\ndf_scaled = scale_columns(df_encoded, ['age_approx', \n                                       'target', \n                                       'tfrecord', \n                                       'width', \n                                       'height',\n                                       'sex_male', \n                                       'anatom_site_general_challenge_head/neck',\n                                       'anatom_site_general_challenge_lower extremity',\n                                       'anatom_site_general_challenge_oral/genital',\n                                       'anatom_site_general_challenge_palms/soles',\n                                       'anatom_site_general_challenge_torso',\n                                       'anatom_site_general_challenge_upper extremity',\n                                       'benign_malignant_malignant'])\n\ndf_scaled.to_csv('./train_cleaned.csv')\ndf_scaled['target'].value_counts()\ndf_scaled.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"other_df = drop_columns(df_encoded, ['target', 'image_name'])\nother_df.to_csv('./other_df.csv')\nother_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def image_to_nparray(path):\n    i = plt.imread(path)    \n    return(np.array(i))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class AdvancedHairAugmentation:\n    def __init__(self, hairs: int = 4, hairs_folder: str = \"\"):\n        self.hairs = hairs\n        self.hairs_folder = hairs_folder\n\n    def __call__(self, img):\n        n_hairs = random.randint(0, self.hairs)\n\n        if not n_hairs:\n            return img\n\n        height, width, _ = img.shape  # target image width and height\n        hair_images = [im for im in os.listdir(self.hairs_folder) if 'png' in im]\n\n        for _ in range(n_hairs):\n            hair = cv2.imread(os.path.join(self.hairs_folder, random.choice(hair_images)))\n            hair = cv2.flip(hair, random.choice([-1, 0, 1]))\n            hair = cv2.rotate(hair, random.choice([0, 1, 2]))\n\n            h_height, h_width, _ = hair.shape  # hair image width and height\n            roi_ho = random.randint(0, img.shape[0] - hair.shape[0])\n            roi_wo = random.randint(0, img.shape[1] - hair.shape[1])\n            roi = img[roi_ho:roi_ho + h_height, roi_wo:roi_wo + h_width]\n\n            img2gray = cv2.cvtColor(hair, cv2.COLOR_BGR2GRAY)\n            ret, mask = cv2.threshold(img2gray, 10, 255, cv2.THRESH_BINARY)\n            mask_inv = cv2.bitwise_not(mask)\n            img_bg = cv2.bitwise_and(roi, roi, mask=mask_inv)\n            hair_fg = cv2.bitwise_and(hair, hair, mask=mask)\n\n            dst = cv2.add(img_bg, hair_fg)\n            img[roi_ho:roi_ho + h_height, roi_wo:roi_wo + h_width] = dst\n\n        return img\n    \n    \nclass Microscope:\n    def __init__(self, p: float = 0.5):\n        self.p = p\n\n    def __call__(self, img):\n        if random.random() < self.p:\n            circle = cv2.circle((np.ones(img.shape) * 255).astype(np.uint8),\n                        (img.shape[0]//2, img.shape[1]//2),\n                        random.randint(img.shape[0]//2 - 3, img.shape[0]//2 + 15),\n                        (0, 0, 0),\n                        -1)\n\n            mask = circle - 255\n            img = np.multiply(img, mask)\n\n        return img\n\n    def __repr__(self):\n        return f'{self.__class__.__name__}(p={self.p})'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class MyDataset(Dataset):\n    \n    '''\n    csv_file_path : path to csv\n    images_path : path to images\n    transform (callable, optional): Optional transform to be applied on a sample.\n    '''\n    \n    def __init__(self, csv_file_path ,other_csv_path, images_path, augmentation=None, transform=None):\n\n        self.transform = transform\n        self.augmentation = augmentation\n        \n        self.images_path = images_path\n        self.d = pd.read_csv(csv_file_path)[0:]\n        print(self.d.head())\n        self.other_df = pd.read_csv(other_csv_path)[0:]\n        self.smol_img_paths =self.d[self.d.columns[1]]\n        \n        \n   \n        \n    def __getitem__(self, index): \n        \n        full_img_path = self.images_path+str(self.d.iloc[index]['image_name']) + '.jpg'\n        #print(full_img_path)\n        img_arr = image_to_nparray(full_img_path)\n        \n        class_name2 = self.d.iloc[index]['target']\n        other_part2=np.array(self.other_df.iloc[index][0:].values, dtype=np.float32)\n\n        if self.augmentation is not None:\n            img  = self.augmentation(image = img_arr)\n            img2 = img[\"image\"]\n\n        if self.transform is not None:\n            img_ret = self.transform(img2)\n        \n        return(torch.tensor(int(class_name2)), ((img_ret), torch.tensor([other_part2])) )\n                                                                                   \n    def __len__(self):\n        return (len(self.d))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data = MyDataset('./train_cleaned.csv', \n                 './other_df.csv',\n                 train_images_path,\n                 augmentation = Compose([ \n                                        ]),\n                transform = transforms.Compose([AdvancedHairAugmentation(hairs_folder='/kaggle/input/melanoma-hairs'),\n                                                Microscope(p=0.7),\n                                                transforms.ToPILImage(),\n                                                transforms.Resize((224,224),interpolation = Image.NEAREST),\n                                                transforms.RandomResizedCrop(size=224, scale=(0.8, 1.0)),\n                                                transforms.RandomHorizontalFlip(),\n                                                transforms.RandomVerticalFlip(),\n                                                transforms.ToTensor(),\n                                                transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])\n                    \n                                                ]))\n                \n\ntrain_data, val_data = torch.utils.data.random_split(data, [len(data)-500, 500])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_loader = torch.utils.data.DataLoader(\n    data\n    ,batch_size=10\n    ,shuffle=False\n    \n)\n\nval_loader = torch.utils.data.DataLoader(\n    val_data\n    ,batch_size=1000\n    ,shuffle=False\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for label, x in (train_loader):\n    #print(label)\n    images,features = x\n    i=np.transpose(images[0], (1, 2, 0)) \n    #print(i)\n    plt.imshow(i, interpolation='sinc')\n    plt.show()\n    print(label[0])\n    break\n    \n    #x = ((I,I,I,I), (F,F,F,F))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, axs = plt.subplots(2, 2, figsize=(10,10))\nfig = plt.figure(figsize=(10,3))\ntrans = transforms.ToPILImage()\nclass_list = [\"no\", \"yes\"]\n\nfor i in range(2):\n    for j in range(2):\n        for labels,x in (train_loader):\n\n            images,features = x\n            img=np.transpose(images[0], (1, 2, 0)) \n            #print(i)\n            class_number = labels[0].item()\n            #print(class_number)\n            im_label=class_list[class_number]\n            axs[j,i].imshow(img, interpolation='sinc')\n            #axs[j,i].title.set_text(str(class_number))\n            \n            break\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_num_correct(preds, labels):\n    return preds.argmax(dim=1).eq(labels).sum().item()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"arch = EfficientNet.from_pretrained('efficientnet-b1')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class Net(nn.Module):\n    def __init__(self, arch, n_meta_features: int):\n        super(Net, self).__init__()\n        self.arch = arch\n        if 'EfficientNet' in str(arch.__class__):\n            self.arch._fc = nn.Linear(in_features=1280, out_features=500, bias=True)\n            \n        self.lower_nn = nn.Sequential(nn.Linear(n_meta_features,50))\n                             \n        \n        self.combined_layer = nn.Linear(500+50, 1)\n\n    def forward(self, inputs):\n        \"\"\"\n        No sigmoid in forward because we are going to use BCEWithLogitsLoss\n        Which applies sigmoid for us when calculating a loss\n        \"\"\"\n        x, meta = inputs\n        #print(meta)\n        x = x.to(device)\n        meta=meta.to(device)\n        cnn_features = self.arch(x)\n        meta_features = self.lower_nn(meta)\n        features = torch.cat((cnn_features.squeeze().detach(), meta_features.squeeze().detach()), dim=1)\n        output = (self.combined_layer(features))\n        return output\n\n\narch = EfficientNet.from_pretrained('efficientnet-b1')\n\nnetwork = Net(arch=arch, n_meta_features=13)\nnetwork = network.to(device)\nprint(network)\n\noptimizer = optim.Adam(network.parameters(), lr = 0.01) \ncriterion = nn.BCEWithLogitsLoss()\nscheduler = ReduceLROnPlateau(optimizer=optimizer, \n                           mode='max',\n                           patience=2, \n                           verbose=True, \n                           factor=0.2)\n\n\nloss_list=[]\nacc_list=[]\nval_loss_list=[]\nval_acc_list=[]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_loader_2 = torch.utils.data.DataLoader(\n    train_data\n    ,batch_size=64\n    ,shuffle=True\n    ,num_workers=4\n\n)\n\nval_loader_2 = torch.utils.data.DataLoader(\n    val_data\n    ,batch_size=64\n    ,shuffle=False\n    ,num_workers=4\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for epoch in tnrange(1): \n    \n    total_loss = 0\n    total_correct = 0\n    total_loss2 = 0\n    total_correct2 = 0\n    \n\n    for labels, x_train in tqdm(train_loader_2): # Get Batch\n\n        images, feature_tensors = x\n        images = images.to(device)\n        feature_tensors = feature_tensors.to(device)\n        labels=labels.to(device)\n        \n        optimizer.zero_grad()\n        preds = network(x_train)\n        preds= preds.to(device)\n        preds2 = torch.round(torch.sigmoid(preds))\n        \n        labels = labels.type_as(preds2)\n        loss = criterion(preds2.flatten(), labels)\n        loss_list.append(loss)\n        num_correct=get_num_correct(preds, labels)\n        \n        loss.backward()\n        optimizer.step() \n        total_correct+=num_correct\n    \n    acc_list.append(total_correct)\n        \n    print(\"training_corr :\",total_correct)\n    \n    with torch.no_grad():\n        network.eval()\n        for labels, x_val in tqdm(val_loader_2): # Get Batch\n\n            images, feature_tensors = x_val\n            images = images.to(device)\n            feature_tensors = feature_tensors.to(device)\n            labels=labels.to(device)\n            preds = network(x_val)\n            preds= preds.to(device)\n            preds1 = torch.round(torch.sigmoid(preds))\n\n            labels = labels.type_as(preds)\n            loss2 = criterion(preds1.flatten(), labels)\n            val_loss_list.append(loss2)\n            val_num_correct=get_num_correct(preds, labels)\n            total_correct2+=val_num_correct\n\n        val_acc_list.append(total_correct2)\n\n        print(\"val_corr :\", total_correct2)\n        \n        \n        #why isnt the accuracy going up?\n        ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"with torch.no_grad():\n        network.eval()\n        total_correct2=0\n        for labels, x_val in tqdm(val_loader_2): # Get Batch\n\n            images, feature_tensors = x_val\n            images = images.to(device)\n            feature_tensors = feature_tensors.to(device)\n            labels=labels.to(device)\n            preds = network(x_val)\n            preds= preds.to(device)\n            preds1 = torch.round(torch.sigmoid(preds))\n\n            labels = labels.type_as(preds)\n            loss2 = criterion(preds1.flatten(), labels)\n            val_loss_list.append(loss2)\n            val_num_correct=get_num_correct(preds, labels)\n            total_correct2+=val_num_correct\n        print(total_correct2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.plot(loss_list)\n\n# y 13 metafeatures?","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# try scaling all values","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}