{"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":"# GPU\nimport torch\n\ndevice = 'cuda:0' if torch.cuda.is_available() else 'cpu'\nprint('GPU State:', device)","metadata":{"execution":{"iopub.status.busy":"2021-06-14T10:17:37.924596Z","iopub.execute_input":"2021-06-14T10:17:37.925149Z","iopub.status.idle":"2021-06-14T10:17:38.264883Z","shell.execute_reply.started":"2021-06-14T10:17:37.925014Z","shell.execute_reply":"2021-06-14T10:17:38.263051Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Set file path ","metadata":{}},{"cell_type":"code","source":"import os\n\n# Local\n# data_path = './Datasets/'\n\n# Path for Kaggle\ndata_path = '/kaggle/input/beginners-cats-and-dogs/'\n\ntest_data_path = os.path.join(data_path, 'testing_set/testing_set')\ntrain_data_path = os.path.join(data_path, 'training_set/training_set')","metadata":{"execution":{"iopub.status.busy":"2021-06-14T10:17:38.266554Z","iopub.execute_input":"2021-06-14T10:17:38.267177Z","iopub.status.idle":"2021-06-14T10:17:38.272808Z","shell.execute_reply.started":"2021-06-14T10:17:38.267135Z","shell.execute_reply":"2021-06-14T10:17:38.271627Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Take a look at data","metadata":{}},{"cell_type":"code","source":"%matplotlib inline\nfrom PIL import Image\nfrom matplotlib.pyplot import imshow\n\n# check pictures\nimg_path = os.path.join(test_data_path, 'testing_3.jpg')\nim = Image.open(img_path)\nimshow(im)","metadata":{"execution":{"iopub.status.busy":"2021-06-14T10:17:38.274971Z","iopub.execute_input":"2021-06-14T10:17:38.275626Z","iopub.status.idle":"2021-06-14T10:17:38.468856Z","shell.execute_reply.started":"2021-06-14T10:17:38.275589Z","shell.execute_reply":"2021-06-14T10:17:38.468026Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Exploring data format","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n\ntrain_df = pd.read_csv(os.path.join(data_path , 'Train.csv'))\ntrain_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-06-14T10:17:38.470263Z","iopub.execute_input":"2021-06-14T10:17:38.470577Z","iopub.status.idle":"2021-06-14T10:17:38.494562Z","shell.execute_reply.started":"2021-06-14T10:17:38.470545Z","shell.execute_reply":"2021-06-14T10:17:38.493644Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df = pd.read_csv(os.path.join(data_path , 'Test.csv'))\ntest_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-06-14T10:17:38.496001Z","iopub.execute_input":"2021-06-14T10:17:38.496347Z","iopub.status.idle":"2021-06-14T10:17:38.513673Z","shell.execute_reply.started":"2021-06-14T10:17:38.496310Z","shell.execute_reply":"2021-06-14T10:17:38.512988Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from collections import defaultdict\nfrom collections import Counter\nimport numpy as np\n\n# get all the filename and use them to load .jpg\ntrain_x_files = train_df['filename']\nshape_dict = defaultdict(int)\n\n\nsize = 128, 128\nfor idx, filename in enumerate(train_x_files):\n    \n    # use Image.open() to load JPG, and using np.array to transform it to matrix.\n    img_path = os.path.join(train_data_path, filename)\n    im = Image.open(img_path)\n      \n    # resize image to the largest \"size\"\n    im.thumbnail(size, Image.ANTIALIAS)\n\n    # .conver('L') could get gray scale image\n    numeric_gray_x = np.array(im.convert('L'), dtype='float32')\n    shape_dict[numeric_gray_x.shape] += 1\n    \ncounter = Counter(shape_dict)","metadata":{"execution":{"iopub.status.busy":"2021-06-14T10:17:38.514875Z","iopub.execute_input":"2021-06-14T10:17:38.515223Z","iopub.status.idle":"2021-06-14T10:18:15.664041Z","shell.execute_reply.started":"2021-06-14T10:17:38.515187Z","shell.execute_reply":"2021-06-14T10:18:15.663177Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Almost all picture has different shape.","metadata":{}},{"cell_type":"code","source":"counter.most_common(10)","metadata":{"execution":{"iopub.status.busy":"2021-06-14T10:18:15.665430Z","iopub.execute_input":"2021-06-14T10:18:15.665776Z","iopub.status.idle":"2021-06-14T10:18:15.672717Z","shell.execute_reply.started":"2021-06-14T10:18:15.665740Z","shell.execute_reply":"2021-06-14T10:18:15.671924Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Geberate (data, label) for training\n\nThe label (**y**) of data could derive from Train.csv directly.  ","metadata":{}},{"cell_type":"markdown","source":"The input (**x**) need some preprocessing:\n* load JPG transform to numerical matrix \n* permute the dimension to match the input format of nn.Conv2d\n* padding data to the same size\n\n\n存參:https://towardsdatascience.com/data-preprocessing-and-network-building-in-cnn-15624ef3a28b","metadata":{}},{"cell_type":"code","source":"# function for transform figure into matrix\n\ndef fig2matrix(data_df, data_path, size=(128,128), channel=1, is_train:bool=True):\n    # get all the filename and use them to load .jpg\n    x_files = data_df['filename']\n\n    # prepare a list to store matrix\n    matrix_x = []\n    data_idx = []\n    \n    show = True\n    for idx, filename in enumerate(x_files):\n\n        # use Image.open() to load JPG, and using np.array to transform it to matrix.\n        img_path = os.path.join(data_path, filename)\n        im = Image.open(img_path)\n\n        # resize image to the largest \"size\"\n        im.thumbnail(size, Image.ANTIALIAS)\n\n        # using np.array to transform it to matrix\n        # turn them into torch Tensor for utilize permute() function\n        numeric_rgb_x = np.array(im, dtype='float32')\n        if numeric_rgb_x.shape == (96, 128, 3):\n\n            data_idx.append(idx)  \n            if channel == 3:\n                matrix_x.append(torch.as_tensor(numeric_rgb_x).permute(2, 0, 1))\n\n            elif channel == 1:\n                # .conver('L') could get gray scale image\n                numeric_gray_x = np.array(im.convert('L'), dtype='float32')\n                matrix_x.append(torch.as_tensor(numeric_gray_x).unsqueeze(0))\n\n            if show:\n                print(f'matrix_x[0] type: {type(matrix_x[0])}')\n                print(f'matrix_x[0] shape: {matrix_x[0].shape}')\n                show = False\n\n    labels = torch.as_tensor(data_df['label'].values[data_idx]) if is_train else None\n    return torch.stack(matrix_x), labels, data_idx","metadata":{"execution":{"iopub.status.busy":"2021-06-14T10:29:26.387183Z","iopub.execute_input":"2021-06-14T10:29:26.387747Z","iopub.status.idle":"2021-06-14T10:29:26.399885Z","shell.execute_reply.started":"2021-06-14T10:29:26.387706Z","shell.execute_reply":"2021-06-14T10:29:26.398967Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f'Process training data...')\ntrain_x, train_y, train_data_idx = fig2matrix(train_df, data_path=train_data_path, is_train=True)\n\nprint(f'\\nProcess testing data...')\ntest_x, _, test_data_idx = fig2matrix(test_df, data_path=test_data_path, is_train=False)","metadata":{"execution":{"iopub.status.busy":"2021-06-14T10:29:26.401544Z","iopub.execute_input":"2021-06-14T10:29:26.401845Z","iopub.status.idle":"2021-06-14T10:30:13.263744Z","shell.execute_reply.started":"2021-06-14T10:29:26.401818Z","shell.execute_reply":"2021-06-14T10:30:13.262860Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('In training set:')\nprint(f' train_y type: {type(train_y)}')\nprint(f' train_y shape: {train_y.shape}')\n\nn_dogs = sum([1 for y in train_y if y==0])\nprint(f'   n_dogs: {n_dogs}')\nprint(f'   n_cats: {len(train_y) - n_dogs}')","metadata":{"execution":{"iopub.status.busy":"2021-06-14T10:22:46.273629Z","iopub.execute_input":"2021-06-14T10:22:46.273952Z","iopub.status.idle":"2021-06-14T10:22:46.314347Z","shell.execute_reply.started":"2021-06-14T10:22:46.273915Z","shell.execute_reply":"2021-06-14T10:22:46.313491Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Build Classifier","metadata":{}},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\n\nimport torch\nimport torch.nn as nn\n\nclass testNet(nn.Module):\n    def __init__(self):\n        super(testNet, self).__init__()\n        self.cnn1 = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=5, \n                             stride=2, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')\n        self.act = nn.ReLU()\n        \n        self.cnn2 = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=3, \n                              stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')\n        \n        self.fc = nn.Linear(2640, 128)\n        self.fc2 = nn.Linear(128, 32)\n        self.fc3 = nn.Linear(32, 2)\n\n    def forward(self, x_3D):\n        x1 = self.act(self.cnn1(x_3D))\n        x2 = self.act(self.cnn2(x1))\n        x_flat = torch.flatten(x2, 1)\n#         print('x_flat:',x_flat.shape)\n        x3 = self.act(self.fc(x_flat))\n        x4 = self.act(self.fc2(x3))\n        x5 = self.fc3(x4)\n        return x5","metadata":{"execution":{"iopub.status.busy":"2021-06-14T10:23:13.210425Z","iopub.execute_input":"2021-06-14T10:23:13.210766Z","iopub.status.idle":"2021-06-14T10:23:13.221097Z","shell.execute_reply.started":"2021-06-14T10:23:13.210733Z","shell.execute_reply":"2021-06-14T10:23:13.219953Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Prepare dataloader\nUsing dataloader, we could manipulate data more easily. For example, dataloader can do shuffle for us. ","metadata":{}},{"cell_type":"code","source":"from sklearn.preprocessing import OneHotEncoder\nfrom torch.utils.data import DataLoader, TensorDataset\n\n# onehotencoder = OneHotEncoder()\n# train_Y = onehotencoder.fit_transform(torch.as_tensor(train_y).unsqueeze(-1)).toarray()\n\ntrainLoader = DataLoader(TensorDataset(train_x, train_y), batch_size=32, shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2021-06-14T10:23:14.343088Z","iopub.execute_input":"2021-06-14T10:23:14.343452Z","iopub.status.idle":"2021-06-14T10:23:14.348923Z","shell.execute_reply.started":"2021-06-14T10:23:14.343417Z","shell.execute_reply":"2021-06-14T10:23:14.347136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for data in trainLoader:\n    print('x:', data[0])\n    print('y:', data[1])    \n    break","metadata":{"execution":{"iopub.status.busy":"2021-06-14T10:23:15.802886Z","iopub.execute_input":"2021-06-14T10:23:15.803227Z","iopub.status.idle":"2021-06-14T10:23:15.822054Z","shell.execute_reply.started":"2021-06-14T10:23:15.803195Z","shell.execute_reply":"2021-06-14T10:23:15.821042Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Train","metadata":{}},{"cell_type":"code","source":"import torch.optim as optim\n\nmodel = testNet()\nmodel.to(device)\n\n# Parameters\nepochs = 300\nlr = 0.001\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.SGD(model.parameters(), lr=lr)","metadata":{"execution":{"iopub.status.busy":"2021-06-14T10:27:44.565261Z","iopub.execute_input":"2021-06-14T10:27:44.565611Z","iopub.status.idle":"2021-06-14T10:27:44.578596Z","shell.execute_reply.started":"2021-06-14T10:27:44.565581Z","shell.execute_reply":"2021-06-14T10:27:44.577723Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train\nfor epoch in range(epochs):\n    running_loss = 0.0\n\n    for times, data in enumerate(trainLoader):\n        inputs, labels = data[0].to(device), data[1].to(device)\n#         print('inputs:',inputs)\n\n        # Zero the parameter gradients\n        optimizer.zero_grad()\n\n        # Foward + backward + optimize\n        outputs = model(inputs)\n\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n\n        # Print statistics\n        running_loss += loss.item()\n    print('[%d/%d, %d/%d] loss: %.5f' % (epoch+1, epochs, times+1, len(trainLoader), running_loss/2000))\n\nprint('Training Finished.')","metadata":{"execution":{"iopub.status.busy":"2021-06-14T10:27:45.698606Z","iopub.execute_input":"2021-06-14T10:27:45.698925Z","iopub.status.idle":"2021-06-14T10:29:26.385741Z","shell.execute_reply.started":"2021-06-14T10:27:45.698898Z","shell.execute_reply":"2021-06-14T10:29:26.384758Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Prediciton","metadata":{}},{"cell_type":"code","source":"# prediction\npred_y = []\nfor times, data in enumerate(test_x):\n    inputs = data.to(device)\n    # Foward + backward + optimize\n    outputs = model(inputs.unsqueeze(0))\n\n    # Print statistics\n    pred_y.append(torch.argmax(outputs).item())","metadata":{"execution":{"iopub.status.busy":"2021-06-14T10:33:00.759846Z","iopub.execute_input":"2021-06-14T10:33:00.760183Z","iopub.status.idle":"2021-06-14T10:33:01.270020Z","shell.execute_reply.started":"2021-06-14T10:33:00.760140Z","shell.execute_reply":"2021-06-14T10:33:01.269128Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"f = open('prediction.csv', 'w')\nprint(f'filename,label', file=f)\n\ni = 0\nfor idx, file in enumerate(test_df['filename']):\n    if idx in test_data_idx:\n        print(f'{file},{pred_y[i]}',file=f)\n        i += 1\n    else:\n        print(f'{file},0', file=f)\n        \nf.close()","metadata":{"execution":{"iopub.status.busy":"2021-06-14T10:35:11.570183Z","iopub.execute_input":"2021-06-14T10:35:11.570522Z","iopub.status.idle":"2021-06-14T10:35:11.590392Z","shell.execute_reply.started":"2021-06-14T10:35:11.570492Z","shell.execute_reply":"2021-06-14T10:35:11.589671Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred_df = pd.read_csv('prediction.csv')\npred_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-06-14T10:35:55.219311Z","iopub.execute_input":"2021-06-14T10:35:55.219673Z","iopub.status.idle":"2021-06-14T10:35:55.234424Z","shell.execute_reply.started":"2021-06-14T10:35:55.219638Z","shell.execute_reply":"2021-06-14T10:35:55.233500Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}