{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 10-6 ResNet for cifar10\n", "\n", "## original code is =>\n", "https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html#sphx-glr-beginner-blitz-cifar10-tutorial-py" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import torch\n", "import torch.nn as nn\n", "\n", "import torch.optim as optim\n", "\n", "import torchvision\n", "import torchvision.transforms as transforms" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "import visdom\n", "\n", "vis = visdom.Visdom()\n", "vis.close(env=\"main\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## define value tracker" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def value_tracker(value_plot, value, num):\n", " '''num, loss_value, are Tensor'''\n", " vis.line(X=num,\n", " Y=value,\n", " win = value_plot,\n", " update='append'\n", " )" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "device = 'cuda' if torch.cuda.is_available() else 'cpu'\n", "\n", "torch.manual_seed(777)\n", "if device =='cuda':\n", " torch.cuda.manual_seed_all(777)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))\n", "\n", "### How to Calculate mean and std in Normalize " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "transform = transforms.Compose([\n", " transforms.ToTensor()\n", "])\n", "\n", "trainset = torchvision.datasets.CIFAR10(root='./cifar10', train=True, download=True, transform=transform)\n", "\n", "print(trainset.train_data.shape)\n", "\n", "train_data_mean = trainset.train_data.mean( axis=(0,1,2) )\n", "train_data_std = trainset.train_data.std( axis=(0,1,2) )\n", "\n", "\n", "print(train_data_mean)\n", "print(train_data_std)\n", "\n", "train_data_mean = train_data_mean / 255\n", "train_data_std = train_data_std / 255\n", "\n", "print(train_data_mean)\n", "print(train_data_std)\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "transform_train = transforms.Compose([\n", " transforms.RandomCrop(32, padding=4),\n", " transforms.ToTensor(),\n", " transforms.Normalize(train_data_mean, train_data_std)\n", "])\n", "\n", "transform_test = transforms.Compose([\n", " transforms.ToTensor(),\n", " transforms.Normalize(train_data_mean, train_data_std)\n", "])\n", "\n", "trainset = torchvision.datasets.CIFAR10(root='./cifar10', train=True,\n", " download=True, transform=transform_train)\n", "trainloader = torch.utils.data.DataLoader(trainset, batch_size=256,\n", " shuffle=True, num_workers=0)\n", "\n", "testset = torchvision.datasets.CIFAR10(root='./cifar10', train=False,\n", " download=True, transform=transform_test)\n", "\n", "testloader = torch.utils.data.DataLoader(testset, batch_size=256,\n", " shuffle=False, num_workers=0)\n", "\n", "classes = ('plane', 'car', 'bird', 'cat',\n", " 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## make ResNet50 using resnet.py" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import resnet" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "conv1x1=resnet.conv1x1\n", "Bottleneck = resnet.Bottleneck\n", "BasicBlock= resnet.BasicBlock" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class ResNet(nn.Module):\n", "\n", " def __init__(self, block, layers, num_classes=1000, zero_init_residual=False):\n", " super(ResNet, self).__init__()\n", " self.inplanes = 16\n", " self.conv1 = nn.Conv2d(3, 16, kernel_size=3, stride=1, padding=1,\n", " bias=False)\n", " self.bn1 = nn.BatchNorm2d(16)\n", " self.relu = nn.ReLU(inplace=True)\n", " #self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)\n", " \n", " self.layer1 = self._make_layer(block, 16, layers[0], stride=1)\n", " self.layer2 = self._make_layer(block, 32, layers[1], stride=1)\n", " self.layer3 = self._make_layer(block, 64, layers[2], stride=2)\n", " self.layer4 = self._make_layer(block, 128, layers[3], stride=2)\n", " \n", " self.avgpool = nn.AdaptiveAvgPool2d((1, 1))\n", " self.fc = nn.Linear(128 * block.expansion, num_classes)\n", "\n", " for m in self.modules():\n", " if isinstance(m, nn.Conv2d):\n", " nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')\n", " elif isinstance(m, nn.BatchNorm2d):\n", " nn.init.constant_(m.weight, 1)\n", " nn.init.constant_(m.bias, 0)\n", "\n", " # Zero-initialize the last BN in each residual branch,\n", " # so that the residual branch starts with zeros, and each residual block behaves like an identity.\n", " # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677\n", " if zero_init_residual:\n", " for m in self.modules():\n", " if isinstance(m, Bottleneck):\n", " nn.init.constant_(m.bn3.weight, 0)\n", " elif isinstance(m, BasicBlock):\n", " nn.init.constant_(m.bn2.weight, 0)\n", "\n", " def _make_layer(self, block, planes, blocks, stride=1):\n", " downsample = None\n", " if stride != 1 or self.inplanes != planes * block.expansion:\n", " downsample = nn.Sequential(\n", " conv1x1(self.inplanes, planes * block.expansion, stride),\n", " nn.BatchNorm2d(planes * block.expansion),\n", " )\n", "\n", " layers = []\n", " layers.append(block(self.inplanes, planes, stride, downsample))\n", " self.inplanes = planes * block.expansion\n", " for _ in range(1, blocks):\n", " layers.append(block(self.inplanes, planes))\n", "\n", " return nn.Sequential(*layers)\n", "\n", " def forward(self, x):\n", " x = self.conv1(x)\n", " #x.shape =[1, 16, 32,32]\n", " x = self.bn1(x)\n", " x = self.relu(x)\n", " #x = self.maxpool(x)\n", "\n", " x = self.layer1(x)\n", " #x.shape =[1, 128, 32,32]\n", " x = self.layer2(x)\n", " #x.shape =[1, 256, 32,32]\n", " x = self.layer3(x)\n", " #x.shape =[1, 512, 16,16]\n", " x = self.layer4(x)\n", " #x.shape =[1, 1024, 8,8]\n", " \n", " x = self.avgpool(x)\n", " x = x.view(x.size(0), -1)\n", " x = self.fc(x)\n", "\n", " return x" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "resnet50 = ResNet(resnet.Bottleneck, [3, 4, 6, 3], 10, True).to(device) \n", "#1(conv1) + 9(layer1) + 12(layer2) + 18(layer3) + 9(layer4) +1(fc)= ResNet50" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "resnet50" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "a=torch.Tensor(1,3,32,32).to(device)\n", "out = resnet50(a)\n", "print(out)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "criterion = nn.CrossEntropyLoss().to(device)\n", "optimizer = torch.optim.SGD(resnet50.parameters(), lr = 0.1, momentum = 0.9, weight_decay=5e-4)\n", "lr_sche = optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## make plot" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "loss_plt = vis.line(Y=torch.Tensor(1).zero_(),opts=dict(title='loss_tracker', legend=['loss'], showlegend=True))\n", "acc_plt = vis.line(Y=torch.Tensor(1).zero_(),opts=dict(title='Accuracy', legend=['Acc'], showlegend=True))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## define acc_check function" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def acc_check(net, test_set, epoch, save=1):\n", " correct = 0\n", " total = 0\n", " with torch.no_grad():\n", " for data in test_set:\n", " images, labels = data\n", " images = images.to(device)\n", " labels = labels.to(device)\n", " outputs = net(images)\n", "\n", " _, predicted = torch.max(outputs.data, 1)\n", "\n", " total += labels.size(0)\n", " correct += (predicted == labels).sum().item()\n", " \n", " acc = (100 * correct / total)\n", " print('Accuracy of the network on the 10000 test images: %d %%' % acc)\n", " if save:\n", " torch.save(net.state_dict(), \"./model/model_epoch_{}_acc_{}.pth\".format(epoch, int(acc)))\n", " return acc" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Training with (acc check + model save)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(len(trainloader))\n", "epochs = 150\n", "\n", "for epoch in range(epochs): # loop over the dataset multiple times\n", "\n", " running_loss = 0.0\n", " lr_sche.step()\n", " for i, data in enumerate(trainloader, 0):\n", " # get the inputs\n", " inputs, labels = data\n", " inputs = inputs.to(device)\n", " labels = labels.to(device)\n", "\n", " # zero the parameter gradients\n", " optimizer.zero_grad()\n", "\n", " # forward + backward + optimize\n", " outputs = resnet50(inputs)\n", " loss = criterion(outputs, labels)\n", " loss.backward()\n", " optimizer.step()\n", "\n", " # print statistics\n", " running_loss += loss.item()\n", " if i % 30 == 29: # print every 30 mini-batches\n", " value_tracker(loss_plt, torch.Tensor([running_loss/30]), torch.Tensor([i + epoch*len(trainloader) ]))\n", " print('[%d, %5d] loss: %.3f' %\n", " (epoch + 1, i + 1, running_loss / 30))\n", " running_loss = 0.0\n", " \n", " #Check Accuracy\n", " acc = acc_check(resnet50, testloader, epoch, save=1)\n", " value_tracker(acc_plt, torch.Tensor([acc]), torch.Tensor([epoch]))\n", " \n", "\n", "print('Finished Training')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Model Accuracy Testing" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "correct = 0\n", "total = 0\n", "\n", "with torch.no_grad():\n", " for data in testloader:\n", " images, labels = data\n", " images = images.to(device)\n", " labels = labels.to(device)\n", " outputs = resnet50(images)\n", " \n", " _, predicted = torch.max(outputs.data, 1)\n", " \n", " total += labels.size(0)\n", " \n", " correct += (predicted == labels).sum().item()\n", "\n", "print('Accuracy of the network on the 10000 test images: %d %%' % (\n", " 100 * correct / total))" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.8" } }, "nbformat": 4, "nbformat_minor": 2 }