{"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 time\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\nfrom os import listdir, makedirs\nfrom os.path import join, exists, expanduser\n\nfrom PIL import Image\n\nimport matplotlib.pyplot as plt\nfrom mpl_toolkits.axes_grid1 import ImageGrid\n\nimport torch\nfrom torch import nn\nfrom torch.autograd import Variable\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms, datasets, models\nfrom torch.optim import lr_scheduler\n","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"ls ../input","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3a26b1de7e251d0c05abe636cdb19c63e7daf77c"},"cell_type":"code","source":"ls ../working","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"45216b7a5d66c539ec284e21c5ba9efa3c7f3841"},"cell_type":"code","source":"INPUT_SIZE = 224\nNUM_CLASSES = 16\ndata_dir = '../input/'\nlabels = pd.read_csv(join(data_dir, 'labels.csv'))\nsample_submission = pd.read_csv(join(data_dir, 'sample_submission.csv'))\nprint(len(listdir(join(data_dir, 'train'))), len(labels))\nprint(len(listdir(join(data_dir, 'test'))), len(sample_submission))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ea2281eaae87f92f209c5bc20347e32b82bdb7cd"},"cell_type":"code","source":"selected_breed_list = list(labels.groupby('breed').count().sort_values(by='id', ascending=False).head(NUM_CLASSES).index)\nlabels = labels[labels['breed'].isin(selected_breed_list)]\nlabels['target'] = 1\nlabels['rank'] = labels.groupby('breed').rank()['id']\nlabels_pivot = labels.pivot('id', 'breed', 'target').reset_index().fillna(0)\n\ntrain = labels_pivot.sample(frac=0.8)\nvalid = labels_pivot[~labels_pivot['id'].isin(train['id'])]\nprint(train.shape, valid.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"579aa1fefea9e0089e2beedbb13806e7a8b87457","collapsed":true},"cell_type":"code","source":"class DogsDataset(Dataset):\n    def __init__(self, labels, root_dir, subset=False, transform=None):\n        self.labels = labels\n        self.root_dir = root_dir\n        self.transform = transform\n    \n    def __len__(self):\n        return len(self.labels)\n    \n    def __getitem__(self, idx):\n        img_name = '{}.jpg'.format(self.labels.iloc[idx, 0])\n        fullname = join(self.root_dir, img_name)\n        image = Image.open(fullname)\n        labels = self.labels.iloc[idx, 1:].as_matrix().astype('float')\n        labels = np.argmax(labels)\n        if self.transform:\n            image = self.transform(image)\n        return [image, labels]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6dc31b5a369ce357e8e499e31281924fd5017087","collapsed":true},"cell_type":"code","source":"normalize = transforms.Normalize(\n   mean=[0.485, 0.456, 0.406],\n   std=[0.229, 0.224, 0.225]\n)\nds_trans = transforms.Compose([transforms.Resize(224),\n                               transforms.CenterCrop(224),\n                               transforms.ToTensor(),\n                               normalize])\ntrain_ds = DogsDataset(train, data_dir+'train/', transform=ds_trans)\nvalid_ds = DogsDataset(valid, data_dir+'train/', transform=ds_trans)\n\ntrain_dl = DataLoader(train_ds, batch_size=16, shuffle=True, num_workers=1)\nvalid_dl = DataLoader(valid_ds, batch_size=16, shuffle=False, num_workers=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f610b1bd8b1b0a547e8d34cd344c7fd452c34766","collapsed":true},"cell_type":"code","source":"#create cnn class\nclass Bottleneck(nn.Module):\n    expansion = 4\n\n    def __init__(self, inplanes, planes, stride=1, downsample=None):\n        super(Bottleneck, self).__init__()\n        self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False)\n        self.bn1 = nn.BatchNorm2d(planes)\n        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride,\n                               padding=1, bias=False)\n        self.bn2 = nn.BatchNorm2d(planes)\n        self.conv3 = nn.Conv2d(planes, planes * self.expansion, kernel_size=1, bias=False)\n        self.bn3 = nn.BatchNorm2d(planes * self.expansion)\n        self.relu = nn.ReLU(inplace=True)\n        self.downsample = downsample\n        self.stride = stride\n\n    def forward(self, x):\n        residual = x\n\n        out = self.conv1(x)\n        out = self.bn1(out)\n        out = self.relu(out)\n\n        out = self.conv2(out)\n        out = self.bn2(out)\n        out = self.relu(out)\n\n        out = self.conv3(out)\n        out = self.bn3(out)\n\n        if self.downsample is not None:\n            residual = self.downsample(x)\n\n        out += residual\n        out = self.relu(out)\n\n        return out\n\n\nclass DBCNN(torch.nn.Module) :\n    def __init__(self):\n        super(DBCNN, self).__init__()\n        self.baseblock = Bottleneck\n        \n        self.conv1 = nn.Sequential(\n                     nn.Conv2d(in_channels=3, out_channels=64, kernel_size=7, stride=2, padding=3, bias=False), \n                     nn.BatchNorm2d(64),\n                     nn.ReLU(inplace=True),\n                     nn.MaxPool2d(kernel_size=3, stride=2, padding=1)\n                     )\n        \n        downsample = None\n        downsample = nn.Sequential(\n                     nn.Conv2d(64, 64*self.baseblock.expansion, kernel_size=1, stride=1, bias=False),\n                     nn.BatchNorm2d(64*self.baseblock.expansion)\n                     )\n        self.layer1 = nn.Sequential(\n                      self.baseblock(64, 64, 1, downsample),\n                      self.baseblock(256, 64),\n                      self.baseblock(256, 64)\n                      )\n        \n        downsample = nn.Sequential(\n                     nn.Conv2d(256, 128*self.baseblock.expansion, kernel_size=1, stride=2, bias=False),\n                     nn.BatchNorm2d(128*self.baseblock.expansion)\n                     )\n        self.layer2 = nn.Sequential(\n                      self.baseblock(256, 128, 2, downsample),\n                      self.baseblock(512, 128),\n                      self.baseblock(512, 128),            \n                      self.baseblock(512, 128)\n                      )\n        \n        downsample = nn.Sequential(\n                     nn.Conv2d(512, 256*self.baseblock.expansion, kernel_size=1, stride=2, bias=False),\n                     nn.BatchNorm2d(256*self.baseblock.expansion)\n                     )\n        self.layer3 = nn.Sequential(\n                      self.baseblock(512, 256, 2, downsample),\n                      self.baseblock(1024, 256),\n                      self.baseblock(1024, 256),            \n                      self.baseblock(1024, 256),            \n                      self.baseblock(1024, 256),            \n                      self.baseblock(1024, 256)\n                      )\n        \n        downsample = nn.Sequential(\n                     nn.Conv2d(1024, 512*self.baseblock.expansion, kernel_size=1, stride=2, bias=False),\n                     nn.BatchNorm2d(512*self.baseblock.expansion)\n                     )\n        self.layer4 = nn.Sequential(\n                      self.baseblock(1024, 512, 2, downsample),\n                      self.baseblock(2048, 512),\n                      self.baseblock(2048, 512)\n                      )\n        \n        self.avgpool = nn.AvgPool2d(7, stride=1)\n        self.fc = nn.Linear(512*self.baseblock.expansion, 1000)\n \n    def forward(self, x):\n        x = self.conv1(x)\n        \n        x = self.layer1(x)\n        x = self.layer2(x)\n        x = self.layer3(x)\n        x = self.layer4(x)\n        \n        x = self.avgpool(x)\n        x = x.view(x.size(0), -1) # 展平为\n        x = self.fc(x)\n        return x\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"58ad4cf735e13dc7933e7aacfcd3738f5a37a8a9","collapsed":true},"cell_type":"code","source":"dbcnn = DBCNN()\n#if exists(\"../working/dbcnn.pkl\"):\n#    print(\"load model\")\n#    dbcnn = torch.load('dbcnn.pkl')\n    \n#dbcnn = models.resnet50(pretrained=False)\n#print(dbcnn)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6f1d4f87bb48a5cdd1214a1365fb82971f1156a2","collapsed":true},"cell_type":"code","source":"def train_model(dataloders, model, criterion, optimizer, scheduler, num_epochs=25):\n    since = time.time()\n    use_gpu = torch.cuda.is_available()\n    best_model_wts = model.state_dict()\n    best_acc = 0.0\n    dataset_sizes = {'train': len(dataloders['train'].dataset), \n                     'valid': len(dataloders['valid'].dataset)}\n    print(dataset_sizes)\n\n    for epoch in range(num_epochs):\n        for phase in ['train', 'valid']:\n            if phase == 'train':\n                scheduler.step()\n                model.train(True)\n            else:\n                model.train(False)\n\n            running_loss = 0.0\n            running_corrects = 0\n\n            for inputs, labels in dataloders[phase]:\n                if use_gpu:\n                    inputs, labels = Variable(inputs.cuda()), Variable(labels.cuda())\n                else:\n                    inputs, labels = Variable(inputs), Variable(labels)\n\n                optimizer.zero_grad()\n\n                outputs = model(inputs)\n                _, preds = torch.max(outputs.data, 1)\n                loss = criterion(outputs, labels)\n                \n                if phase == 'train':\n                    loss.backward()\n                    optimizer.step()\n                \n                running_loss += loss.data[0] * labels.size()[0]\n                running_corrects += torch.sum(preds == labels.data)\n            if phase == 'train':\n                train_epoch_loss = running_loss / dataset_sizes[phase]\n                train_epoch_acc = running_corrects / dataset_sizes[phase]\n            else:\n                valid_epoch_loss = running_loss / dataset_sizes[phase]\n                valid_epoch_acc = running_corrects / dataset_sizes[phase]\n                \n            if phase == 'valid' and valid_epoch_acc > best_acc:\n                best_acc = valid_epoch_acc\n                best_model_wts = model.state_dict()\n\n        if (epoch + 1)%100 == 0 :\n            print('Epoch [{}/{}] train loss: {:.4f} acc: {:.4f} ' \n              'valid loss: {:.4f} acc: {:.4f}'.format(\n                epoch + 1, num_epochs,\n                train_epoch_loss, train_epoch_acc, \n                valid_epoch_loss, valid_epoch_acc))\n            \n    print('Best val Acc: {:4f}'.format(best_acc))\n\n    model.load_state_dict(best_model_wts)\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"dd05f747923d413cd6cbf7f5511035382f4eedf5","collapsed":true},"cell_type":"code","source":"md = dbcnn\nuse_gpu = torch.cuda.is_available()\n# freeze all model parametersstart_time = time.time()\nfor param in md.parameters():\n    param.requires_grad = False\n\n# new final layer with 16 classes\nnum_ftrs = md.fc.in_features\nmd.fc = torch.nn.Linear(num_ftrs, 16)\nif use_gpu:\n    md = md.cuda()\n\ncriterion = torch.nn.CrossEntropyLoss()\n\nparameters = filter(lambda p: p.requires_grad, md.parameters())\n\noptimizer = torch.optim.Adam(parameters, lr=0.001, betas=(0.9, 0.99))\nexp_lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=200, gamma=0.1)\n\ndloaders = {'train':train_dl, 'valid':valid_dl}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b0151c596a0b8944aaf20ac6eba0a62bb59b4b17"},"cell_type":"code","source":"start_time = time.time()\nmodel = train_model(dloaders, md, criterion, optimizer, exp_lr_scheduler, num_epochs=1000)\nprint('Training time: {:10f} minutes'.format((time.time()-start_time)/60))\n\ntorch.save(model, 'dbcnn.pkl')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e93463110a90668720b0716dcdb96ecd31d9b82c","collapsed":true},"cell_type":"code","source":"ls ../working","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"49a71edbbdd9051f6b13ea902bc0bb005c232296"},"cell_type":"code","source":"def imshow(axis, inp):\n    \"\"\"Denormalize and show\"\"\"\n    inp = inp.numpy().transpose((1, 2, 0))\n    mean = np.array([0.485, 0.456, 0.406])\n    std = np.array([0.129, 0.124, 0.125])\n    #change 0.229,0.224,0.225 to 0.129,0.124,0.125\n    #sometimes can not show image\n    inp = std * inp + mean\n    axis.imshow(inp)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"8a90ad52a006fcf2adf492a6a0e1c2890bc16f7d"},"cell_type":"code","source":"def getBreedName(index):\n    if index >= 0 and index < len(selected_breed_list) :\n        return selected_breed_list[index]\n    return \"unknown\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"ca039dc0da94dcb9ece648ac846d7cfaf99037e6"},"cell_type":"code","source":"def visualize_model(dataloders, model, num_images=16):\n    cnt = 0\n    fig = plt.figure(1, figsize=(16, 16))\n    grid = ImageGrid(fig, 111, nrows_ncols=(4, 4), axes_pad=0.05)\n    for i, (inputs, labels) in enumerate(dataloders['valid']):\n        if use_gpu:\n            inputs, labels = Variable(inputs.cuda()), Variable(labels.cuda())\n        else:\n            inputs, labels = Variable(inputs), Variable(labels)\n        outputs = model(inputs)\n        _, preds = torch.max(outputs.data, 1)\n\n        for j in range(inputs.size()[0]):\n            ax = grid[cnt]\n            imshow(ax, inputs.cpu().data[j])\n            ax.text(10, 210, 'P:{}/R:{}'.format(getBreedName(preds[j]), getBreedName(labels.data[j])), \n                    color='k', backgroundcolor='w', alpha=0.8)\n            cnt += 1\n            if cnt == num_images:\n                return","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0c34d9202bcab28354b89aee59f7e147bdd1a7a5","collapsed":true},"cell_type":"code","source":"visualize_model(dloaders, dbcnn)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"cec34280c254dd39b02fff17e9cd0196c369a380"},"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.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}