{"cells":[{"metadata":{},"cell_type":"markdown","source":"<h1>Importar Datos</h1>","execution_count":null},{"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)\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":"#Python Imports\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import train_test_split\nimport os\n\n#PyTorch Util\nimport torch\nimport torchvision\nimport torchvision.transforms as transforms\nfrom torch.utils.data import DataLoader, TensorDataset\nfrom torchvision.utils import make_grid\n\n#PyTorch NN\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = pd.read_csv(\"/kaggle/input/digit-recognizer/train.csv\")\ntest_df = pd.read_csv(\"/kaggle/input/digit-recognizer/test.csv\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Convertir DataFrame a Numpy Array\ntrain_labels = train_df['label'].values\ntrain_images = (train_df.iloc[:,1:].values).astype('float32')\ntest_images = (test_df.iloc[:,:].values).astype('float32')\n\n#Split del train y validation set (85/15 %)\ntrain_images, val_images, train_labels, val_labels = train_test_split(train_images, train_labels,\n                                                                     stratify=train_labels,\n                                                                     test_size=0.15)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"Tamaño Train Set: \\t\",len(train_images))\nprint(\"Tamaño Validation Set: \\t\",len(val_images))\nprint(\"Tamaño Test Set: \\t\",len(test_images))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Reshape de los Array de Numpy (M, nChan, H, W)\n\n#Reshape a (35700, 1, 28,28)\ntrain_images = train_images.reshape(train_images.shape[0], 1, 28, 28)\n#Reshape a (6300, 1, 28,28)\nval_images = val_images.reshape(val_images.shape[0], 1, 28, 28) \n#Reshape a (28000, 1, 28,28)\ntest_images = test_images.reshape(test_images.shape[0], 1, 28, 28) ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h1>Dataloaders & Hiperparametros</h1>","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"#Convertir de Numpy Array a Tensors y Tensor Datasets\n\n#Pasar a Tensor y Normalizar\ntrain_images_tensor = torch.tensor(train_images)/255.0 #Normalizar\ntrain_labels_tensor = torch.tensor(train_labels)\n#Train Tensor Dataset\ntrain_tensor = TensorDataset(train_images_tensor, train_labels_tensor)\n\n#Pasar a Tensor y Normalizar\nval_images_tensor = torch.tensor(val_images)/255.0 #Normalizar\nval_labels_tensor = torch.tensor(val_labels)\n#Test Tensor Dataset\nval_tensor = TensorDataset(val_images_tensor, val_labels_tensor)\n\n#Pasar a Tensor y Normalizar\ntest_images_tensor = torch.tensor(test_images)/255.0 #Normalizar\n\n#Hiperparametros\nbatch_size = 128\nlearning_rate = 0.0005\ndropout_prob = 0.5\nweight_decay = 1e-5\nepochs = 15\n\n\ntrain_loader = DataLoader(train_tensor, batch_size=batch_size, num_workers=2, shuffle=True)\nval_loader = DataLoader(val_tensor, batch_size=batch_size, num_workers=2, shuffle=True)\ntest_loader = DataLoader(test_images_tensor, batch_size=batch_size, num_workers=2, shuffle=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h1>Arquitectura del Modelo</h1>","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"class Net(nn.Module):\n    def __init__(self):\n        super(Net, self).__init__()\n        \n        #Conv Layer 1\n        self.conv1 = nn.Conv2d(in_channels=1, out_channels=32, kernel_size=5, stride=1)\n        self.pool = nn.MaxPool2d(2, 2)\n        self.bn1 = nn.BatchNorm2d(32)\n        \n        #Conv Layer 2\n        self.conv2 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, stride=1)\n        self.bn2 = nn.BatchNorm1d(64*4*4)\n        \n        #Fully Connected 1\n        self.fc1 = nn.Linear(64*4*4, 128)\n        \n        #Fully Connected 2\n        self.fc2 = nn.Linear(128, 64)\n        \n        #Fully Connected 3 Output\n        self.fc3 = nn.Linear(64, 10)\n        \n        #Dropout\n        self.dropout = nn.Dropout(p=dropout_prob)\n\n    def forward(self, x):\n        \n        #Conv 1\n        x = self.pool(F.relu(self.conv1(x)))\n        x = self.bn1(x)\n        #Conv 2\n        x = self.pool(F.relu(self.conv2(x)))\n        x = x.view(-1, 64 * 4 * 4) #Flatten Image a dim de fc1\n        x = self.bn2(x)\n        #Fully Connected 1\n        x = self.dropout(F.relu(self.fc1(x)))\n        #Fully Connected 2\n        x = self.dropout(F.relu(self.fc2(x)))\n        #Output\n        x = self.fc3(x)\n        return x\n\n#Inicializacion Xavier a los Weights\ndef xavier_init(m):\n    if type(m) == nn.Linear:\n        torch.nn.init.xavier_uniform_(m.weight)\n        m.bias.data.fill_(0.01)\n        \n#Instanciar Modelo\nnet=Net()\nnet.apply(xavier_init)\n# Loss Function\ncriterion = nn.CrossEntropyLoss()\n# Optimizador Adam\noptimizer = optim.Adam(net.parameters(), lr=learning_rate)\nnet","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h1>Entrenamiento</h1>","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"#Listas de losses por epoch\ntrain_losses, val_losses = [], []\nfor e in range(epochs):\n    train_loss = 0\n    for images, labels in train_loader:\n\n        optimizer.zero_grad()\n        #forward prop\n        preds = net(images)\n        loss = criterion(preds, labels)\n        #back prop\n        loss.backward()\n        optimizer.step()\n\n        train_loss += loss.item()\n            \n    else:\n        #Pase de validacion/evaluacion        \n        val_loss = 0\n        correct = 0\n        total = 0\n        with torch.no_grad():\n            net.eval()\n            for images, labels in val_loader:\n                #Calcular validation loss\n                preds = net(images)\n                val_loss += criterion(preds, labels)\n                #Calcular Accuracy\n                _, predicted = torch.max(preds.data, 1)\n                total += labels.size(0)\n                correct += (predicted == labels).sum().item()\n    \n    net.train()\n    #Agregar a listas por epoch\n    train_losses.append(train_loss/len(train_loader))\n    val_losses.append(val_loss/len(val_loader))\n\n    print(\"Epoch {}/{}\".format(e+1,epochs),\n          \"Training Loss: {:.4f}\".format(train_loss/len(train_loader)),\n          \"Validation Loss: {:.4f}\".format(val_loss/len(val_loader)),\n          \"Accuracy: {:.4f}\".format(correct/total))\n\n\n#Plot Train vs Val Loss\n%matplotlib inline\n%config InlineBackend.figure_format = 'retina'\nplt.plot(train_losses, label='Training loss')\nplt.plot(val_losses, label='Validation loss')\nplt.legend(frameon=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h1>Evaluar en Test Set</h1>","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Calcular predicciones en el test_loader\n# y agregarlas en el tensor test_preds\n\ndef predictions(data_loader):\n    net.eval()\n    test_preds = torch.LongTensor()\n    \n    for i, data in enumerate(data_loader):\n            \n        output = net(data)\n        preds = output.data.max(1, keepdim=True)[1]\n        test_preds = torch.cat((test_preds, preds), dim=0)\n        \n    return test_preds\n\nts_predictions = predictions(test_loader)\n\nsubmission_df = pd.read_csv(\"/kaggle/input/digit-recognizer/sample_submission.csv\")\n\nsubmission_df['Label'] = ts_predictions.numpy().squeeze()\n\nsubmission_df.to_csv('submission.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}