{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Recognize handwritten digit using CNN\n\n## import useful package","execution_count":null},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"%matplotlib inline\nimport numpy as np \nimport pandas as pd\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport torch\nfrom torchvision import datasets, transforms\nfrom sklearn.model_selection import train_test_split\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\nimport os\n\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Explore Data","execution_count":null},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"df = pd.read_csv('/kaggle/input/digit-recognizer/train.csv')\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"As we can see our data set has 785 columns where first columns contain label of image and rest columns contain the pixel value of 28*28 image which are in range(0,255).\n\nExplore some more detail....","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"df.describe()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Visulize the Dataset\n\nThe first step in a classification task is to take a look at the data, make sure it is loaded in correctly, then make any initial observations about patterns in that data.\n\n\nLet's check the distribution of data accross all labels.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"label = [i for i in range(10)]\nheight = [df['label'].value_counts()[i] for i in range(10)]\nplt.bar(label,height,color = 'r')\nplt.xticks(label);","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Now we see some sample image of handwritten digit.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"idx = np.random.randint(1,42000,20)\nfig = plt.figure(figsize=(25, 4))\nimg = df.loc[idx,df.columns != 'label'].values.reshape(-1,28,28)\nlabel = df.loc[idx,'label'].values\nfor i in np.arange(20):\n    ax = fig.add_subplot(2, 20/2, i+1, xticks=[], yticks=[])\n    ax.imshow(np.squeeze(img[i]), cmap='gray')\n    ax.set_title(str(label[i]))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## View an image in more detail","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"img = df.loc[50,df.columns != 'label'].values.reshape(28,28)\nfig = plt.figure(figsize = (12,12))\nax = fig.add_subplot(111)\nax.imshow(img, cmap = 'Greys_r')\nplt.title(df.loc[50,'label'])\nplt.xticks([])\nplt.yticks([]);\nthresh = img.max()/2.5\nheight = width = 28\nfor x in range(width):\n    for y in range(height):\n        val = round(img[x][y],2) if img[x][y] !=0 else 0\n        ax.annotate(str(val), xy=(y,x),\n                    horizontalalignment='center',\n                    verticalalignment='center',\n                    color='white' if img[x][y]<thresh else 'black')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Load dataset for training and Validation\n\nwe split our train data in two parts for training and validation and then build data loaders.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"X = torch.from_numpy(df.loc[:,df.columns != 'label'].values/255)#scaling\nX = X.reshape(42000,1,28,28)\n\ny = torch.from_numpy(df.label.values).type(torch.LongTensor)\n\n\nX_train,X_val,y_train,y_val = train_test_split(X,y,test_size = .05)\n\ntrainset = torch.utils.data.TensorDataset(X_train,y_train)\ntrainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)\n\nvalset = torch.utils.data.TensorDataset(X_val,y_val)\nvalloader = torch.utils.data.DataLoader(valset,batch_size = 64,shuffle = True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Define Network\n\nWe create a CNN architecture which have 2 conv2d layers and 2 fully connected layers.\n\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"class Net(nn.Module):\n    def __init__(self):\n        super(Net, self).__init__()\n        self.conv1 = nn.Conv2d(1, 10, kernel_size=5)\n        self.conv2 = nn.Conv2d(10, 20, kernel_size=5)\n        self.conv2_drop = nn.Dropout2d()\n        self.fc1 = nn.Linear(320, 50)\n        self.fc2 = nn.Linear(50, 10)\n\n    def forward(self, x):\n        x = F.relu(F.max_pool2d(self.conv1(x), 2))\n        x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))\n        x = x.view(-1, 320)\n        x = F.relu(self.fc1(x))\n        x = F.dropout(x, training=self.training)\n        x = self.fc2(x)\n        return F.log_softmax(x)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = Net()\nmodel","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Define Loss and Optimizer\n\nwe use CrossEntropyLoss() for loss calculation and SGD() for optimizer.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"criterion = torch.nn.CrossEntropyLoss()\noptimizer = optim.SGD(model.parameters(), lr=0.01)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Training Network and Saving Best","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"n_epoch = 50\nloss_min = np.Inf\nmodel = model.double()\nfor i in range(1,n_epoch+1):\n    train_loss = 0\n    valid_loss = 0\n    \n\n    model.train()\n    for data,target in trainloader: \n        optimizer.zero_grad()\n        #data = data.astype(np.double\n        out = model(data.double())\n        loss = criterion(out,target)\n        loss.backward()\n        optimizer.step()\n\n        train_loss+=loss.item()*data.size(0)\n\n    model.eval()\n    for data,target in valloader:\n        out = model(data)\n        loss = criterion(out,target)\n        valid_loss += loss.item()*data.size(0)\n\n    train_loss = train_loss/len(trainloader.sampler)\n    valid_loss = valid_loss/len(valloader.sampler)\n\n    print('Epoch: {} \\tTraining Loss: {:.6f} \\tValidation Loss: {:.6f}'.format(\n        i, train_loss, valid_loss))\n\n    if valid_loss <= loss_min:\n        print('Validation loss decreased ({:.6f} --> {:.6f}).  Saving model ...'.format(\n        loss_min,\n        valid_loss))\n        torch.save(model.state_dict(), 'model_cifar.pt')\n        loss_min = valid_loss","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Load the Best Model","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"model.load_state_dict(torch.load('/kaggle/working/model_cifar.pt'))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Let's Check Our Model ","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"img,label = next(iter(valloader))\nout = model(img)\n_,out = torch.max(out,1)\n\nfig = plt.figure(figsize=(25, 4))\nfor i in np.arange(20):\n    ax = fig.add_subplot(2, 20/2, i+1, xticks=[], yticks=[])\n    ax.imshow(np.squeeze(img[i]), cmap='gray')\n    ax.set_title(f'{label[i]}({out[i]})',color = 'g' if label[i] == out[i] else 'r')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Thanks and If Like please UPVOTE","execution_count":null}],"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}