網頁

2019年10月10日 星期四

Keras implementation of an LSTM neural network to classify and predict the MINST dataset

這篇將會針對經常用於時間序列數據進行分類的神經網路LSTM對2D數據進行分類,例如手寫字母的圖像來進行討論。


首先將MINST數據集60,000張手寫數字(0至9)圖像用於28 x 28像素網格上做訓練,以及10,000張用於測試的圖像。因此,每個數字由784條信息表示。在這個測試中,將每個圖像分解為28個steps,並為LSTM網絡提供28個features,看它是否仍然可以學習。有效地將784像素的圖像分解為28個time-step的“movie”(每個frame包含28條訊息)。

在下面的第一次嘗試中,將完全沒有優化的網絡做學習能夠達到98.89%的準確度。

# James implementation of minst database
# import required to process csv files with pandas
import pandas as pd
# for array manipulation
import numpy as np
# for normalizing the data
from sklearn.preprocessing import MinMaxScaler
# allows onehotencoding
from sklearn.preprocessing import OneHotEncoder
 
# read the training csv file # data from 60000 images originally represented as a 28 x 28 pixel grid
# originally obtained from http://yann.lecun.com/exdb/mnist/
mnist_training_data = pd.read_csv(r'C:\Users\james\Anaconda3JamesData\mnist_train.csv', header=None)
 
# each row of data consists of
# the first element [0] is the label of the actual number (0 through 9)
# the following 784 element [1:785] is the actual number originally respresented as a 28 x 28 pixel grid
 
# we want to create training data, and label data for our LSTM to train from
mnist_training_data_values = mnist_training_data.iloc[:, 1:785].values
mnist_training_data_labels = mnist_training_data.iloc[:, 0].values
 
# we will normalize the training data (from 0 to 1 using MinMaxScaler)
# normalise the training data
scaler = MinMaxScaler(feature_range = (0.0, 1.0))
mnist_training_data_values = scaler.fit_transform(mnist_training_data_values.astype('float64'))
 
# the output of the network values (the labels) are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
 
# Onehotencoding expects a 2D array
mnist_training_data_labels = mnist_training_data_labels.reshape (60000,1)
 
# create the encoder
encoder = OneHotEncoder(sparse=False, categories='auto')
 
# encode the training labels
mnist_training_data_labels = encoder.fit_transform(mnist_training_data_labels)
 
# reshape mnist_training_data_values into 3d array
mnist_training_data_values = mnist_training_data_values.reshape(60000 , 28, 28)
 
# effectively I will feed each image into the LSTM as 28 rows of data
# with 28 steps - so effectively preceptually changing the data into a
# 28 step time sequence (with 28 features per step)
 
#print("mnist_training_data_values shape:", mnist_training_data_values.shape)
#print ("mnist_training_data_labels shape: ",mnist_training_data_labels.shape)
#print (mnist_training_data_labels )
 
from keras.models import Sequential
from keras.layers import LSTM
from keras.layers import Dense
from keras.optimizers import Adam
#from keras.layers import Dropout
 
# each sequence (representing one number from the minst database) has 28 steps and 28 features
model = Sequential()
model.add(LSTM(50,return_sequences=True,input_shape=(28, 28)))
model.add(LSTM(50))
model.add(Dense(10, activation='softmax'))
model.compile(Adam(lr=0.001), loss='categorical_crossentropy', metrics=['acc'])
 
history = model.fit(mnist_training_data_values , mnist_training_data_labels , validation_split=0.1, shuffle=True, batch_size= 28,epochs=500, verbose=2)
 
# display diagnostics of the training
import matplotlib.pyplot as plt 
%matplotlib inline
 
plt.figure(figsize=(13,8)) 
plt.plot(history.history['loss'], color='blue')
plt.plot(history.history['val_loss'], color='orange')
plt.plot(history.history['acc'], color='red')
plt.plot(history.history['val_acc'], color='green')
plt.title('model loss during training')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['loss', 'val_loss', 'acc',' val_acc'], loc='upper left')
plt.show()
 
 
# prediction model
mnist_testing_data = pd.read_csv(r'C:\Users\james\Anaconda3JamesData\mnist_test.csv', header=None)
 
# process the data as before
mnist_testing_data_values = mnist_testing_data.iloc[:, 1:785].values
mnist_testing_data_labels = mnist_testing_data.iloc[:, 0].values
 
# using the same normalisation as I used on the training data
# hence using 'transform' and not 'fit_transform'
mnist_testing_data_values = scaler.transform(mnist_testing_data_values.astype('float64'))
 
length_of_testing_data = len(mnist_testing_data_values)
 
# reshape the testing data values to the same shape as the training values
mnist_testing_data_values = mnist_testing_data_values.reshape(length_of_testing_data, 28, 28)
 
predict = model.predict(mnist_testing_data_values)
 
# decode the onehotencoded prediction results
one_hot_decoded_data = encoder.inverse_transform(predict)
 
#length = len(one_hot_decoded_data) #the decoded predict model
one_hot_decoded_data = np.array(one_hot_decoded_data)
mnist_testing_data_labels = np.array(mnist_testing_data_labels)
 
#print (one_hot_decoded_data.shape)
#print (mnist_testing_data_labels.shape)
 
# reshape the one_hot_decoded_data
one_hot_decoded_data = one_hot_decoded_data.reshape(1,-1)
mnist_testing_data_labels = mnist_testing_data_labels.reshape(1,10000)
 
#print (one_hot_decoded_data.shape)
#print (mnist_testing_data_labels.shape)
 
# accuracy analytics
correct= 0
for i in range(0,10000):
    if (one_hot_decoded_data[0,i] == mnist_testing_data_labels[0,i]):
        print ("sample number: ",i," test: ",mnist_testing_data_labels[0,i], " predicted: ",one_hot_decoded_data[0,i], " CORRECT")
        correct+=1
    else:
        print ("sample number: ",i," test: ",mnist_testing_data_labels[0,i], " predicted: ",one_hot_decoded_data[0,i], " FALSE")
 
print ('Accuracy: %f' % ((correct/10000)*100))





參考
https://www.drjamesfroggatt.com/python-and-neural-networks/keras-implementation-of-an-lstm-neural-network-to-classify-and-predict-the-minst-dataset/





沒有留言:

張貼留言