Neural Networkによる手書き数字認識@2017.11.28


Photoshopで28ピクセルx28ピクセルの手書き数字PNGgファイルを作成
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
Photoshopで新規ファイル作成>28ピクセルx28ピクセル、解像度72,カラーモード:グレースケール、カンパスカラー:白
キャンバスにブラシで数字を書き、web用PNGファイル保存。ファイル名は、2828_my_own_R_*.pngとして、*の部分に正解の数字を埋め込む。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
手書き数字認識 Neural Network
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
import numpy
# scipy.special for the sigmoid function expit()
import scipy.special
# library for plotting arrays
import matplotlib.pyplot
# ensure the plots are inside this notebook, not an external window
%matplotlib inline
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
# helper to load data from PNG image files
import scipy.misc
# glob helps select multiple files using patterns
import glob
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
# neural network class definition
class neuralNetwork:

# initialise the neural network
def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
# set number of nodes in each input, hidden, output layer
self.inodes = inputnodes
self.hnodes = hiddennodes
self.onodes = outputnodes

# link weight matrices, wih and who
# weights inside the arrays are w_i_j, where link is from node i to node j in the next layer
# w11 w21
# w12 w22 etc
self.wih = numpy.random.normal(0.0, pow(self.inodes, -0.5), (self.hnodes, self.inodes))
self.who = numpy.random.normal(0.0, pow(self.hnodes, -0.5), (self.onodes, self.hnodes))

# learning rate
self.lr = learningrate

# activation function is the sigmoid function
self.activation_function = lambda x: scipy.special.expit(x)

pass

# train the neural network
def train(self, inputs_list, targets_list):
# convert inputs list to 2d array
inputs = numpy.array(inputs_list, ndmin=2).T
targets = numpy.array(targets_list, ndmin=2).T

# calculate signals into hidden layer
hidden_inputs = numpy.dot(self.wih, inputs)
# calculate the signals emerging from hidden layer
hidden_outputs = self.activation_function(hidden_inputs)

# calculate signals into final output layer
final_inputs = numpy.dot(self.who, hidden_outputs)
# calculate the signals emerging from final output layer
final_outputs = self.activation_function(final_inputs)

# output layer error is the (target – actual)
output_errors = targets – final_outputs
# hidden layer error is the output_errors, split by weights, recombined at hidden nodes
hidden_errors = numpy.dot(self.who.T, output_errors)

# update the weights for the links between the hidden and output layers
self.who += self.lr * numpy.dot((output_errors * final_outputs * (1.0 – final_outputs)), numpy.transpose(hidden_outputs))

# update the weights for the links between the input and hidden layers
self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 – hidden_outputs)), numpy.transpose(inputs))

pass

# query the neural network
def query(self, inputs_list):
# convert inputs list to 2d array
inputs = numpy.array(inputs_list, ndmin=2).T

# calculate signals into hidden layer
hidden_inputs = numpy.dot(self.wih, inputs)
# calculate the signals emerging from hidden layer
hidden_outputs = self.activation_function(hidden_inputs)

# calculate signals into final output layer
final_inputs = numpy.dot(self.who, hidden_outputs)
# calculate the signals emerging from final output layer
final_outputs = self.activation_function(final_inputs)

return final_outputs
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
# number of input, hidden and output nodes
input_nodes = 784
hidden_nodes = 200
output_nodes = 10

# learning rate
learning_rate = 0.1

# create instance of neural network
n = neuralNetwork(input_nodes,hidden_nodes,output_nodes, learning_rate)
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
# load the mnist training data CSV file into a list
training_data_file = open(“mnist_dataset/mnist_train.csv”, ‘r’)
training_data_list = training_data_file.readlines()
training_data_file.close()
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
# train the neural network

# epochs is the number of times the training data set is used for training
epochs = 10

for e in range(epochs):
# go through all records in the training data set
for record in training_data_list:
# split the record by the ‘,’ commas
all_values = record.split(‘,’)
# scale and shift the inputs
inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01
# create the target output values (all 0.01, except the desired label which is 0.99)
targets = numpy.zeros(output_nodes) + 0.01
# all_values[0] is the target label for this record
targets[int(all_values[0])] = 0.99
n.train(inputs, targets)
pass
pass
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
# our own image test data set
our_own_dataset = []

# load the png image data as test data set
for image_file_name in glob.glob(‘my_own_images/2828_my_own_R_?.png’):

# use the filename to set the correct label
label = int(image_file_name[-5:-4])

# load image data from png files into an array
print (“loading … “, image_file_name)
img_array = scipy.misc.imread(image_file_name, flatten=True)

# reshape from 28×28 to list of 784 values, invert values
img_data = 255.0 – img_array.reshape(784)

# then scale data to range from 0.01 to 1.0
img_data = (img_data / 255.0 * 0.99) + 0.01
print(numpy.min(img_data))
print(numpy.max(img_data))

