{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"import glob \nimport zipfile\nimport numpy as np\nimport cv2\nimport os\nimport time\n\nfrom tqdm import tqdm\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\n\nimport pandas as pd\nfrom sklearn.model_selection import train_test_split\n\n\ndata_root_path = ''\ntest_path = data_root_path + 'data/test1'\ntrain_path = data_root_path + 'data/train'\n\ndef unzip_files():\n    zip_files = glob.glob(data_root_path + '/kaggle/input/*/*.zip')\n    for zip_file in zip_files:\n        with zipfile.ZipFile(zip_file, 'r') as zf:\n            zf.extractall(data_root_path + \"data\")\n\n\nIMAGE_SIZE = (50, 50)\ntrain_data = []\n\ndef make_training_data():\n    unzip_files()\n    LABELS = {'cat': 0, 'dog': 1}\n    for f in os.listdir(train_path):\n        path = os.path.join(train_path, f)\n        if(\"jpg\" not in f):\n            continue\n        img=cv2.imread(path, cv2.IMREAD_GRAYSCALE)\n        img=cv2.resize(img, IMAGE_SIZE)\n        train_data.append([img, np.eye(len(LABELS))[LABELS[f.split('.')[0]]]])\n    \n    np.random.shuffle(train_data)\n    np.save(data_root_path + \"train_data.npy\", train_data)\n\nif(os.path.exists(data_root_path + \"train_data.npy\")):\n    train_data = np.load(data_root_path + \"train_data.npy\", allow_pickle=True)\nelse:\n    make_training_data()\n\n\nnp.random.shuffle(train_data)\nprint(train_data[0])\n\nclass Net(nn.Module):\n    def __init__(self):\n        super().__init__() \n        self.conv1 = nn.Conv2d(1, 32, 5) \n        self.conv2 = nn.Conv2d(32, 64, 5) \n        self.conv3 = nn.Conv2d(64, 128, 5)\n        \n        self.fc1 = torch.nn.Linear(2*2*128, 32)\n        self.fc2 = torch.nn.Linear(32, 2) \n        \n        self.max_pool = torch.nn.MaxPool2d(kernel_size=2, stride=2)\n        \n    def forward(self, x):\n        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))\n        x = F.max_pool2d(F.relu(self.conv2(x)), (2, 2))\n        x = F.max_pool2d(F.relu(self.conv3(x)), (2, 2))\n        \n        x = F.relu(self.fc1(x.view(-1, 128*2*2)))\n        x = self.fc2(x) # bc this is our output layer. No activation here.\n        return F.softmax(x, dim=1)\n\nif torch.cuda.is_available():\n    device = torch.device(\"cuda:0\")  # you can continue going on here, like cuda:1 cuda:2....etc. \n    print(\"Running on the GPU\")\nelse:\n    device = torch.device(\"cpu\")\n    print(\"Running on the CPU\")\n    \nnet = Net().to(device)\n\nall_X = torch.Tensor([i[0] for i in train_data]).view(-1,50,50)\nall_X = all_X/255.0\nall_y = torch.Tensor([i[1] for i in train_data])\n\nX_train, X_test, y_train, y_test = train_test_split(all_X, all_y, test_size=0.1, stratify=all_y)\n\ndef run(X, y, is_training=True):\n    \n    optimizer = optim.Adam(net.parameters(), lr=0.001)\n    loss_function = nn.MSELoss()\n    \n    if is_training:\n        net.zero_grad()\n        optimizer.zero_grad()\n        \n    outputs = net(X)\n    matches  = [torch.argmax(i)==torch.argmax(j) for i, j in zip(outputs, y)]\n    acc = matches.count(True)/len(matches)\n    loss = loss_function(outputs, y)\n\n    if is_training:\n        loss.backward()\n        optimizer.step()\n\n    return acc, loss\n\ndef batch_and_run(X, y, is_training=True):\n    BATCH_SIZE = 64\n    for i in tqdm(range(0, len(X), BATCH_SIZE)): \n        batch_X = X[i:i+BATCH_SIZE].view(-1, 1, 50, 50).to(device)\n        batch_y = y[i:i+BATCH_SIZE].to(device)\n            \n        return run(batch_X, batch_y, is_training)\n        \ndef train(net):\n    EPOCHS = 20  \n    for epoch in range(EPOCHS):\n        acc, loss = batch_and_run(X_train, y_train, True)\n        val_acc, val_loss = batch_and_run(X_test, y_test, False)\n        print(f\"Epoch: {epoch}, {round(time.time(),3)},{round(float(acc),2)},{round(float(loss), 4)},{round(float(val_acc),2)},{round(float(val_loss),4)}\\n\")\n        \ntrain(net)\n\n\npredictions=[]\nid_line=[]\ndef test(net):\n    for f in os.listdir(test_path):\n        id_line.append(f.split('.')[0])\n        path = os.path.join(test_path, f)\n        img=cv2.imread(path, cv2.IMREAD_GRAYSCALE)\n        img=cv2.resize(img, (50, 50))\n        test_X = torch.Tensor(img).view(-1, 1, 50, 50)\n        test_X = test_X.to(device)\n        net_out = net(test_X)\n        \n        predictions.append(torch.argmax(net_out))\n\ntest(net)\n\npredicted_val = [x.tolist() for x in predictions]\nsubmission_df = pd.DataFrame({'id':id_line, 'label':predicted_val})\nsubmission_df.to_csv(\"submiss.csv\", index=False)","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}