###### tags: `Collegue Life` `Coding-X` `AI & Machine Learning` # Practice - MNIST with CNN ## Introduction This is a class practice for CNN practicing, **learning using Keras to build a CNN model for MNIST**, with source code provided in PPT for class. Here's the model's imformation: ![](https://i.imgur.com/Uq9Jdu2.png) Codes below are rewrited by me. And I alse added more detailed comments and some of my thoughts, wish could help you if you're interested in it. Enjoy! ## Code [Github link](https://github.com/chwchao/2019-Coding-X/tree/master/MachineLearning/CNN_MNIST) 1. **Open training file** ```python=1 with open('train.csv', 'r')as file: csv_lines = file.readlines() ``` <br> 2. **Access and store the data** According to the format of MNIST data, 1st column is label, the answer of the picture in the other hand. Columns left are the pixel imformation of the picture (Gray scale - 0~255) So we store pictures and labels into different lists **Notice:** Because we're using convolition, we have to reshape the one-dimension data into the origin shape we expected, which is a picture having 28 x 28 pixcels. ```python=+ import numpy as np pic = [] label = [] for i in range(1, len(csv_lines)): row = csv_lines[i].replace('\n', '').split(',') pic.append(np.array(list(map(int, row[1:]))).reshape(28, 28, 1)) label.append(list(map(int, row[0]))) ``` <br> 3. **One-hot encoding** Because our labels are only map from 10 numbers (0~9), we can use "One-hot Encoding" to simplify the data. ```python=+ from keras.utils import to_categorical label = to_categorical(y, num_classes = 10) ``` <br> 4. **Transform into numpy.array, and also normalize** Because we know that the data of the pictures are mapped from 0~255 (gray scale), we divide them by 255 to normalize, which are re-mapped to 0~1. ```python=+ pic = np.array(pic)/255.0 label = np.array(label) print(pic.shape) print(label.shape) ``` ![](https://i.imgur.com/WDsgaoR.png) <br> 5. **Build the model** We can see it as an empty model at first, and we need to add layers one by one. >First layer: >A convolution layer, which is the only one we need to set the input shape. >Hidden layers: >Described in the imformation of the model. >Output layer: >The last one layer, its number of neurals must be same as the options we want the model come out. Take this situation for example, we will only get 0~9 total ten numbers, so the output layer must have 10 neurals. >Also, we use "Softmax" activation function to make outputs converge. ```python=+ from keras.models import Sequential from keras.layers import Dense, Dropout, Flatten from keras.layers import Conv2D, MaxPool2D # Declare a sequential model model = Sequential() # Add a convolution layer (it's the first layer, input shape is needed) model.add(Conv2D( filters=32, kernel_size=(3,3), input_shape=(28, 28, 1), activation='relu', padding='same' )) # Dropout model.add(Dropout(0.2)) # Pooling - 2*2 model.add(MaxPool2D(pool_size=(2, 2))) # Add a convolution layer model.add(Conv2D( filters=32, kernel_size=(3, 3), activation='relu', padding='same' )) # Dropout model.add(Dropout(0.2)) # Pooling - 2*2 model.add(MaxPool2D(pool_size=(2, 2))) # Add a flatten layer (transform data back to one-dimension for DNN) model.add(Flatten()) # Dropout model.add(Dropout(0.25)) # MLP model.add(Dense(1024, activation='relu')) model.add(Dropout(0.25)) model.add(Dense(10, activation='softmax')) # Print out the summary of the model print(model.summary()) ``` *relu -- Rectified Linear Unit* *softmax -- Softmax* ![](https://i.imgur.com/JzUfTzi.png) <br> 6. **Compile the model** Set imformations of the model. ```python=+ model.compile( loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'] ) ``` <br> 7. **Start training** >validation -- how much data is splited out used to validate the model's loss. accuracy... >batch_size -- how much data used in a gradient >epochs -- how many times all data is used > >verbose -- 0 : No log , 1 : Show progress bar , 2 : Log of each epochs ```python=+ history = model.fit( pic, label, validation_split=0.2, epochs=10, batch_size=128, verbose=1 ) ``` ![](https://i.imgur.com/qGUu07H.png) <br> 8. **Evaluation** Show the accuracy when training and validating on a plot. >acc -- accuracy when training >val_acc -- accuracy when validating ```python=+ import matplotlib.pyplot as plt def show_train_history(train_history): plt.plot(train_history.history['acc']) plt.plot(train_history.history['val_acc']) plt.xticks([i for i in range(0, len(train_history.history['acc']))]) plt.title('Train History') plt.ylabel('acc') plt.xlabel('epoch') plt.legend(['train', 'validation'], loc='lower right') plt.show() show_train_history(history) ``` ![](https://i.imgur.com/zlxee2K.png) <br> 9. **Confusion Matrix** ```python+= import itertools from sklearn.metrics import confusion_matrix, classification_report def plot_confusion_matrix( cm, classes, title='Confusion matrix', cmap=plt.cm.Blues ): fig = plt.figure() plt.imshow(cm, interpolation='nearest', cmap=cmap) plt.title(title) plt.colorbar() tick_marks = np.arange(len(classes)) plt.xticks(tick_marks, classes, rotation=45) plt.yticks(tick_marks, classes) thresh = cm.max() / 2. for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])): plt.text(j, i, cm[i, j],horizontalalignment="center", color="white" if cm[i, j] > thresh else "black") plt.tight_layout() plt.ylabel('True label') plt.xlabel('Predicted label') # fig.savefig(title + '.eps', format='eps', dpi=600, quality=95) # fig.savefig(title + '.png', dpi=600, quality=95) plt.show() plt.close() # Mnist label classes = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] # Predict the values from the training Y_pred = model.predict([pic]) # Convert predictions classes to one hot vectors y_pred = np.argmax(Y_pred, axis = 1) # Convert training observations to one hot vectors Y_true = np.argmax(label, axis = 1) # compute the confusion matrix confusion_mtx = confusion_matrix(Y_true, y_pred) # plot the confusion matrix plot_confusion_matrix( confusion_mtx, classes=classes, title='Confusion_matrix_train' ) ``` ![](https://i.imgur.com/AoEaX0t.png) <br> 10. **Submit the result to submit.csv** ```python=+ # The format of the output, also the title of the form submit='ImageId,Lable\n' # Open the testing file with open('test.csv', 'r')as file: csv_lines = file.readlines() # Count for row image_id = 1 for i in range(1, len(csv_lines)): # delete '\n', and split by ',' into lists row = csv_lines[i].replace('\n', '').split(',') # do predict (format must be same as fit()) img = np.array(list(map(int, row))).reshape(28, 28, 1) result = model.predict_classes(np.array([img])/255.0)[0] submit += str(image_id) + ',' + str(result) + '\n' image_id += 1 # Write file open('submit.csv', 'w').write(submit) ``` ![](https://i.imgur.com/c1NPD4S.png) ![](https://i.imgur.com/gRBb68z.png)