{"cells":[{"metadata":{"_cell_guid":"aa34e0e0-f27a-4fc7-9495-100876a93bda","_uuid":"f2865fe191046e3c72fee3542e49c229f8a2d0ca"},"cell_type":"markdown","source":"## Visualize a Convolutional Neural Network\nThis kernel is used for demonstrating the visualization of layers in a Convolutional Neural Network, which uses data from the Digit Recognizer. For kernel that actually solves the problem on the Digit Recognizer, feel free to check out my another kernel, [Fast and Easy CNN for starters in Keras 0.99471\n](https://www.kaggle.com/codeastar/fast-and-easy-cnn-for-starters-in-keras-0-99471) .\n\nYou can also check out my [blog](http://www.codeastar.com/visualize-convolutional-neural-network/) for more details on the related topic.\n","outputs":[],"execution_count":null},{"metadata":{"_cell_guid":"60e51602-348d-4ab7-9a2a-8100ac629d14","collapsed":true,"_uuid":"5247e10ba3f9c8431aed0dff66f980793db1d271","trusted":true},"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"9a39cc5e-be61-4ba7-a531-3d4584d8452e","collapsed":true,"_uuid":"b16cb3955ca33fb7373305139ecac57419821e8a","trusted":true},"cell_type":"code","source":"#load the traing and testing datasets\ndf_train = pd.read_csv('../input/train.csv')\ndf_test = pd.read_csv('../input/test.csv')","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"8cace43f-7c6c-4aab-abec-f0523d69a1f0","_uuid":"0bfecd5fa65268f080bb5418f85542496069a858","trusted":true},"cell_type":"code","source":"#import required modules\nfrom keras.models import Sequential\nfrom keras.layers import Dense, Dropout, Flatten\nfrom keras.layers.convolutional import Conv2D, MaxPooling2D\nfrom keras.utils import np_utils\nfrom keras.optimizers import RMSprop\nfrom keras.callbacks import ReduceLROnPlateau\nimport matplotlib.pyplot as plt\nfrom random import randrange","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"11aa04b3-cffe-4e04-be3b-555bcb0cc843","collapsed":true,"_uuid":"99cabdade358676287ae2a5abb33cda92d21dd8f","trusted":true},"cell_type":"code","source":"#define our CNN model\ndef cnn_model(result_class_size):\n    model = Sequential()\n    model.add(Conv2D(30, (5, 5), input_shape=(28,28,1), activation='relu'))\n    model.add(MaxPooling2D(pool_size=(2, 2)))\n    model.add(Conv2D(15, (3, 3), activation='relu'))\n    model.add(Dropout(0.2))\n    model.add(Flatten())\n    model.add(Dense(128, activation='relu'))\n    model.add(Dense(50, activation='relu'))\n    model.add(Dense(result_class_size, activation='softmax'))   \n    model.compile(loss='categorical_crossentropy', optimizer=RMSprop(), metrics=['accuracy'])\n    return model","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"71d0ffa7-703a-4c5d-84ff-4f47c459ed71","_uuid":"241a196d82fa838ecbe3bf3241dc08e3dae3780f"},"cell_type":"markdown","source":"Prepare the training materials and start to train our CNN model.","outputs":[],"execution_count":null},{"metadata":{"_cell_guid":"ffe9055e-8c4c-4694-90b3-7d650e09cdb6","collapsed":true,"_uuid":"c89760b3c37dab6be3f75f60663d8c9a1bf3706c","trusted":true},"cell_type":"code","source":"df_train_x = df_train.iloc[:,1:]  #get 784 pixel value columns after the first column\ndf_train_y = df_train.iloc[:,:1]  #get the lable column","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"fe49a50d-7ee2-42e1-9e93-7d64ffa7e647","_uuid":"0513d7bf335c0b15b12aae57d3dcece762bc980d","trusted":true},"cell_type":"code","source":"arr_train_y = np_utils.to_categorical(df_train_y['label'].values)\nmodel = cnn_model(arr_train_y.shape[1])\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"50b80e9b-0687-43be-886d-1c00858c159d","collapsed":true,"_uuid":"88d49bc313b169bf13e0c7f46fd33664ae44bad4","trusted":true},"cell_type":"code","source":"df_train_x = df_train_x / 255\ndf_test = df_test / 255\n \n#reshape training X and texting X to (number, height, width, channel)\narr_train_x_28x28 = np.reshape(df_train_x.values, (df_train_x.values.shape[0], 28, 28, 1))","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"905f049a-fdb3-47e6-97a6-a626aaa5661b","_uuid":"c5e2b10de1786255c03a6dc9364793a216311b3b","scrolled":true,"trusted":true},"cell_type":"code","source":"#train only 3 epochs for demo purpose\nmodel.fit(arr_train_x_28x28, arr_train_y, epochs=3, batch_size=100)","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"cfb16471-51bc-499d-ae51-369531973022","_uuid":"a9d3355abdd8f64d1958968e4dc0defc10dbcf05"},"cell_type":"markdown","source":"How does our trained CNN see the world? By using following filters: ","outputs":[],"execution_count":null},{"metadata":{"_cell_guid":"5c929b91-ba39-4c4f-a31e-adf486c13a7c","_uuid":"aecb2a653643e650ff7ab9122f21a0e9b40661d7","trusted":true},"cell_type":"code","source":"#get_weights [x, y, channel, nth convolutions layer ]\nweight_conv2d_1 = model.layers[0].get_weights()[0][:,:,0,:]\n\ncol_size = 6\nrow_size = 5\nfilter_index = 0\nfig, ax = plt.subplots(row_size, col_size, figsize=(12,8))\nfor row in range(0,row_size): \n  for col in range(0,col_size):\n    ax[row][col].imshow(weight_conv2d_1[:,:,filter_index],cmap=\"gray\")\n    filter_index += 1","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"46ff8fa3-9453-411f-ae8e-1c4a5a8e5c4b","_uuid":"ee16a1cccf622d92a2937e26da4010de9aadff6a"},"cell_type":"markdown","source":"We pick an image from the testing dataset. ","outputs":[],"execution_count":null},{"metadata":{"_cell_guid":"f8604fdb-7729-4b17-8aa5-47c8240f863c","_uuid":"9e8610b2e9c99ea2bd8cd5f00e07d745a22b0c4c","trusted":true},"cell_type":"code","source":"test_index = randrange(df_test.shape[0])\ntest_img = arr_train_x_28x28[test_index]\nplt.imshow(test_img.reshape(28,28), cmap='gray')\nplt.title(\"Index:[{}]\".format(test_index))\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"571e7f91-c177-4a24-b2d3-0ff6eb3a39be","_uuid":"6afd62e326cc6fd72a5040f8455ac236ff402a98"},"cell_type":"markdown","source":"Then let our trained CNN recognize the image and get the outputs from each layer.","outputs":[],"execution_count":null},{"metadata":{"_cell_guid":"3ac54052-69fb-44a5-9b50-7bee50b5b39f","collapsed":true,"_uuid":"750dbbc9a9c00d654d4d31296688cd9bfe4883a3","trusted":true},"cell_type":"code","source":"from keras.models import Model\nlayer_outputs = [layer.output for layer in model.layers]\nactivation_model = Model(inputs=model.input, outputs=layer_outputs)\nactivations = activation_model.predict(test_img.reshape(1,28,28,1))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"578fb397a5f9833245521c1a2ffe99817231f96d"},"cell_type":"markdown","source":"Let's write a function to display outputs in defined size and layer. ","outputs":[],"execution_count":null},{"metadata":{"_cell_guid":"56c9112d-cab8-47cc-8c13-49da5efc0477","collapsed":true,"_uuid":"c5015f0ff7574199708c2aa92c77ca0f9edf933e","trusted":true},"cell_type":"code","source":"def display_activation(activations, col_size, row_size, act_index): \n    activation = activations[act_index]\n    activation_index=0\n    fig, ax = plt.subplots(row_size, col_size, figsize=(row_size*2.5,col_size*1.5))\n    for row in range(0,row_size): \n      for col in range(0,col_size):\n        ax[row][col].imshow(activation[0, :, :, activation_index], cmap='gray')\n        activation_index += 1","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"4c66cdd8-53d6-4990-a8cf-272bd8e92409","collapsed":true,"_uuid":"483428704f9ea63f6bd9ac03680e154e57a69405","trusted":false},"cell_type":"markdown","source":"First, we visualize the first convolutional layer with 30 filters.","outputs":[],"execution_count":null},{"metadata":{"_cell_guid":"a8b3d865-30a8-482b-beed-d6a0a120d0cb","_uuid":"846b0ab83603b51cc2b224c3d88c302e713e3a1c","trusted":true},"cell_type":"code","source":"#conv2d_1\ndisplay_activation(activations, 6, 5, 0)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"eea28a56e23a1f8f29277010c0c6db515b541156"},"cell_type":"markdown","source":"Then the pooling layer.","outputs":[],"execution_count":null},{"metadata":{"_cell_guid":"a7b7de2d-a5d6-4663-9c90-d84f1da0f12e","_uuid":"ba024e2f60c5b70b55556bbd9655ab74f6c5e9a1","trusted":true},"cell_type":"code","source":"#max_pooling2d_1\ndisplay_activation(activations, 6, 5, 1)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"e79f16ec1933e7e7473262ca1415a20f08f0aab2"},"cell_type":"markdown","source":"And our second convolutional layer with 15 filters.","outputs":[],"execution_count":null},{"metadata":{"_cell_guid":"59721c4c-bca9-488c-bfb6-0faf57aa49b1","_uuid":"1a5161802b4a68e2ccd69a8b9680add78ebd6556","trusted":true},"cell_type":"code","source":"#conv2d_2\ndisplay_activation(activations, 5, 3, 2)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"6c567fdf5a209b4a872c2dbce92b819fa4964739"},"cell_type":"markdown","source":"We have a dropout layer which its dropping rate is set to 25% of inputs. ","outputs":[],"execution_count":null},{"metadata":{"_cell_guid":"8e208904-fd11-4359-918d-893b69bdcfe6","_uuid":"1104adfcf49e32184d50c721261b8849b0d6c6ab","trusted":true},"cell_type":"code","source":"#dropout_1\ndisplay_activation(activations, 5, 3, 3)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"de2896433d189f0a0640ef314872016abb214331"},"cell_type":"markdown","source":"Finally, we get the outputs from the last fully connected layer.","outputs":[],"execution_count":null},{"metadata":{"_cell_guid":"7565651e-7d94-4fb1-aa3b-79433c6f4c30","_uuid":"159c79cfef08fda4dfd99b547cac0d20689499bd","trusted":true},"cell_type":"code","source":"act_dense_3  = activations[7]\nact_dense_3","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"f2226bdd-8769-490b-9214-281d832e862e","_uuid":"5be80bfcdf3231261123d1df66bff90604049493","trusted":true},"cell_type":"code","source":"y = act_dense_3[0]\nx = range(len(y))\nplt.xticks(x)\nplt.bar(x, y)\nplt.show()","execution_count":null,"outputs":[]}],"metadata":{"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"}},"nbformat":4,"nbformat_minor":1}