{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Visualizing MNIST\n\n### 1. Imports"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\nimport torch \nimport torch.optim as optim\nfrom torch.utils.data import *\nimport torch.nn as nn","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### 2. Define data fetcher"},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_data():\n    path = '/kaggle/input/digit-recognizer/train.csv'\n    raw_data = np.loadtxt(path, skiprows = 1, delimiter = ',')\n    raw_X = raw_data[:,1:]\n    raw_Y = raw_data[:,0]\n    \n    raw_X = raw_X.reshape(-1, 1, 28, 28)\n    \n    m = raw_X.shape[0]\n    \n    train_X_lst = []\n    train_Y_lst = []\n    test_X_lst = []\n    test_Y_lst = []\n    for i in range(m):\n        if(i % 2 == 0):\n            train_X_lst.append(raw_X[i])\n            train_Y_lst.append(raw_Y[i])\n        else:\n            test_X_lst.append(raw_X[i])\n            test_Y_lst.append(raw_Y[i])\n    train_X = np.array(train_X_lst)\n    train_Y = np.array(train_Y_lst)\n    test_X = np.array(test_X_lst)\n    test_Y = np.array(test_Y_lst)\n    return train_X, train_Y, test_X, test_Y\n    ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### 3. Define Data class"},{"metadata":{"trusted":true},"cell_type":"code","source":"class Data(Dataset):\n    def __init__(self,x, y):        \n        self.x = torch.from_numpy(x).float().cuda()\n        self.y  = torch.from_numpy(y).long().cuda()\n        self.len = x.shape[0]\n    def __getitem__(self, i):\n        return (self.x[i], self.y[i])\n    def __len__(self):\n        return self.len","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### 4. Define model class"},{"metadata":{"trusted":true},"cell_type":"code","source":"class CNN(nn.Module):\n    def __init__(self):\n        super(CNN, self).__init__()\n        # The architecture used here is based on LeNet-5.\n        #28x28x1 --> 24x24x6 --> 12x12x6\n        self.conv1 = nn.Conv2d(1, 6, 5)\n        self.pool1 = nn.MaxPool2d(2, 2)\n        #12x12x6 --> 8x8x16 --> 4x4x16-->256\n        self.conv2 = nn.Conv2d(6, 16, 5)\n        self.pool2 = nn.MaxPool2d(2, 2)\n        self.flatten = nn.Flatten()\n        # 256 --> 120\n        self.linear1 = nn.Sequential(nn.Linear(256, 120), nn.ReLU())\n        # 120 -->84\n        self.linear2 = nn.Sequential(nn.Linear(120, 84), nn.ReLU())\n        # 84 -->10\n        self.linear3 = nn.Sequential(nn.Linear(84, 10), nn.Softmax())\n    def forward(self, x):\n        a1 = self.conv1(x)\n        a2 = self.pool1(a1)\n        a3 = self.conv2(a2)\n        a4 = self.pool2(a3)\n        a5 = self.flatten(a4)\n        a6 = self.linear1(a5)\n        a7 = self.linear2(a6)\n        a8 = self.linear3(a7)\n        return a8, (a1, a2, a3, a4, a5, a6, a7)\n        ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### 5. Fetch data"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_X, train_Y, test_X, test_Y = get_data()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### 6. Tune hyperparameters"},{"metadata":{"trusted":true},"cell_type":"code","source":"learning_rate = 0.0001\nbatch_size = 128\nnum_epochs = 100","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### 7. Initialize model and utils"},{"metadata":{"trusted":true},"cell_type":"code","source":"model = CNN()\nmodel.cuda()\ntrain_dset = Data(train_X, train_Y)\ntrainloader = DataLoader(train_dset, batch_size = batch_size)\ncostfn = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr = learning_rate)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### 8. Train!"},{"metadata":{"trusted":true},"cell_type":"code","source":"costs = []\naccuracies = []\nepochwise_accuracies = []\nfor epoch in range(num_epochs):\n    this_epoch_accuracies = []\n    for x, y in trainloader:\n        optimizer.zero_grad()\n        yhat, _ = model(x)\n        cost = costfn(yhat, y)\n        cost.backward()\n        optimizer.step()\n        costs.append(cost.item())\n        yhat_np = np.argmax(yhat.detach().cpu().numpy(), axis = 1)\n        y_np = y.detach().cpu().numpy()\n        accuracy = 100*(1- np.sum( (yhat_np!= y_np).astype(int))/yhat.shape[0])\n        accuracies.append(accuracy)\n        this_epoch_accuracies.append(accuracy)\n    this_epoch_accuracies = np.array(this_epoch_accuracies)\n    mean_accuracy = np.mean(this_epoch_accuracies)\n    epochwise_accuracies.append(mean_accuracy)\n    print(\"Epoch:\", epoch)\n    print(\"Accuracy = \", mean_accuracy)\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### 9. Plot costs and accuracies"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.plot(costs)\nplt.show()\nplt.plot(accuracies)\nplt.show()\nplt.plot(epochwise_accuracies)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### 10. Run model on test set"},{"metadata":{"trusted":true},"cell_type":"code","source":"test_dset = Data(test_X, test_Y)\ntestloader = DataLoader(test_dset, batch_size)\ntest_accuracies = []\nl1s, l2s, l3s, l4s, l5s, l6s, l7s = [], [], [], [], [], [], []\nfor x, y in testloader:\n    yhat, intermediates = model(x)\n    l1s.append(intermediates[0].detach().cpu().numpy())\n    l2s.append(intermediates[1].detach().cpu().numpy())\n    l3s.append(intermediates[2].detach().cpu().numpy())\n    l4s.append(intermediates[3].detach().cpu().numpy())\n    l5s.append(intermediates[4].detach().cpu().numpy())\n    l6s.append(intermediates[5].detach().cpu().numpy())\n    l7s.append(intermediates[6].detach().cpu().numpy())\n    yhat_np = np.argmax(yhat.detach().cpu().numpy(), axis = 1)\n    y_np = y.detach().cpu().numpy()\n    accuracy = 100*(1- np.sum( (yhat_np!= y_np).astype(int))/yhat.shape[0])\n    test_accuracies.append(accuracy)\ntest_accuracies = np.array(test_accuracies)\ntest_accuracy = np.mean(test_accuracies)\nprint(\"Test accuracy = \", test_accuracy)\nl1s = np.concatenate(l1s)\nl2s = np.concatenate(l2s)\nl3s = np.concatenate(l3s)\nl4s = np.concatenate(l4s)\nl5s = np.concatenate(l5s)\nl6s = np.concatenate(l6s)\nl7s = np.concatenate(l7s)\n\ny = test_Y\nx = test_X","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### 11. Visualizing the response to input"},{"metadata":{"trusted":true},"cell_type":"code","source":"index = 1\nprint(\"The displayed image is:\", y[index])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### a. The input layer"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.imshow(test_X[index][0], cmap = 'gray')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### b. The first conv layer"},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in range(l1s[index].shape[0]):\n    plt.imshow(l1s[index][i], cmap = 'gray')\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### c. The first pooling layer"},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in range(l2s[index].shape[0]):\n    plt.imshow(l2s[index][i], cmap = 'gray')\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### d. The second conv layer"},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in range(l3s[index].shape[0]):\n    plt.imshow(l3s[index][i], cmap = 'gray')\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### e. The second pooling layer"},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in range(l4s[index].shape[0]):\n    plt.imshow(l4s[index][i], cmap = 'gray')\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### f. The flattened layer"},{"metadata":{"trusted":true},"cell_type":"code","source":"to_display = l5s[index].reshape(16, 16)\nplt.imshow(to_display, cmap = 'gray')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### g. The first dense layer"},{"metadata":{"trusted":true},"cell_type":"code","source":"to_display = l6s[index].reshape(10, -1)\nplt.imshow(to_display, cmap = 'gray')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### g. The second dense layer"},{"metadata":{"trusted":true},"cell_type":"code","source":"to_display = l7s[index].reshape(7, -1)\nplt.imshow(to_display, cmap = 'gray')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### 12. Visualizing the parameters"},{"metadata":{"trusted":true},"cell_type":"code","source":"params = list(model.parameters())\nfor i in range(len(params)):\n    params[i] = params[i].detach().cpu().numpy()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### a. The first conv filter"},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in range(params[0].shape[0]):\n    plt.imshow(params[0][i][0], cmap = 'gray')\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### b. The second conv layer"},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in range(params[2].shape[0]):\n    plt.imshow(params[2][i][0], cmap = 'gray')\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### c. The first dense layer"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.imshow(params[4], cmap = 'gray')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.imshow(params[6], cmap = 'gray')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### d. The third dense layer"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.imshow(params[8], cmap = 'gray')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### e. Reinterpreting the last layer"},{"metadata":{"trusted":true},"cell_type":"code","source":"last_layer = params[8].reshape(10, 7, 12)\nfor i in range(last_layer.shape[0]):\n    plt.imshow(last_layer[i], cmap = 'gray')\n    plt.show()","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}