{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":3004,"databundleVersionId":861823,"sourceType":"competition"}],"dockerImageVersionId":30648,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"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\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":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-input":false,"execution":{"iopub.status.busy":"2024-02-05T18:38:56.966173Z","iopub.execute_input":"2024-02-05T18:38:56.966628Z","iopub.status.idle":"2024-02-05T18:38:56.975422Z","shell.execute_reply.started":"2024-02-05T18:38:56.966596Z","shell.execute_reply":"2024-02-05T18:38:56.974335Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import models, transforms\nfrom tqdm.notebook import tqdm","metadata":{"execution":{"iopub.status.busy":"2024-02-05T21:56:16.492678Z","iopub.execute_input":"2024-02-05T21:56:16.493043Z","iopub.status.idle":"2024-02-05T21:56:16.498665Z","shell.execute_reply.started":"2024-02-05T21:56:16.493016Z","shell.execute_reply":"2024-02-05T21:56:16.497722Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Observe the dataset\n\ntrain_csv = '/kaggle/input/digit-recognizer/train.csv'\ntest_csv = '/kaggle/input/digit-recognizer/test.csv'\nsample_csv = '/kaggle/input/digit-recognizer/sample_submission.csv'\n\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n\ndef read_as_tensor(dir):\n    df = pd.read_csv(dir)\n    data = np.array(df)\n    data = torch.tensor(data)\n    return data\n\ntrain_data = read_as_tensor(train_csv).to(device)\ntest_data = read_as_tensor(test_csv).to(device)\nprint('train_data.shape: ', train_data.shape) # torch.Size([42000, 785])\nprint('test_data.shape: ', test_data.shape) # torch.Size([28000, 784])","metadata":{"execution":{"iopub.status.busy":"2024-02-05T21:56:16.627470Z","iopub.execute_input":"2024-02-05T21:56:16.627731Z","iopub.status.idle":"2024-02-05T21:56:21.065756Z","shell.execute_reply.started":"2024-02-05T21:56:16.627709Z","shell.execute_reply":"2024-02-05T21:56:21.064819Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class myDataset(Dataset):\n    \n    def __init__(self, data, split='train'):\n        self.photo_size = 28\n        self.split = split\n        \n        if split == 'train':\n            x = data[:, 1:]\n            x = x.reshape(-1, self.photo_size, self.photo_size).type(torch.float32)\n            y = data[:, 0]\n            \n            self.x = x\n            self.y = y\n            \n            # Is the RandomHorizontalFlip reasonable?\n            self.trans = transforms.Compose([transforms.ToPILImage(), transforms.RandomHorizontalFlip(), transforms.ToTensor()])\n            \n        elif split == 'test':\n            x = data.reshape(-1, self.photo_size, self.photo_size).type(torch.float32)\n            \n            self.x = x\n            \n            self.trans = transforms.Compose([transforms.ToPILImage(), transforms.ToTensor()])\n        else:\n            print('ERROR: Unknown split type in myDataset init.')\n            exit()\n            \n    def __len__(self):\n        return self.x.shape[0]\n    \n    def __getitem__(self, idx):\n        if(self.split == 'train'):\n            return self.trans(self.x[idx]), self.y[idx]\n        else:\n            return self.trans(self.x[idx])","metadata":{"execution":{"iopub.status.busy":"2024-02-05T21:56:21.067265Z","iopub.execute_input":"2024-02-05T21:56:21.067558Z","iopub.status.idle":"2024-02-05T21:56:21.077113Z","shell.execute_reply.started":"2024-02-05T21:56:21.067533Z","shell.execute_reply":"2024-02-05T21:56:21.076279Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class myModel(nn.Module):\n    def __init__(self):\n        super().__init__()\n\n        self.cnn = nn.Sequential(\n            nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1),\n            nn.BatchNorm2d(32),\n            nn.ReLU(inplace=True),\n            nn.Conv2d(32, 32, kernel_size=3, stride=1, padding=1),\n            nn.BatchNorm2d(32),\n            nn.ReLU(inplace=True),\n            nn.MaxPool2d(kernel_size=2, stride=2),\n\n            nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),\n            nn.BatchNorm2d(64),\n            nn.ReLU(inplace=True),\n            nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1),\n            nn.BatchNorm2d(64),\n            nn.ReLU(inplace=True),\n            nn.MaxPool2d(kernel_size=2, stride=2),\n        )\n\n        self.classifier = nn.Sequential(\n            nn.Dropout(p=0.5),\n            nn.Linear(64 * 7 * 7, 512),\n            nn.BatchNorm1d(512),\n            nn.ReLU(inplace=True),\n\n            nn.Dropout(p=0.5),\n            nn.Linear(512, 512),\n            nn.BatchNorm1d(512),\n            nn.ReLU(inplace=True),\n\n            nn.Dropout(p=0.5),\n            nn.Linear(512, 10),\n        )\n    \n    def forward(self, x):\n        x = self.cnn(x)\n        x = x.reshape(x.shape[0], -1)\n        x = self.classifier(x)\n        return x\n    \n    def loss(self, x, y):\n        return nn.CrossEntropyLoss()(x, y)","metadata":{"execution":{"iopub.status.busy":"2024-02-05T21:56:21.078215Z","iopub.execute_input":"2024-02-05T21:56:21.078481Z","iopub.status.idle":"2024-02-05T21:56:21.089907Z","shell.execute_reply.started":"2024-02-05T21:56:21.078457Z","shell.execute_reply":"2024-02-05T21:56:21.089027Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train(model, optimizer, x, y):\n    model.train()\n    optimizer.zero_grad()\n    output = model(x)\n    loss = model.loss(output, y)\n    loss.backward()\n    optimizer.step()\n    _, pre_y = output.max(dim=1)\n    return loss.item(), pre_y\n\ndef test(model, x):\n    model.eval()\n    with torch.no_grad():\n        output = model(x)\n        \n        \ndef main():\n    \n    # Hyperparameter\n\n    train_bs = 32\n    test_bs = 1\n    lr = 0.001\n    momentum = 0.9\n    epoch = 10\n    \n    seed = 0\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed_all(seed)\n    \n    device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n    \n    \n    # Data process\n    train_dataset = myDataset(train_data, split='train')\n    test_dataset = myDataset(test_data, split='test')\n    \n    train_dataloader = DataLoader(train_dataset, batch_size=train_bs, shuffle=True)\n    test_dataloader = DataLoader(test_dataset, batch_size=test_bs)\n    \n    \n    # Model\n    \n    model = myModel()\n    model = model.to(device)\n    optimizer = optim.SGD(params=model.parameters(), lr=lr, momentum=momentum)\n    \n    # Train\n    for i in range(1, epoch+1):\n        epoch_loss = 0\n        correct_cnt = 0\n        print('Training Epoch {} :'.format(i))\n        for j, (x, y) in enumerate(tqdm(train_dataloader)):\n            x = x.to(device)\n            y = y.to(device)\n            loss, pre_y = train(model, optimizer, x, y)\n            epoch_loss += loss\n            correct_cnt += torch.sum(pre_y == y)\n        print('Epoch: {}, Loss: {:.4f}, Acc: {:.4f}%'.format(i, loss, correct_cnt*100/len(train_dataset)))\n        \n    # Test\n    model.eval()\n    with torch.no_grad():\n        ans = torch.Tensor().to(device)\n        print(\"Test Processing: \")\n        for i, x in enumerate(tqdm(test_dataloader)):\n            x = x.to(device)\n            _, pre_y = model(x).max(dim=1)\n            ans = torch.cat((ans, pre_y), dim=0)\n        print(ans)\n    \n    # Output\n    submission_df = pd.read_csv(sample_csv)\n    submission_df['Label'] = ans.type(torch.int32).to('cpu').numpy().squeeze()\n    submission_df.to_csv('submission.csv', index=False)\n            \nif __name__ == '__main__':\n    main()","metadata":{"execution":{"iopub.status.busy":"2024-02-05T21:57:28.302321Z","iopub.execute_input":"2024-02-05T21:57:28.302673Z","iopub.status.idle":"2024-02-05T21:58:08.722332Z","shell.execute_reply.started":"2024-02-05T21:57:28.302644Z","shell.execute_reply":"2024-02-05T21:58:08.721353Z"},"trusted":true},"execution_count":null,"outputs":[]}]}