# append label and image data to test data set
record = numpy.append(label,img_data)
our_own_dataset.append(record)

pass
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
loading … my_own_images/2828_my_own_R_0.png
0.01
0.992235
loading … my_own_images/2828_my_own_R_1.png
0.01
0.996118
loading … my_own_images/2828_my_own_R_2.png
0.01
0.953412
loading … my_own_images/2828_my_own_R_3.png
0.01
0.996118
loading … my_own_images/2828_my_own_R_4.png
0.01
0.996118
loading … my_own_images/2828_my_own_R_5.png
0.01
0.996118
loading … my_own_images/2828_my_own_R_6.png
0.01
1.0
loading … my_own_images/2828_my_own_R_7.png
0.01
0.984471
loading … my_own_images/2828_my_own_R_8.png
0.01
0.996118
loading … my_own_images/2828_my_own_R_9.png
0.01
1.0
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
# test the neural network with our own images

# record to test
item = 0

# plot image
matplotlib.pyplot.imshow(our_own_dataset[item][1:].reshape(28,28), cmap=’Greys’, interpolation=’None’)

# correct answer is first value
correct_label = our_own_dataset[item][0]
# data is remaining values
inputs = our_own_dataset[item][1:]

# query the network
outputs = n.query(inputs)
print (outputs)

# the index of the highest value corresponds to the label
label = numpy.argmax(outputs)
print(“network says “, label)
# append correct or incorrect to list
if (label == correct_label):
print (“match!”)
else:
print (“no match!”)
pass
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
手書きを認識するか?
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
[[ 0.08749586]
[ 0.01693271]
[ 0.08272637]
[ 0.19052411]
[ 0.01344942]
[ 0.00916322]
[ 0.23033908]
[ 0.00746316]
[ 0.00839809]
[ 0.01564953]]
network says 6 失敗! 0勝1敗
no match!

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
[[ 0.00929601]
[ 0.00705695]
[ 0.00896116]
[ 0.01571136]
[ 0.01280686]
[ 0.26678773]
[ 0.11057505]
[ 0.00643837]
[ 0.04254716]
[ 0.00054947]]
network says 5 失敗! 0勝2敗
no match!

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
[[ 0.19699445]
[ 0.00863226]
[ 0.09640107]
[ 0.13376429]
[ 0.03982884]
[ 0.00548624]
[ 0.37999148]
[ 0.00127124]
[ 0.27588656]
[ 0.00573728]]
network says 6 失敗! 0勝3敗
no match!

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
[[ 0.01147864]
[ 0.00175073]
[ 0.00699022]
[ 0.99274195]
[ 0.00567327]
[ 0.00475358]
[ 0.01379812]
[ 0.00159104]
[ 0.0478471 ]
[ 0.00730703]]
network says 3 成功!  1勝3敗
match!

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
[[ 0.23671729]
[ 0.00639598]
[ 0.03482028]
[ 0.03384677]
[ 0.05345516]
[ 0.02063995]
[ 0.6614655 ]
[ 0.00285741]
[ 0.10413975]
[ 0.02487155]]
network says 6 失敗!  1勝4敗
no match!

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
[[ 1.17262770e-02]
[ 4.23298181e-03]
[ 4.93694504e-03]
[ 1.62192124e-01]
[ 4.55143482e-03]
[ 8.20789618e-01]
[ 3.03220173e-01]
[ 7.96863250e-02]
[ 1.23657271e-02]
[ 7.76690264e-04]]
network says 5  成功!  2勝4敗
match!

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
[[ 0.05285198]
[ 0.00387988]
[ 0.14801434]
[ 0.08918772]
[ 0.02010164]
[ 0.09634501]
[ 0.36159842]
[ 0.00561413]
[ 0.08645926]
[ 0.03594678]]
network says 6 成功!  3勝4敗
match!

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
[[ 0.00489775]
[ 0.02010467]
[ 0.12412905]
[ 0.49777193]
[ 0.00593953]
[ 0.00682776]
[ 0.03434232]
[ 0.2688507 ]
[ 0.24320634]
[ 0.01637723]]
network says 3 失敗! 3勝5敗 
no match!

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
[[ 0.03225633]
[ 0.001868 ]
[ 0.0335084 ]
[ 0.29520095]
[ 0.0163471 ]
[ 0.00921536]
[ 0.10173158]
[ 0.00461127]
[ 0.83934395]
[ 0.02801475]]
network says 8 成功! 4勝5敗 
match!

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
[[ 0.02861226]
[ 0.01349142]
[ 0.00613588]
[ 0.01699902]
[ 0.17791183]
[ 0.05718847]
[ 0.15776007]
[ 0.07520391]
[ 0.07301927]
[ 0.89640036]]
network says 9 成功! 5勝5敗 
match!

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
5勝5敗 正答率50%とあまり良くない!
「自作」のアルゴリズムでは難しいのか、次はTensorFlowかSCikitで挑戦してみよう。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー