{"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":{"trusted":true},"cell_type":"code","source":"train_dir = '../input/iwildcam-2019-fgvc6/'\ntest_dir = '../input/iwildcam-2019-fgvc6/'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nimport cv2\nimport math\n\nfrom PIL import Image\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Помимо категории, есть еще полезная информация такие как время съемки и локация. \n# помимо изображений в сети буду использовать также \ntrain_df = pd.read_csv(os.path.join(train_dir, 'train.csv'))\ntrain_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df = pd.read_csv(os.path.join(test_dir, 'test.csv'))\ntest_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_time_df(df):\n    try:\n        df['date_time'] = pd.to_datetime(df['date_captured'], errors='coerce')\n        df[\"month\"] = df['date_time'].dt.month - 1\n        df[\"hour\"] = df['date_time'].dt.hour\n    except Exception as ex:\n        print(\"Exception:\".format(ex))\n    df.loc[np.isfinite(df['hour']) == False, ['month', 'hour']] = 0\n    df['hour'] = df['hour'].astype(int)\n    df['month'] = df['month'].astype(int)\n    return df\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = get_time_df(train_df)\ntest_df = get_time_df(test_df)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from torchvision import models\nimport torch.nn.functional as F\nimport torch.optim as optim\nimport torch.nn as nn\nimport torch\n\n\nclass SimpleConv(nn.Module):\n    def __init__(self, num_categories, len_dense, weighs):\n        super(SimpleConv, self).__init__()\n        self.model_conv = models.resnet152(pretrained=False)\n        if weighs:\n            self.model_conv.load_state_dict(torch.load(weighs))\n        self.model_conv.fc = nn.Linear(self.model_conv.fc.in_features, num_categories)\n        self.model_dense = nn.Linear(len_dense, num_categories)\n        self.model = nn.Linear(2*num_categories, num_categories)\n    \n    def forward(self, x, y):\n        x1 = self.model_conv(x)\n        x2 = self.model_dense(y)\n        x = F.relu(torch.cat((x1, x2), 1))\n        return self.model(x)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nsimple_conv = SimpleConv(23, 12+24, '../input/resnet152/resnet152.pth')\nsimple_conv = simple_conv.to(device)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from torch.utils.data import Dataset, SubsetRandomSampler, DataLoader\n\nclass SimpleDataset(Dataset):\n    def __init__(self, folder, df, n_category, transform=None):\n        self.transform = transform\n        self.root_dir = folder\n        self.df = df\n        self.y = np.array(df.get('category_id', []))\n#         self.y = np.eye(n_category)[category_ids]\n        month = np.eye(12)[df.month.tolist()]\n        hours = np.eye(24)[df.hour.tolist()]\n        self.time = np.concatenate((month, hours), axis=1)\n    \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, index):\n        img_name = os.path.join(self.root_dir, self.df.file_name[index])\n        image = Image.open(img_name)\n        if len(self.y):\n            label = self.y[index]\n        else:\n            label = 0\n        image = Image.open(img_name).convert('RGB')\n        time = torch.from_numpy(self.time[index]).float()\n        \n        if self.transform:\n            image = self.transform(image)\n        return image, time, label, self.df.id[index]\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from torchvision import transforms\n\ndata_transforms = {\n    'train': transforms.Compose([\n        transforms.Resize((150, 150)),\n        transforms.RandomResizedCrop((128, 128)),\n        transforms.RandomHorizontalFlip(),\n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n    ]),\n    'test': transforms.Compose([\n        transforms.Resize((128, 128)),\n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n    ]),\n}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_ds = SimpleDataset(os.path.join(train_dir, 'train_images'), train_df, n_category=23, transform=data_transforms['train'])\ntest_ds = SimpleDataset(os.path.join(train_dir, 'test_images'), test_df, n_category=23, transform=data_transforms['test'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"batch_size = 256\n\ndata_size = len(train_ds)\nvalidation_fraction = .2\n\nindices = list(range(data_size))\ndata_size = len(indices)\nval_split = int(np.floor((validation_fraction) * data_size))\n\nnp.random.seed(42)\nnp.random.shuffle(indices)\n\nval_indices, train_indices = indices[:val_split], indices[val_split:]\n\ntrain_sampler = SubsetRandomSampler(train_indices)\nval_sampler = SubsetRandomSampler(val_indices)\n\ntrain_loader = torch.utils.data.DataLoader(train_ds, batch_size=batch_size, \n                                           sampler=train_sampler)\nval_loader = torch.utils.data.DataLoader(train_ds, batch_size=batch_size,\n                                         sampler=val_sampler)\n# Notice that we create test data loader in a different way. We don't have the labels\ntrain_sampler = SubsetRandomSampler(train_indices)\n# test_loader = torch.utils.data.DataLoader(test_ds, batch_size=512)\ntest_loader = torch.utils.data.DataLoader(test_ds, batch_size=512)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import copy\nfrom sklearn.metrics import confusion_matrix, f1_score, precision_score, recall_score\n\n\ndef train_model(model, train_loader, val_loader, loss, optimizer, num_epochs):    \n    loss_history = []\n    train_history = []\n    val_history = []\n    best_acc = 0.0\n    best_model_wts = copy.deepcopy(model.state_dict())\n    \n    for epoch in range(num_epochs):\n        model.train() # Enter train mode\n        \n        loss_accum = 0\n        correct_samples = 0\n        total_samples = 0\n\n        for i_step, (x1, x2, y, _) in enumerate(train_loader):\n          \n            x1_gpu = x1.to(device)\n            x2_gpu = x2.to(device)\n            y_gpu = y.to(device)\n            \n            prediction = model(x1_gpu, x2_gpu)    \n            loss_value = loss(prediction, y_gpu)\n            optimizer.zero_grad()\n            loss_value.backward()\n            optimizer.step()\n            _, indices = torch.max(prediction, 1)\n            correct_samples += torch.sum(indices == y_gpu)\n            total_samples += y.shape[0]\n            \n            loss_accum += loss_value\n#             print('{}/{}'.format(i_step, len(train_loader)))\n\n        ave_loss = loss_accum / i_step\n        train_accuracy = float(correct_samples) / total_samples\n        val_f1, val_accuracy = compute_accuracy(model, val_loader)\n        \n        loss_history.append(float(ave_loss))\n        train_history.append(train_accuracy)\n        val_history.append(val_accuracy)\n        \n        print(\"Average loss: %f, Train accuracy: %f, Val accuracy: %f val F1: %f\" % (ave_loss, train_accuracy, val_accuracy, val_f1))\n        if val_f1 > best_acc:\n            best_acc = val_f1\n            best_model_wts = copy.deepcopy(model.state_dict())\n            \n    return loss_history, train_history, val_history, best_model_wts\n\n\ndef compute_accuracy(model, loader):\n    model.eval() \n    correct = 0\n    total = 0\n    predictions = np.empty(shape=len(val_sampler)).astype(int)\n    ground_truth = np.empty(shape=len(val_sampler)).astype(int)\n    \n    with torch.no_grad():\n        for i,(x1, x2, y, _) in enumerate(loader):\n            begin = i*batch_size\n            x1_gpu = x1.to(device)\n            x2_gpu = x2.to(device)\n            y_gpu = y.to(device)\n            \n            outputs = model(x1_gpu, x2_gpu)\n            _, predicted = torch.max(outputs.data, 1)\n            total += y_gpu.size(0)\n            correct += (predicted == y_gpu).sum().item()\n#             print(predictions.shape, np.array(predicted.cpu()).shape)\n#             print(begin, len(predictions), min(begin+batch_size, len(predictions)))\n            predictions[begin : min(begin+batch_size, len(predictions))] = np.array(predicted.cpu())\n            ground_truth[begin : min(begin+batch_size, len(ground_truth))] = np.array(y_gpu.cpu())\n        val_f1 = f1_score(predictions, ground_truth, average='macro')\n    return val_f1, correct / total","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"optimizer = optim.SGD(simple_conv.parameters(), lr=0.01, momentum=0.9)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"loss = nn.CrossEntropyLoss()\nresult = train_model(simple_conv, train_loader, val_loader, loss, optimizer, num_epochs=2)\nsimple_conv.load_state_dict(result[3])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"image_id = []\nbatch_size = test_loader.batch_size\npredictions = np.zeros(shape=len(test_ds)).astype(int)\nsimple_conv.eval()\nwith torch.no_grad():\n    for i,(x1,x2,_,id_img) in enumerate(test_loader):\n#         print('{}/{}'.format(i+1, len(test_loader)))\n        begin = i*batch_size\n        x1_gpu = x1.to(device)\n        x2_gpu = x2.to(device)\n        outputs = simple_conv(x1_gpu, x2_gpu)\n        _, predicted = torch.max(outputs.data, 1)\n        predictions[begin : begin+len(predicted)] = np.array(predicted.cpu())\n        image_id += id_img\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission_df = pd.read_csv(os.path.join('../input/iwildcam-2019-fgvc6','sample_submission.csv'),delimiter=',')\n# submission_df['Predicted'] = predictions","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import csv\n\nwith open('submission.csv', 'w') as submissionFile:\n    writer = csv.writer(submissionFile)\n    writer.writerow(['Id', 'Predicted'])\n    writer.writerows(zip(submission_df.Id.tolist(),predictions))","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}