{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n\nimport os\nprint(os.listdir(\"../input\"))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"%matplotlib inline \nimport matplotlib.pyplot as plt\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os\nimport time\nimport copy","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"64900dd20effe7deba0c0d0ffd04fd5438079ed3"},"cell_type":"code","source":"from PIL import Image\n\nDATASET_SIZE = 8000\nBATCH_SIZE = 200\nW = H = 256\n\ntrain_path = '../input/train/'\ntest_path = '../input/test/'\n\nLABEL_MAP = {\n0: \"Nucleoplasm\" ,\n1: \"Nuclear membrane\"   ,\n2: \"Nucleoli\"   ,\n3: \"Nucleoli fibrillar center\",   \n4: \"Nuclear speckles\"   ,\n5: \"Nuclear bodies\"   ,\n6: \"Endoplasmic reticulum\"   ,\n7: \"Golgi apparatus\"  ,\n8: \"Peroxisomes\"   ,\n9:  \"Endosomes\"   ,\n10: \"Lysosomes\"   ,\n11: \"Intermediate filaments\"  , \n12: \"Actin filaments\"   ,\n13: \"Focal adhesion sites\"  ,\n14: \"Microtubules\"   ,\n15: \"Microtubule ends\"   ,\n16: \"Cytokinetic bridge\"   ,\n17: \"Mitotic spindle\"  ,\n18: \"Microtubule organizing center\",  \n19: \"Centrosome\",\n20: \"Lipid droplets\"   ,\n21: \"Plasma membrane\"  ,\n22: \"Cell junctions\"   ,\n23: \"Mitochondria\"   ,\n24: \"Aggresome\"   ,\n25: \"Cytosol\" ,\n26: \"Cytoplasmic bodies\",\n27: \"Rods & rings\"}\n\nLABELS = []\n\nfor label in LABEL_MAP.values():\n    LABELS.append(label)\n    \ntrain_csv_path = '../input/train.csv'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"fc9c64b49229f2edf4cc64bf6e9ffd345ab63afd"},"cell_type":"code","source":"df = pd.read_csv(train_csv_path)\n\nTRAINING_SAMPLES = df.shape[0]\n\nprint(\"we have \" + str(TRAINING_SAMPLES) + \" different samples\")\nprint(\"And there are \"+  str(len(df.Target.unique())) + \" different combinations of labels in our dataset\")\n\nimport seaborn as sns\nsns.set(style=\"dark\")\n\nn = 20\n\nvalues = df['Target'].value_counts()[:n].keys().tolist()\ncounts = df['Target'].value_counts()[:n].tolist()\n\nplt.figure(figsize=(6,6))\npal = sns.cubehelix_palette(n, start=2, rot=0, dark=0, light=.75, reverse=True)\ng = sns.barplot(y=counts, x=values, palette=pal)\ng.set_title(str(n)+\" MOST COMMON LABEL COMBINATIONS\")\ng.set_xticklabels(g.get_xticklabels(),rotation=90);","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"9fc99fba88c0285e69e52db0721c0fa0b92a9fbd"},"cell_type":"code","source":"\nTRAINING_SAMPLES = df.shape[0]\n\nprint(\"we have \" + str(TRAINING_SAMPLES) + \" different samples\")\nprint(\"And there are \"+  str(len(df.Target.unique())) + \" different combinations of labels in our dataset\")\n\nimport seaborn as sns\nsns.set(style=\"dark\")\n\nn = 20\n\nvalues = df['Target'].value_counts()[:n].keys().tolist()\ncounts = df['Target'].value_counts()[:n].tolist()\n\nplt.figure(figsize=(6,6))\npal = sns.cubehelix_palette(n, start=2, rot=0, dark=0, light=.75, reverse=True)\ng = sns.barplot(y=counts, x=values, palette=pal)\ng.set_title(str(n)+\" MOST COMMON LABEL COMBINATIONS\")\ng.set_xticklabels(g.get_xticklabels(),rotation=90);","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"de645f4e5a43806a5ae0e9b29642d9782dc82199"},"cell_type":"code","source":"from PIL import Image\n\ndef load_image(basepath, image_id):\n    images = np.zeros(shape=(256,256,4))\n    r = Image.open(basepath+image_id+\"_red.png\").resize((256,256))\n    g = Image.open(basepath+image_id+\"_green.png\").resize((256,256))\n    b = Image.open(basepath+image_id+\"_blue.png\").resize((256,256))\n    y = Image.open(basepath+image_id+\"_yellow.png\").resize((256,256))\n\n    images[:,:,0] = np.asarray(r)\n    images[:,:,1] = np.asarray(g)\n    images[:,:,2] = np.asarray(b)\n    images[:,:,3] = np.asarray(y)\n    \n    return images","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"51d112e78c77185f36d6f8b24bdd6f4ef265c51e"},"cell_type":"code","source":"targets = df['Target'].value_counts().keys()\ncounts = df['Target'].value_counts().values\n\nhow_many = counts/TRAINING_SAMPLES*DATASET_SIZE\n\n# at least one example of each possible combination of labels..\nhow_many = how_many.astype('int')+1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"757bcf11b6ad300c1c63ecc93ce046e912d773d2"},"cell_type":"code","source":"import torch\nimport numpy as np\nimport pandas as pd\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms, utils\nimport warnings\nwarnings.filterwarnings(\"ignore\")\nfrom skimage import io, transform\nfrom sklearn.preprocessing import MultiLabelBinarizer\nclasses = np.arange(0,28)\nmlb = MultiLabelBinarizer(classes)\nmlb.fit(classes)\nclass HumanProteinDataset(Dataset):\n\n    def __init__(self, csv_file,transform=None, test=False):\n        \"\"\"\n        Args:\n            csv_file (string): Path to the csv file with annotations.\n            test (Boolean): the csv no contains labels\n            transform (callable, optional): Optional transform to be applied\n                on a sample.\n        \"\"\"\n        self.test = test\n        self.complete_df = pd.read_csv(csv_file)\n        \n        if not test:\n            self.path = train_path\n            self.loadData()\n        else:\n            self.path = test_path\n            self.df = self.complete_df\n            \n        self.transform = transform\n        \n    def CreateDummyVariables(self):\n        self.complete_df['Targets'] = self.complete_df['Target'].map(lambda x: list(map(int, x.strip().split())))\n            \n    def loadData(self):\n        self.CreateDummyVariables()\n        self.df = pd.DataFrame(columns=['Id','Target'])\n        for i, target in enumerate(targets):\n            fdf = self.complete_df[self.complete_df['Target'] == target]\n            sample = fdf.sample(n=how_many[i], replace=False)\n            self.df = self.df.append(sample)\n        self.df = self.df.sample(frac=1).reset_index(drop=True)\n            \n    def __getitem__(self, idx):\n        \n        image = load_image(self.path, self.df['Id'].iloc[idx])\n        \n        sample = {'image': image}\n\n        if not self.test:\n            target = np.array(self.complete_df['Targets'].iloc[idx])\n            target = mlb.transform([target])\n            sample['target'] = target\n        \n        else:\n            sample['Id'] = self.df['Id'].iloc[idx]\n\n        if self.transform:\n            sample = self.transform(sample)\n        return sample\n    \n    def __len__(self):\n        return self.df.shape[0]\n    \n    def shape(self):\n        return self.df.shape\n    \nclass ToTensor(object):\n    \"\"\"Convert ndarrays in sample to Tensors.\"\"\"\n\n    def __call__(self, sample):\n        \n        image = sample['image']/255.0\n        \n        totensor = transforms.ToTensor()\n        \n        ret = {'image': totensor(image)}\n        \n        if \"target\" in sample.keys():\n            target = sample['target'][0]\n            ret['target'] = target\n        else:\n            ret['Id'] = sample['Id']\n                  \n        return ret","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d364857c35b34683a4282c2dc389267082d3be28"},"cell_type":"code","source":"def Show(sample):\n    f, (ax1,ax2,ax3,ax4) = plt.subplots(1, 4, figsize=(25,25), sharey=True)\n\n    title = ''\n    \n    labels =sample['target']\n                \n    for i, label in enumerate(LABELS):\n        if labels[i] == 1:\n            if title == '':\n                title += label\n            else:\n                title += \" & \" + label\n            \n    ax1.imshow(sample['image'][0,:,:],cmap=\"hot\")\n    ax1.set_title('Red')\n    ax2.imshow(sample['image'][1,:,:],cmap=\"copper\")\n    ax2.set_title('Green')\n    ax3.imshow(sample['image'][2,:,:],cmap=\"bone\")\n    ax3.set_title('Blue')\n    ax4.imshow(sample['image'][3,:,:],cmap=\"afmhot\")\n    ax4.set_title('Yellow')\n    f.suptitle(title, fontsize=20, y=0.62)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"282b37aa6e59133c63ffc6bd115ed0b062537e55"},"cell_type":"code","source":"dataset = HumanProteinDataset(train_csv_path, transform=ToTensor())\nimport random\n\nidxs = random.sample(range(1, dataset.df.shape[0]), 3)\n\nfor idx in idxs:\n    Show(dataset[idx])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"4fb5e73ea113a6ee30b9bd120b09cd6b5f4531b4"},"cell_type":"code","source":"from torch.utils.data.sampler import SubsetRandomSampler\nfrom torch.optim import lr_scheduler\nimport torch.optim as optim\nimport torch.nn as nn\nimport math\n\ndef prepare_loaders():\n    dataset.loadData()\n    num_train = len(dataset)\n    indices = list(range(num_train))\n    val_size = int(0.45 * num_train) \n\n    # Random, non-contiguous split\n    validation_idx = np.random.choice(indices, size=val_size, replace=False)\n    train_idx = list(set(indices) - set(validation_idx))\n\n    train_sampler = SubsetRandomSampler(train_idx)\n    validation_sampler = SubsetRandomSampler(validation_idx)\n\n    dataset_sizes = {}\n\n    dataset_sizes['train'] = len(train_idx)\n    dataset_sizes['val'] = len(validation_idx)\n    train_loader = DataLoader(dataset, batch_size=BATCH_SIZE,num_workers=0, sampler=train_sampler)\n    validation_loader = DataLoader(dataset, batch_size=BATCH_SIZE, num_workers=0,sampler=validation_sampler)\n\n    dataloaders = {}\n\n    dataloaders['train'] = train_loader\n    dataloaders['val'] = validation_loader\n    \n    return (dataloaders, dataset_sizes)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8250904c6ec7c14e48b7e8467226795b29579be4"},"cell_type":"code","source":"dataloaders, dataset_sizes = prepare_loaders()\n\ndataset.df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"80d7074e32c59385e604e1abb6c63f343277a5c2"},"cell_type":"code","source":"# Wout = 1 + (Win - Kernel_size + 2Padding)/Stride\n\nclass CNN(nn.Module):\n    def __init__(self):\n        super(CNN, self).__init__()\n        self.conv1 = nn.Sequential(      #input: 4xWxH\n            nn.Conv2d(4,8,5,1,2),        # input_channels, output_channels, kernel_size, stride, padding   \n            nn.ReLU(),                      \n            nn.MaxPool2d(kernel_size=2), #output: 8xW/2xH/2\n        )\n        self.conv2 = nn.Sequential(      #input: 4xWxH\n            nn.Conv2d(8,16,5,1,2),        # input_channels, output_channels, kernel_size, stride, padding   \n            nn.ReLU(),                      \n            nn.MaxPool2d(kernel_size=2), #output: 16xW/4xH/4\n        )\n        self.drop_out = nn.Dropout()\n        self.out1 = nn.Linear( int(16 * W/4 * H/4), 900)   # fully connected layer, output 28 classes\n        self.out2 = nn.Linear( 900, 28)   # fully connected layer, output 28 classes\n\n    def forward(self, x):\n        x = self.conv1(x)\n        x = self.conv2(x)\n        x = x.view(x.size(0), -1)           # flatten the output of conv2 to (batch_size, 32 * 7 * 7)\n        output = self.drop_out(x)\n        output = self.out1(x)\n        output = self.out2(output)\n        return output, x    # return x for visualization\n\ndef init_weights(m):\n        if type(m) == nn.Linear:\n            torch.nn.init.xavier_uniform(m.weight)\n            m.bias.data.fill_(0.01)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1187d6e52dddc8c45b5d26d684d0a29a50fe4032"},"cell_type":"code","source":"# create a new subdataset for training\ndataloaders, dataset_sizes = prepare_loaders()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b966aff905f243bf6d78d790fcba9e3d3dafc50f"},"cell_type":"code","source":"losses = {}\naccuracys = {}\n\nlosses['train'] = []\nlosses['val'] = []\naccuracys['train'] = []\naccuracys['val'] = []","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ac948b58d95b5846c863201cdc1dfd8e2ccda2b7"},"cell_type":"code","source":"def Train(model, epochs=10, criterion=nn.BCEWithLogitsLoss(reduction='sum'), optimizer= None):\n    since = time.time()\n\n    best_model_wts = copy.deepcopy(model.state_dict())\n    best_acc = 0.0\n\n\n    if optimizer == None:\n        optimizer = optim.Adam(model.parameters(), lr=0.04, betas=(0.9, 0.99))\n    \n    device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n    print(\"training with device: \" + str(device))\n    \n    model.to(device)\n    \n    for epoch in range(epochs):  # loop over the dataset multiple times\n        print('Epoch {}/{}'.format(epoch+1, epochs))\n        print('-' * 10)\n        \n        for phase in ['train', 'val']:\n            if phase == 'train':\n                model.train()  # Set model to training mode\n            else:\n                model.eval()   # Set model to evaluate mode\n                \n            running_loss = 0.0    \n            running_corrects = 0.0\n    \n            for i, data in enumerate(dataloaders[phase], 0):            \n                # get the inputs\n                inputs, labels = data['image'], data['target']\n\n                inputs, labels = inputs.to(device,dtype=torch.float), labels.to(device,dtype=torch.float)\n\n                # zero the parameter gradients\n                optimizer.zero_grad()\n                \n                # forward\n                # track history if only in train\n                with torch.set_grad_enabled(phase == 'train'):\n                    outputs = model(inputs)[0]\n                    preds = outputs > 0\n                    loss = criterion(outputs, labels)\n\n                    # backward + optimize only if in training phase\n                    if phase == 'train':\n                        loss.backward()\n                        optimizer.step()\n                        \n                 # statistics\n                running_loss += loss.item() * inputs.size(0)\n                labels = labels.data.byte()\n                running_corrects += torch.sum((labels == preds).all(1))\n                                \n            epoch_loss = running_loss / dataset_sizes[phase]\n            epoch_acc = running_corrects.float() / dataset_sizes[phase]\n            print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc))\n            \n            losses[phase].append(epoch_loss)\n            accuracys[phase].append(epoch_acc)\n            \n            # deep copy the model\n            if phase == 'val' and epoch_acc > best_acc:\n                best_acc = epoch_acc\n                best_model_wts = copy.deepcopy(model.state_dict())\n                \n                \n\n    time_elapsed = time.time() - since\n    print('Training complete in {:.0f}m {:.0f}s'.format(\n        time_elapsed // 60, time_elapsed % 60))\n    print('Best val Acc: {:4f}'.format(best_acc))\n\n    # load best model weights\n    model.load_state_dict(best_model_wts)\n    return model\n\n\ndef run_model(model,batch):\n    device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n    model.to(device)\n    inputs = batch\n    inputs = inputs.to(device,dtype=torch.float)\n    out = model(inputs)\n    out = out[0].cpu()\n    return out","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a537a116724ae0a38bb5d7bbe0cb0129be7d9e99"},"cell_type":"code","source":"# model creation and initialization\ncnn = CNN()\ncnn.apply(init_weights)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c1545c08b007ab29492fd5b3c087609b766cfb07"},"cell_type":"code","source":"# training\ntorch.cuda.empty_cache()\ncnn = Train(cnn, epochs=10,  criterion=nn.BCEWithLogitsLoss(reduction='sum'), optimizer = optim.Adam(cnn.parameters(), lr=0.001, betas=(0.9, 0.99)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d0c2b69005901ec3691eace4aa31f25c70f294eb"},"cell_type":"code","source":"# training\ntorch.cuda.empty_cache()\ncnn = Train(cnn, epochs=10,  criterion=nn.BCEWithLogitsLoss(reduction='sum'), optimizer = optim.Adam(cnn.parameters(), lr=0.001, betas=(0.9, 0.99)))\ndataloaders, dataset_sizes = prepare_loaders()\ntorch.cuda.empty_cache()\ncnn = Train(cnn, epochs=10,  criterion=nn.BCEWithLogitsLoss(reduction='sum'), optimizer = optim.Adam(cnn.parameters(), lr=0.001, betas=(0.9, 0.99)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"74a013679bf884395a0628b3361e249dabaeff7f"},"cell_type":"code","source":"plt.plot(np.arange(len(losses['train'])), losses['train'],label=\"train\")\nplt.plot(np.arange(len(losses['val'])), losses['val'], label=\"val\")\nplt.legend()\nplt.title(\"loss by epoch\")\nplt.show()\n\nplt.plot(np.arange(len(accuracys['train'])), accuracys['train'], label=\"train\")\nplt.plot(np.arange(len(accuracys['val'])), accuracys['val'], label=\"val\")\nplt.title(\"accuracy by epoch\")\nplt.legend()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"eefc633f5e578f1ab939e2d8d566e2a6d4088891"},"cell_type":"code","source":"def save(model, full = True, name=\"model\"):\n    if not full:\n        torch.save(model.state_dict(), name+'_params.pkl')   # save only the parameters\n    else:\n        torch.save(model, name+'.pkl')  # save entire net\n\n        \ndef restore_net(name=\"model\"):\n    model = torch.load(name+'.pkl')\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"119e48ee8ee71f20de390a25798bc168113571f8"},"cell_type":"code","source":"save(cnn, name=\"cnn\")\n!ls","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"9ceb076baf2fcf8f87efda042d1ccbc26fa9454e"},"cell_type":"code","source":"cnn = restore_net(name=\"cnn\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0721a1a99deac88a4179ef44f94d7286e94c9e9e"},"cell_type":"code","source":"submit = pd.read_csv('../input/sample_submission.csv')\n\ndataset_test = HumanProteinDataset(csv_file='../input/sample_submission.csv', transform=transforms.Compose([\n    ToTensor()\n]), test=True)\n\ndataloader_test = DataLoader(dataset_test, batch_size=BATCH_SIZE,\n                        shuffle=False, num_workers=0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6faea5c4ff5b58afca1e6d2a1532f1b7ca26601d"},"cell_type":"code","source":"ids = []\npredictions = []\n\ncnn = cnn.cuda()\n\nfor sample_batched in dataloader_test:\n        out = run_model(cnn,sample_batched['image'])\n        \n        preds = []\n        out = out.detach().numpy()\n        for sample in out:\n            p = \"\"\n            for i,label in enumerate(sample):\n                if label > 0:\n                    p += \" \" + str(i)\n                    print(p)\n            if p == \"\":\n                p = \"0\"\n            else:\n                p = p[1:]\n            preds.append(p)\n\n        ids += list(sample_batched['Id'])\n        predictions += preds","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"798e8ffe553a128e9275c70c03a5d1bc4031612d"},"cell_type":"code","source":"df = pd.DataFrame({'Id':ids,'Predicted':predictions})\ndf.to_csv('protein_classification.csv', header=True, index=False)\n\nprint(df)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3783343a323c5263fefd36aff9f7015832046853"},"cell_type":"code","source":"# import the modules we'll need\nfrom IPython.display import HTML\nimport pandas as pd\nimport numpy as np\nimport base64\n\n# function that takes in a dataframe and creates a text link to  \n# download it (will only work for files < 2MB or so)\ndef create_download_link(df, title = \"Download CSV file\", filename = \"protein_classification.csv\"):  \n    csv = df.to_csv( sep=',', encoding='utf-8', index=False)\n    b64 = base64.b64encode(csv.encode())\n    payload = b64.decode()\n    html = '<a download=\"{filename}\" href=\"data:text/csv;base64,{payload}\" target=\"_blank\">{title}</a>'\n    html = html.format(payload=payload,title=title,filename=filename)\n    return HTML(html)\n\n\n# create a link to download the dataframe\ncreate_download_link(df)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"def200dfd2667d4be04a299dcc49dbc74163a76f"},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}