{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport time\n\nimport matplotlib.pyplot as plt\nimport torch\nimport torchvision\nfrom torch.autograd import Variable\nfrom torchvision import datasets, models, transforms\n\n%matplotlib inline","metadata":{"execution":{"iopub.status.busy":"2021-09-06T17:07:25.579587Z","iopub.execute_input":"2021-09-06T17:07:25.580113Z","iopub.status.idle":"2021-09-06T17:07:26.940845Z","shell.execute_reply.started":"2021-09-06T17:07:25.579981Z","shell.execute_reply":"2021-09-06T17:07:26.940007Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_dir = \"../input/cat-and-dog\"\ndata_str = [\"test_set\", \"training_set\"]\ndata_transform = transforms.Compose([transforms.Resize([64, 64]), transforms.ToTensor()])\nimg_datasets = {\n    x: datasets.ImageFolder(root=data_dir+'/{}/{}'.format(x,x), transform=data_transform)\n    for x in data_str\n}\ndataloader = {\n    x: torch.utils.data.DataLoader(dataset=img_datasets[x], batch_size=16, shuffle=True)\n    for x in data_str\n}","metadata":{"execution":{"iopub.status.busy":"2021-09-06T17:07:26.943971Z","iopub.execute_input":"2021-09-06T17:07:26.944221Z","iopub.status.idle":"2021-09-06T17:07:35.480148Z","shell.execute_reply.started":"2021-09-06T17:07:26.944195Z","shell.execute_reply":"2021-09-06T17:07:35.47928Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_example, y_example = next(iter(dataloader[\"training_set\"]))\n\nprint(\"X_example's number:{}\".format(len(X_example)))\nprint(\"y_example's number:{}\".format(len(y_example)))\nindex_classes = img_datasets[\"training_set\"].class_to_idx\nprint(index_classes)\nexample_classes = img_datasets[\"training_set\"].classes\nprint(example_classes)","metadata":{"execution":{"iopub.status.busy":"2021-09-06T17:37:45.092289Z","iopub.execute_input":"2021-09-06T17:37:45.092663Z","iopub.status.idle":"2021-09-06T17:37:45.179095Z","shell.execute_reply.started":"2021-09-06T17:37:45.092632Z","shell.execute_reply":"2021-09-06T17:37:45.178284Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img = torchvision.utils.make_grid(X_example)\nimg = img.numpy().transpose([1, 2, 0])\nprint([example_classes[i] for i in y_example])\nplt.imshow(img)\nplt.show()  #visualization ","metadata":{"execution":{"iopub.status.busy":"2021-09-06T17:07:35.664367Z","iopub.execute_input":"2021-09-06T17:07:35.664748Z","iopub.status.idle":"2021-09-06T17:07:35.820305Z","shell.execute_reply.started":"2021-09-06T17:07:35.664711Z","shell.execute_reply":"2021-09-06T17:07:35.819392Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"use a pre_trained VGG16 network to do **transfer learing**\n\nfreeze all the paramters in model and adjust its dense layers in classifier","metadata":{"tags":[]}},{"cell_type":"code","source":"model = models.vgg16(pretrained=True)\nfor parma in model.parameters():\n    parma.requires_grad = False\nmodel.classifier = torch.nn.Sequential(\n    torch.nn.Linear(in_features=25088, out_features=1024 * 4, bias=True),\n    torch.nn.ReLU(inplace=True),\n    torch.nn.Dropout(p=0.5, inplace=False),\n    torch.nn.Linear(in_features=1024 * 4, out_features=1024 * 4, bias=True),\n    torch.nn.ReLU(inplace=True),\n    torch.nn.Dropout(p=0.5, inplace=False),\n    torch.nn.Linear(in_features=1024 * 4, out_features=2, bias=True),\n)\nmodel = model.cuda()\nlf = torch.nn.CrossEntropyLoss()\nop = torch.optim.Adam(model.classifier.parameters(), lr=1e-5)\nprint(model)","metadata":{"scrolled":true,"tags":[],"execution":{"iopub.status.busy":"2021-09-06T17:07:35.821671Z","iopub.execute_input":"2021-09-06T17:07:35.82202Z","iopub.status.idle":"2021-09-06T17:07:54.612832Z","shell.execute_reply.started":"2021-09-06T17:07:35.821984Z","shell.execute_reply":"2021-09-06T17:07:54.611915Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"train the model","metadata":{}},{"cell_type":"code","source":"epoch_n = 5\ntime_open = time.time()\n\nfor epoch in range(epoch_n):\n    print('Epoch {}/{}'.format(epoch+1,epoch_n))\n    print('-----------')\n\n    for phase in data_str:\n        if phase == 'training_set':\n            print('Training...')\n            model.train(True)\n        else:\n            print('Validing...')\n            model.train(False)\n        running_loss = 0.0\n        running_correct = 0\n\n        for batch,data in enumerate(dataloader[phase],1):\n            X,y = data\n            X,y = Variable(X.cuda()),Variable(y.cuda())\n            y_pred = model(X)\n\n            _,pred = torch.max(y_pred.data,1)\n\n            op.zero_grad()\n            loss = lf(y_pred,y)\n\n            if phase == 'training_set':\n                loss.backward()\n                op.step()\n\n            running_correct +=torch.sum(pred == y.data)\n            running_loss +=loss.data\n            if batch%500 ==0 and phase =='train':\n                print('Batch {},Train Loss:{:.4f},Train Acc:{:.4f}%'.format(\n                batch,running_loss/batch,100*running_correct/batch/16))\n\n        epoch_loss = running_loss*16/len(img_datasets[phase])\n        epoch_acc = running_correct*100/len(img_datasets[phase])\n\n        print('{} Loss:{:.4f} Acc:{:.4f}%'.format(phase,epoch_loss,epoch_acc))\n\ntime_end = time.time() - time_open\nprint(time_end)","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2021-09-06T17:20:21.34195Z","iopub.execute_input":"2021-09-06T17:20:21.342285Z","iopub.status.idle":"2021-09-06T17:24:15.686817Z","shell.execute_reply.started":"2021-09-06T17:20:21.342255Z","shell.execute_reply":"2021-09-06T17:24:15.685806Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"save the model's paramters(you don't need to train it again)","metadata":{}},{"cell_type":"code","source":"torch.save(model.state_dict(), 'model_params.pth')","metadata":{"execution":{"iopub.status.busy":"2021-09-06T17:24:55.654623Z","iopub.execute_input":"2021-09-06T17:24:55.655047Z","iopub.status.idle":"2021-09-06T17:24:57.71067Z","shell.execute_reply.started":"2021-09-06T17:24:55.655011Z","shell.execute_reply":"2021-09-06T17:24:57.709777Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Validing...\")\nmodel.train(False)\nrunning_loss = 0.0\nrunning_correct = 0\n\nfor batch, data in enumerate(dataloader[\"test_set\"], 1):\n    X, y = data\n    X, y = Variable(X.cuda()), Variable(y.cuda())\n    y_pred = model(X)\n\n    _, pred = torch.max(y_pred.data, 1)\n\n    op.zero_grad()\n    loss = lf(y_pred, y)\n\n    running_correct += torch.sum(pred == y.data)\n    running_loss += loss.data\n\nepoch_loss = running_loss * 16 / len(img_datasets[\"test_set\"])\nepoch_acc = running_correct * 100 / len(img_datasets[\"test_set\"])\n\nprint(\"{} Loss:{:.4f} Acc:{:.4f}%\".format(\"valid\", epoch_loss, epoch_acc))","metadata":{"tags":[],"execution":{"iopub.status.busy":"2021-09-06T17:25:15.821153Z","iopub.execute_input":"2021-09-06T17:25:15.821467Z","iopub.status.idle":"2021-09-06T17:25:23.456678Z","shell.execute_reply.started":"2021-09-06T17:25:15.821437Z","shell.execute_reply":"2021-09-06T17:25:23.455734Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"or use the parameters you saved before","metadata":{}},{"cell_type":"code","source":"# model.load_state_dict(torch.load(\"model_params.pth\"))","metadata":{"execution":{"iopub.status.busy":"2021-09-06T17:08:07.181451Z","iopub.status.idle":"2021-09-06T17:08:07.182029Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# print(\"Validing...\")\n# model.train(False)\n# running_loss = 0.0\n# running_correct = 0\n\n# for batch, data in enumerate(dataloader[\"test_set\"], 1):\n#     X, y = data\n#     X, y = Variable(X.cuda()), Variable(y.cuda())\n#     y_pred = model(X)\n\n#     _, pred = torch.max(y_pred.data, 1)\n\n#     op.zero_grad()\n#     loss = lf(y_pred, y)\n\n#     running_correct += torch.sum(pred == y.data)\n#     running_loss += loss.data\n\n# epoch_loss = running_loss * 16 / len(img_datasets[\"test_set\"])\n# epoch_acc = running_correct * 100 / len(img_datasets[\"test_set\"])\n\n# print(\"{} Loss:{:.4f} Acc:{:.4f}%\".format(\"valid\", epoch_loss, epoch_acc))","metadata":{"execution":{"iopub.status.busy":"2021-09-06T17:08:07.183158Z","iopub.status.idle":"2021-09-06T17:08:07.183771Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"demo","metadata":{}},{"cell_type":"code","source":"dataloader_test = torch.utils.data.DataLoader(\n    dataset=img_datasets['test_set'], batch_size=4, shuffle=True\n)\nX_test, y_test = next(iter(dataloader_test))\ninputs = Variable(X_test)\ninputs = inputs.cuda()\npred = model(inputs)\n_, prd = torch.max(pred, 1)\nexample_classes1 = img_datasets['test_set'].classes\nprint(\"predicted：\", [example_classes1[i] for i in prd])\nprint(\"true：\", [example_classes1[i] for i in y_test])\nimg = torchvision.utils.make_grid(X_test)\nimg = img.numpy().transpose(1, 2, 0)\n\nplt.imshow(img)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-09-06T17:28:15.717373Z","iopub.execute_input":"2021-09-06T17:28:15.717726Z","iopub.status.idle":"2021-09-06T17:28:15.876094Z","shell.execute_reply.started":"2021-09-06T17:28:15.717694Z","shell.execute_reply":"2021-09-06T17:28:15.875338Z"},"trusted":true},"execution_count":null,"outputs":[]}]}