{"cells":[{"metadata":{},"cell_type":"markdown","source":"## Image Classification with Pytorch","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"This notebook is my first classification work and it could be look coarse but i think it will be helpful to pytorch real starter.","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"### there are 8 processes while doing this job.","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"1. import Library\n2. hyper parameter setting\n3. set seed and random value \n4. data load\n5. make our model\n6. set our loss function and optimizer\n7. train\n8. check our model performance or using test datasets in trained model","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"\n### 1. Import Library","execution_count":null},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"#about torch...\nimport torch\nimport torch.nn as nn\nimport torch\nimport torch.optim as optim\nimport torch.nn.functional as F\n\nfrom torchvision import datasets, models, transforms\nfrom torch.utils.data import DataLoader, Dataset\n\n#using numpy\nimport numpy as np\n\n#for data load or save\nimport pandas as pd\n\n#visualize some datasets\nimport matplotlib.pyplot as plt\n\n#check our work directory\nimport os\n\n#to unzip datasets\nimport zipfile","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### 2. Hyper parameters Setting","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"lr = 0.001 # learning_rate\nbatch_size = 100 # we will use mini-batch method\nepochs = 10 # How much to train a model","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"3. Set seed and Random Value","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"device = 'cuda' if torch.cuda.is_available() else 'cpu'\n\ntorch.manual_seed(1234)\nif device =='cuda':\n    torch.cuda.manual_seed_all(1234)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### 4. Load train,  test data","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"In this competition, we can't use datasets with only pandas\nwe should to unzip datasets. and we must check our working directory before unzipping","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"check a directory","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"os.listdir('../input/dogs-vs-cats-redux-kernels-edition')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### make a directory for our datasets after unzipping","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"os.makedirs('../data', exist_ok=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"base_dir = '../input/dogs-vs-cats-redux-kernels-edition'\ntrain_dir = '../data/train'\ntest_dir = '../data/test'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"with zipfile.ZipFile(os.path.join(base_dir, 'train.zip')) as train_zip:\n    train_zip.extractall('../data')\n    \nwith zipfile.ZipFile(os.path.join(base_dir, 'test.zip')) as test_zip:\n    test_zip.extractall('../data')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"os.listdir(train_dir)[:5]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import glob\n\ntrain_list = glob.glob(os.path.join(train_dir,'*.jpg'))\ntest_list = glob.glob(os.path.join(test_dir, '*.jpg'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(train_list)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### check our datasets","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"from PIL import Image\nrandom_idx = np.random.randint(1,25000,size=10)\n\nfig = plt.figure()\ni=1\nfor idx in random_idx:\n    ax = fig.add_subplot(2,5,i)\n    img = Image.open(train_list[idx])\n    plt.imshow(img)\n    i+=1\n\nplt.axis('off')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_list[0].split('/')[-1].split('.')[0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"int(test_list[0].split('/')[-1].split('.')[0])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(len(train_list), len(test_list))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.model_selection import train_test_split\ntrain_list, val_list = train_test_split(train_list, test_size=0.2)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Image Augumentation\n- we have to do this job before making our model. cuz it will prevent overfitting Possibility","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"#data Augumentation\ntrain_transforms =  transforms.Compose([\n        transforms.Resize((224, 224)),\n        transforms.RandomResizedCrop(224),\n        transforms.RandomHorizontalFlip(),\n        transforms.ToTensor(),\n    ])\n\nval_transforms = transforms.Compose([\n        transforms.Resize((224, 224)),\n        transforms.RandomResizedCrop(224),\n        transforms.RandomHorizontalFlip(),\n        transforms.ToTensor(),\n    ])\n\n\ntest_transforms = transforms.Compose([   \n    transforms.Resize((224, 224)),\n     transforms.RandomResizedCrop(224),\n    transforms.RandomHorizontalFlip(),\n    transforms.ToTensor()\n    ])\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Load datasets\n- this code is for load our image sets. you can find this code easily in pytorch.org , main page","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"class dataset(torch.utils.data.Dataset):\n    #가져와서 처리\n    def __init__(self,file_list,transform=None):\n        self.file_list = file_list\n        self.transform = transform\n        \n        \n    #dataset length\n    def __len__(self):\n        self.filelength = len(self.file_list)\n        return self.filelength\n    \n    #load an one of images\n    def __getitem__(self,idx):\n        img_path = self.file_list[idx]\n        img = Image.open(img_path)\n        img_transformed = self.transform(img)\n        \n        label = img_path.split('/')[-1].split('.')[0]\n        if label == 'dog':\n            label=1\n        elif label == 'cat':\n            label=0\n            \n        return img_transformed,label\n        ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### use torchvision.datasets","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data = dataset(train_list, transform=train_transforms)\ntest_data = dataset(test_list, transform=test_transforms)\nval_data = dataset(val_list, transform=test_transforms)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_loader = torch.utils.data.DataLoader(dataset = train_data, batch_size=batch_size, shuffle=True )\ntest_loader = torch.utils.data.DataLoader(dataset = test_data, batch_size=batch_size, shuffle=True)\nval_loader = torch.utils.data.DataLoader(dataset = val_data, batch_size=batch_size, shuffle=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(len(train_data), len(train_loader))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(len(val_data), len(val_loader))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#check our images shape\ntrain_data[0][0].shape","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### build Model\n- 3 Convolution layer and 2 fully connected layer\n- batchNormalization for limit overfitting","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"class Cnn(nn.Module):\n    def __init__(self):\n        super(Cnn,self).__init__()\n        \n        self.layer1 = nn.Sequential(\n            nn.Conv2d(3,16,kernel_size=3, padding=0,stride=2),\n            nn.BatchNorm2d(16),\n            nn.ReLU(),\n            nn.MaxPool2d(2)\n        )\n        \n        self.layer2 = nn.Sequential(\n            nn.Conv2d(16,32, kernel_size=3, padding=0, stride=2),\n            nn.BatchNorm2d(32),\n            nn.ReLU(),\n            nn.MaxPool2d(2)\n            )\n        \n        self.layer3 = nn.Sequential(\n            nn.Conv2d(32,64, kernel_size=3, padding=0, stride=2),\n            nn.BatchNorm2d(64),\n            nn.ReLU(),\n            nn.MaxPool2d(2)\n        )\n        \n        \n        self.fc1 = nn.Linear(3*3*64,10)\n        self.dropout = nn.Dropout(0.5)\n        self.fc2 = nn.Linear(10,2)\n        self.relu = nn.ReLU()\n        \n        \n    def forward(self,x):\n        out = self.layer1(x)\n        out = self.layer2(out)\n        out = self.layer3(out)\n        out = out.view(out.size(0),-1)\n        out = self.relu(self.fc1(out))\n        out = self.fc2(out)\n        return out","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = Cnn().to(device)\nmodel.train()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### set Loss function and optimizer","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"optimizer = optim.Adam(params = model.parameters(),lr=0.001)\ncriterion = nn.CrossEntropyLoss()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Train our Network","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"epochs = 10\n\nfor epoch in range(epochs):\n    epoch_loss = 0\n    epoch_accuracy = 0\n    \n    for data, label in train_loader:\n        data = data.to(device)\n        label = label.to(device)\n        \n        output = model(data)\n        loss = criterion(output, label)\n        \n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n        \n        acc = ((output.argmax(dim=1) == label).float().mean())\n        epoch_accuracy += acc/len(train_loader)\n        epoch_loss += loss/len(train_loader)\n        \n    print('Epoch : {}, train accuracy : {}, train loss : {}'.format(epoch+1, epoch_accuracy,epoch_loss))\n    \n    \n    with torch.no_grad():\n        epoch_val_accuracy=0\n        epoch_val_loss =0\n        for data, label in val_loader:\n            data = data.to(device)\n            label = label.to(device)\n            \n            val_output = model(data)\n            val_loss = criterion(val_output,label)\n            \n            \n            acc = ((val_output.argmax(dim=1) == label).float().mean())\n            epoch_val_accuracy += acc/ len(val_loader)\n            epoch_val_loss += val_loss/ len(val_loader)\n            \n        print('Epoch : {}, val_accuracy : {}, val_loss : {}'.format(epoch+1, epoch_val_accuracy,epoch_val_loss))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dog_probs = []\nmodel.eval()\nwith torch.no_grad():\n    for data, fileid in test_loader:\n        data = data.to(device)\n        preds = model(data)\n        preds_list = F.softmax(preds, dim=1)[:, 1].tolist()\n        dog_probs += list(zip(list(fileid), preds_list))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- In this Problem, we used softmax except sigmoid. \n- why? isn't it binary classification?\n- before i read overview, i didn't recognize that. read overview about this competition First!!","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"dog_probs.sort(key = lambda x : int(x[0]))\ndog_probs","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"idx = list(map(lambda x: x[0],dog_probs))\nprob = list(map(lambda x: x[1],dog_probs))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission = pd.DataFrame({'id':idx,'label':prob})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission.to_csv('result.csv',index=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### check our model performance and visualize some data!","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"import random\n\nid_list = []\nclass_ = {0: 'cat', 1: 'dog'}\n\nfig, axes = plt.subplots(2, 5, figsize=(20, 12), facecolor='w')\n\nfor ax in axes.ravel():\n    \n    i = random.choice(submission['id'].values)\n    \n    label = submission.loc[submission['id'] == i, 'label'].values[0]\n    if label > 0.5:\n        label = 1\n    else:\n        label = 0\n        \n    img_path = os.path.join(test_dir, '{}.jpg'.format(i))\n    img = Image.open(img_path)\n    \n    ax.set_title(class_[label])\n    ax.imshow(img)","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}