{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"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)\nimport os\nimport cv2\nimport numpy as np\nfrom tqdm import tqdm\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\n\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 5GB 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","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import shutil\nimport zipfile\nif(os.path.isdir('/kaggle/working/train/')):\n    shutil.rmtree('/kaggle/working/train/')\n    shutil.rmtree('/kaggle/working/test1/')\n    os.remove('training_data.npy')\n    os.remove('model.log')\nelse:\n    with zipfile.ZipFile(\"/kaggle/input/dogs-vs-cats/train.zip\",\"r\") as z:\n        z.extractall(\".\")\n    os.makedirs('/kaggle/working/train/cat')\n    os.makedirs('/kaggle/working/train/dog')\n    for dir in os.listdir('/kaggle/working/train'):\n        dataDir = '/kaggle/working/train/'+dir\n        if(\"cat\" in dataDir):\n            shutil.move(dataDir, \"/kaggle/working/train/cat\")\n        else:\n            shutil.move(dataDir, \"/kaggle/working/train/dog\")    \n    with zipfile.ZipFile(\"/kaggle/input/dogs-vs-cats/test1.zip\",\"r\") as z:\n        z.extractall(\".\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"REBUILD_DATA = True\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    \nclass DogsVSCats():\n    IMG_SIZE = 50\n    CATS = \"/kaggle/working/train/cat\"\n    DOGS = \"/kaggle/working/train/dog\"\n    TESTING = \"/kaggle/working/train/test1\"\n    LABELS = {CATS: 0, DOGS: 1}\n    training_data = []\n    catcount = 0\n    dogcount = 0\n\n    def make_training_data(self):\n        for label in self.LABELS:\n            print(label)\n            for f in tqdm(os.listdir(label)):\n                if \"jpg\" in f:\n                    try:\n                        path = os.path.join(label, f)\n                        img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)\n                        img = cv2.resize(img, (self.IMG_SIZE, self.IMG_SIZE))\n                        self.training_data.append([np.array(img), np.eye(2)[self.LABELS[label]]])  # do something like print(np.eye(2)[1]), just makes one_hot \n                        #print(np.eye(2)[self.LABELS[label]])\n\n                        if label == self.CATS:\n                            self.catcount += 1\n                        elif label == self.DOGS:\n                            self.dogcount += 1\n\n                    except Exception as e:\n                        pass\n                        #print(label, f, str(e))\n\n        np.random.shuffle(self.training_data)\n        np.save(\"training_data.npy\", self.training_data)\n        print('Cats:',dogsvcats.catcount)\n        print('Dogs:',dogsvcats.dogcount)\n\nclass Net(nn.Module):\n    def __init__(self):\n        super().__init__() # just run the init of parent class (nn.Module)\n        self.conv1 = nn.Conv2d(1, 32, 5) # input is 1 image, 32 output channels, 5x5 kernel / window\n        self.conv2 = nn.Conv2d(32, 64, 5) # input is 32, bc the first layer output 32. Then we say the output will be 64 channels, 5x5 kernel / window\n        self.conv3 = nn.Conv2d(64, 128, 5)\n\n        x = torch.randn(50,50).view(-1,1,50,50)\n        self._to_linear = None\n        self.convs(x)\n\n        self.fc1 = nn.Linear(self._to_linear, 512) #flattening.\n        self.fc2 = nn.Linear(512, 2) # 512 in, 2 out bc we're doing 2 classes (dog vs cat).\n\n    def convs(self, x):\n        # max pooling over 2x2\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        if self._to_linear is None:\n            self._to_linear = x[0].shape[0]*x[0].shape[1]*x[0].shape[2]\n        return x\n\n    def forward(self, x):\n        x = self.convs(x)\n        x = x.view(-1, self._to_linear)  # .view is reshape ... this flattens X before \n        x = F.relu(self.fc1(x))\n        x = self.fc2(x) # bc this is our output layer. No activation here.\n        return F.softmax(x, dim=1)\n        \n        \nif REBUILD_DATA:\n    dogsvcats = DogsVSCats()\n    dogsvcats.make_training_data()\n\nnet = Net().to(device)\nprint(net)\n\ntraining_data = np.load(\"training_data.npy\", allow_pickle=True)\nprint(len(training_data))\n    \nX = torch.Tensor([i[0] for i in training_data]).view(-1,50,50)\nX = X/255.0\ny = torch.Tensor([i[1] for i in training_data])\n    \nVAL_PCT = 0.1  \nval_size = int(len(X)*VAL_PCT)\n\ntrain_X = X[:-val_size]\ntrain_y = y[:-val_size]\n\ntest_X = X[-val_size:]\ntest_y = y[-val_size:] ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"optimizer = optim.Adam(net.parameters(), lr=0.001)\nloss_function = nn.MSELoss()\ndef fwd_pass(X, y, train=False):\n    if train:\n        net.zero_grad()\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 train:\n        loss.backward()\n        optimizer.step()\n\n    return acc, loss\n\ndef test(size=32):\n    random_start = np.random.randint(len(test_X) - size)\n    X, y = test_X[random_start:random_start+size], test_y[random_start:random_start+size]\n    with torch.no_grad():\n        val_acc, val_loss = fwd_pass(X.view(-1,1,50,50).to(device), y.to(device))\n    return val_acc, val_loss\n\nval_acc, val_loss = test(size=1000)\nprint(val_acc, val_loss)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import time\n\nMODEL_NAME = f\"model-{int(time.time())}\"  # gives a dynamic model name, to just help with things getting messy over time. \nnet = Net().to(device)\noptimizer = optim.Adam(net.parameters(), lr=0.001)\nloss_function = nn.MSELoss()\n\ndef train(net):\n    BATCH_SIZE = 100\n    EPOCHS = 8\n\n    with open(\"model.log\", \"a\") as f:\n        for epoch in range(EPOCHS):\n            for i in tqdm(range(0, len(train_X), BATCH_SIZE)):\n                batch_X = train_X[i:i+BATCH_SIZE].view(-1,1,50,50)\n                batch_y = train_y[i:i+BATCH_SIZE]\n\n                batch_X, batch_y = batch_X.to(device), batch_y.to(device)\n\n                acc, loss = fwd_pass(batch_X, batch_y, train=True)\n                \n                if i % 10 == 0:\n                    val_acc, val_loss = test(size=100)\n                    f.write(f\"{MODEL_NAME},{round(time.time(),3)},{round(float(acc),2)},{round(float(loss), 4)},{round(float(val_acc),2)},{round(float(val_loss),4)}\\n\")\ntrain(net)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","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}