{"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":"# Python package to open .7z archives\n!pip install py7zr;","metadata":{"execution":{"iopub.status.busy":"2023-10-03T13:55:29.746746Z","iopub.execute_input":"2023-10-03T13:55:29.747218Z","iopub.status.idle":"2023-10-03T13:55:43.244992Z","shell.execute_reply.started":"2023-10-03T13:55:29.747181Z","shell.execute_reply":"2023-10-03T13:55:43.243629Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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\n\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 read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","execution":{"iopub.status.busy":"2023-10-03T13:55:43.247218Z","iopub.execute_input":"2023-10-03T13:55:43.247565Z","iopub.status.idle":"2023-10-03T13:55:43.615617Z","shell.execute_reply.started":"2023-10-03T13:55:43.247533Z","shell.execute_reply":"2023-10-03T13:55:43.614876Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Loading and processing\nimport glob\nimport cv2\nimport py7zr\n\n# Data manipulation\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\n# Torch\nimport torch\nfrom torch.utils.data import DataLoader, Dataset\nimport torchvision\nimport torchvision.transforms as transforms\nfrom torch.utils.data.sampler import SubsetRandomSampler\nimport matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2023-10-03T13:55:43.616591Z","iopub.execute_input":"2023-10-03T13:55:43.617512Z","iopub.status.idle":"2023-10-03T13:55:46.925117Z","shell.execute_reply.started":"2023-10-03T13:55:43.617484Z","shell.execute_reply":"2023-10-03T13:55:46.923747Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Class labels\nCLASS_NAMES = ['airplane', 'automobile', 'bird', 'cat', 'deer',\n               'dog', 'frog', 'horse', 'ship', 'truck']\nif not len(glob.glob('/kaggle/working/train/*.png')):\n    with py7zr.SevenZipFile('/kaggle/input/cifar-10/train.7z', mode='r') as z:\n        z.extractall()\n        \nif not len(glob.glob('/kaggle/working/test/*.png')):\n    with py7zr.SevenZipFile('/kaggle/input/cifar-10/test.7z', mode='r') as z:\n        z.extractall()","metadata":{"execution":{"iopub.status.busy":"2023-10-03T13:55:46.926842Z","iopub.execute_input":"2023-10-03T13:55:46.927958Z","iopub.status.idle":"2023-10-03T14:13:31.057386Z","shell.execute_reply.started":"2023-10-03T13:55:46.927915Z","shell.execute_reply":"2023-10-03T14:13:31.056439Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Convert the filepath to an integer image ID\ndef filename_to_id(filename):\n    return int(filename.split('/')[-1].split('.')[0])\n\n# Load all of the images into an array, also return the image IDs\ndef load_imgs_and_ids(img_directory_path):\n    image_filenames = glob.glob(img_directory_path + '/*.png')\n    list_of_images = []\n    image_ids = []\n    for f in image_filenames:\n        image_id = filename_to_id(f) # E.G. '/kaggle/working/train/44240.png' -> 44240\n        image_ids.append(image_id)\n        data_array = cv2.imread(f)\n        list_of_images.append(data_array)\n    \n\n    X = np.array(list_of_images)\n    \n    return X, image_ids\n    \nX_train, train_img_ids = load_imgs_and_ids('/kaggle/working/train')\n\n# Read the labels from the CSV files and convert the array of IDs into a 0-9 code\ntrain_labels_df = pd.read_csv('/kaggle/input/cifar-10/trainLabels.csv')\nimg_codes = [CLASS_NAMES.index(train_labels_df.loc[img_id-1]['label']) for img_id in train_img_ids]\ny_train = np.array(img_codes)\n\n# TEST\n\nX_test, test_img_ids = load_imgs_and_ids('/kaggle/input/cifar-10/test')","metadata":{"execution":{"iopub.status.busy":"2023-10-03T14:13:31.059640Z","iopub.execute_input":"2023-10-03T14:13:31.059949Z","iopub.status.idle":"2023-10-03T14:13:39.665897Z","shell.execute_reply.started":"2023-10-03T14:13:31.059923Z","shell.execute_reply":"2023-10-03T14:13:39.664919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# RGB pixel values lie on a [0,...,255] scale. We rescale the channels to have channel intensities lie \n# from 0 to 1 inclusive\n\nX_train = X_train / 255.0\nX_test = X_test / 255.0","metadata":{"execution":{"iopub.status.busy":"2023-10-03T14:13:39.667213Z","iopub.execute_input":"2023-10-03T14:13:39.667569Z","iopub.status.idle":"2023-10-03T14:13:40.273835Z","shell.execute_reply.started":"2023-10-03T14:13:39.667544Z","shell.execute_reply":"2023-10-03T14:13:40.272784Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Class TrainDataset\nclass TrainDataset(Dataset):\n    def __init__(self, X, y, transform=None):\n        self.X = X\n        self.y = y\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.X)\n    \n    def __getitem__(self, idx):\n        image = self.X[idx].astype(np.float32).reshape(32, 32, 3)\n        label = self.y[idx]\n        \n        if self.transform:\n            image = self.transform(image)\n            \n        return image, label","metadata":{"execution":{"iopub.status.busy":"2023-10-03T14:13:40.275408Z","iopub.execute_input":"2023-10-03T14:13:40.275717Z","iopub.status.idle":"2023-10-03T14:13:40.282757Z","shell.execute_reply.started":"2023-10-03T14:13:40.275690Z","shell.execute_reply":"2023-10-03T14:13:40.281258Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Class TestDataset\nclass TestDataset(Dataset):\n    def __init__(self, X, transform=None):\n        self.X = X\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.X)\n    \n    def __getitem__(self, idx):\n        image = self.X[idx].astype(np.float32).reshape(32, 32, 3)\n        \n        if self.transform:\n            image = self.transform(image)\n            \n        return image","metadata":{"execution":{"iopub.status.busy":"2023-10-03T14:13:40.284157Z","iopub.execute_input":"2023-10-03T14:13:40.284606Z","iopub.status.idle":"2023-10-03T14:13:40.297895Z","shell.execute_reply.started":"2023-10-03T14:13:40.284571Z","shell.execute_reply":"2023-10-03T14:13:40.297018Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# number of subprocesses to use for data loading\nnum_workers = 2\n# how many samples per batch to load\nbatch_size = 32\n\n# convert data to torch.FloatTensor\n#transform = transforms.ToTensor()\n\n\n# prepare data loaders\ntrain_loader = torch.utils.data.DataLoader(TrainDataset(X_train, y_train, transform=transforms.ToTensor()), batch_size=batch_size, num_workers=num_workers)\ntest_loader = torch.utils.data.DataLoader(TestDataset(X_test, transform=transforms.ToTensor()), batch_size=batch_size, num_workers=num_workers)","metadata":{"execution":{"iopub.status.busy":"2023-10-03T14:13:40.299679Z","iopub.execute_input":"2023-10-03T14:13:40.300101Z","iopub.status.idle":"2023-10-03T14:13:40.318632Z","shell.execute_reply.started":"2023-10-03T14:13:40.300059Z","shell.execute_reply":"2023-10-03T14:13:40.317672Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Xay dung model\nimport torch.nn as nn\nimport torch.nn.functional as F\n\n# define the Multi-layer perceptron architecture\nclass Net(nn.Module):\n    def __init__(self):\n        super(Net, self).__init__()\n        # linear layer (784 -> 1 hidden node)\n        self.fc1 = nn.Linear(32 * 32 * 3, 512)\n        # linear layer (n_hidden -> hidden_2)\n        self.fc2 = nn.Linear(512, 256)\n        # linear layer (n_hidden -> 10)\n        self.fc3 = nn.Linear(256, 10)\n        # dropout layer (p=0.2)\n        # dropout prevents overfitting of data\n        self.dropout = nn.Dropout(0.2)\n        \n    def forward(self, x):\n        # flatten image input\n        x = x.view(-1, 32 * 32 * 3)\n        # add hidden layer, with relu activation function\n        x = F.relu(self.fc1(x))\n        # add dropout layer\n        x = self.dropout(x)\n        # add hidden layer, with relu activation function\n        x = F.relu(self.fc2(x))\n        # add dropout layer\n        x = self.dropout(x)\n        # add output layer\n        x = self.fc3(x)\n        return x","metadata":{"execution":{"iopub.status.busy":"2023-10-03T14:13:40.320209Z","iopub.execute_input":"2023-10-03T14:13:40.320507Z","iopub.status.idle":"2023-10-03T14:13:40.331602Z","shell.execute_reply.started":"2023-10-03T14:13:40.320484Z","shell.execute_reply":"2023-10-03T14:13:40.330593Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# initialize the NN\nmodel = Net()\nprint(model)","metadata":{"execution":{"iopub.status.busy":"2023-10-03T14:13:40.332962Z","iopub.execute_input":"2023-10-03T14:13:40.333383Z","iopub.status.idle":"2023-10-03T14:13:40.387191Z","shell.execute_reply.started":"2023-10-03T14:13:40.333349Z","shell.execute_reply":"2023-10-03T14:13:40.386243Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# specify loss function (categorical cross-entropy)\ncriterion = nn.CrossEntropyLoss()\n\n# specify optimizer (stochastic gradient descent) and learning rate = 0.01\noptimizer = torch.optim.SGD(model.parameters(), lr=0.01)","metadata":{"execution":{"iopub.status.busy":"2023-10-03T14:13:40.387991Z","iopub.execute_input":"2023-10-03T14:13:40.388304Z","iopub.status.idle":"2023-10-03T14:13:40.393088Z","shell.execute_reply.started":"2023-10-03T14:13:40.388276Z","shell.execute_reply":"2023-10-03T14:13:40.392330Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# TRAINING\n# number of epochs to train the model\nn_epochs = 30\ntrain_loss_min = np.Inf # track change in validation loss\n\nfor epoch in range(1, n_epochs+1):\n    # keep track of training and validation loss\n    train_loss = 0.0\n    \n    ###################\n    # train the model #\n    ###################\n    model.train()\n    for data, target in train_loader:\n        # clear the gradients of all optimized variables\n        optimizer.zero_grad()\n        # forward pass: compute predicted outputs by passing inputs to the model\n        output = model(data)\n        # calculate the loss\n        loss = criterion(output, target)\n        # backward pass: compute gradient of the loss with respect to model parameters\n        loss.backward()\n        # perform a single optimization step (parameter update)\n        optimizer.step()\n        # update running training loss\n        train_loss += loss.item()*data.size(0)\n        \n    # print training statistics \n    # calculate average loss over an epoch\n    train_loss = train_loss/len(train_loader.dataset)\n    \n    print('Epoch: {} \\tTraining Loss: {:.6f}'.format(\n        epoch, \n        train_loss\n        ))\n    \n    # save model if validation loss has decreased\n    if train_loss <= train_loss_min:\n        print('Training loss decreased ({:.6f} --> {:.6f}).  Saving model ...'.format(\n        train_loss_min,\n        train_loss))\n        torch.save(model.state_dict(), 'model_cifar.pt')\n        train_loss_min = train_loss","metadata":{"execution":{"iopub.status.busy":"2023-10-03T14:13:40.393954Z","iopub.execute_input":"2023-10-03T14:13:40.394249Z","iopub.status.idle":"2023-10-03T14:19:05.540490Z","shell.execute_reply.started":"2023-10-03T14:13:40.394225Z","shell.execute_reply":"2023-10-03T14:19:05.539110Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load model\nmodel.load_state_dict(torch.load('model_cifar.pt'))","metadata":{"execution":{"iopub.status.busy":"2023-10-03T14:19:05.543924Z","iopub.execute_input":"2023-10-03T14:19:05.544292Z","iopub.status.idle":"2023-10-03T14:19:05.560452Z","shell.execute_reply.started":"2023-10-03T14:19:05.544258Z","shell.execute_reply":"2023-10-03T14:19:05.559105Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Prediction\n# initialize lists to monitor test loss and accuracy\nclasses = []\nmodel.eval() # prep model for evaluation\nfor data in test_loader:\n    # forward pass: compute predicted outputs by passing inputs to the model\n    output = model(data)\n    # convert output probabilities to predicted class\n    _, pred = torch.max(output, 1)    \n    # append batch of predictions\n    classes.extend(pred.cpu().numpy())\n\n# Submission\n# create submission DataFrame\nsubmission_df = pd.DataFrame({'id':test_img_ids, 'label':classes})\n# save submission DataFrame to csv\nsubmission_df.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2023-10-03T14:19:05.561695Z","iopub.execute_input":"2023-10-03T14:19:05.562003Z","iopub.status.idle":"2023-10-03T14:19:05.678700Z","shell.execute_reply.started":"2023-10-03T14:19:05.561978Z","shell.execute_reply":"2023-10-03T14:19:05.677483Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check train accuracy\n# initialize lists to monitor test loss and accuracy\nclasses = []\nmodel.eval() # prep model for evaluation\nfor data, target in train_loader:\n    # forward pass: compute predicted outputs by passing inputs to the model\n    output = model(data)\n    # convert output probabilities to predicted class\n    _, pred = torch.max(output, 1)    \n    # append batch of predictions\n    classes.extend(pred.cpu().numpy())\n\n# Check train accuracy\nfrom sklearn.metrics import accuracy_score\naccuracy_score(y_train, classes)","metadata":{"execution":{"iopub.status.busy":"2023-10-03T14:19:05.680797Z","iopub.execute_input":"2023-10-03T14:19:05.681519Z","iopub.status.idle":"2023-10-03T14:19:13.083991Z","shell.execute_reply.started":"2023-10-03T14:19:05.681473Z","shell.execute_reply":"2023-10-03T14:19:13.082883Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}