深度学习:构建神经网络并识别手写数字(正确率:0.91175)
转自我自己的blog
github链接
效果
可以看出(10个数据,分别是认为该数字为0-9的程度,最后取最高的那个即为结果)基本能正确识别
但是1和7,4和9还是不太容易识别的
全代码(ipynb)
引入库
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
构建神经网络类
class neuralNetwork(): # neural network class definition
# initialize 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
# learning rate
self.learnRate = learningRate
# link weight matrices, wih and who
# weight 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.hNodes, -0.5), (self.hNodes, self.iNodes))
self.who = numpy.random.normal(
0.0, pow(self.oNodes, -0.5), (self.oNodes, self.hNodes))
# annoymous func
self.actiFunc = lambda x: scipy.special.expit(x)
# train the neural network
def train(self, inputs_list, targets_list):
# convert inputs and targets 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.actiFunc(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.actiFunc(final_inputs)
# error is the difference of target and output
output_errors = targets - final_inputs
# 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.learnRate * \
numpy.dot((output_errors*final_outputs*(1.0-final_outputs)),
numpy.transpose(hidden_outputs))
"""
self.who += self.learnRate * \
numpy.dot((output_errors*final_outputs*(1.0-final_outputs)),
hidden_outputs.T)"""
# between the input and hidden layers
self.wih += self.learnRate * \
numpy.dot((hidden_errors*hidden_outputs *
(1.0 - hidden_outputs)), numpy.transpose(inputs))
# 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.actiFunc(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.actiFunc(final_inputs)
return final_outputs
网络布置
input_nodes = 784 # 28*28
hidden_nodes = 100
output_nodes = 10
learning_rate = 0.3
network = neuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
打开训练数据文件
with open('train.csv', 'r') as data_file:
data_list = data_file.readlines()[1:] # 除首行外,全部读取到内存中
# print(data_list)
data_file.close()
训练神经网络
for record in data_list:
all_values = record.split(',')
# make data into 0.01 ~ 1.00
""" Remains problem
(why?)
0.01: prevent 0.00 leading to failing to update the weight
1.00: just preventing the output value being 1.00 is enough
"""
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)
# numpy.zeros(): use 0 to pad the array
targets = numpy.zeros(output_nodes) + 0.01
# all_values[0] is the label of the record
targets[int(all_values[0])] = 0.99
network.train(inputs, targets)
打开测试数据集
test.csv里的数据集是无标签的
# load the test data CSV file into a list
with open('test.csv', 'r') as test_data_file:
test_data_list = test_data_file.readlines()[1:]
test_data_file.close()
测试数据并输出
使用test.csv的数据集进行测试输出(无标签)
# from test.csv
test = test_data_list[0] # 调度第0个测试数据
test_values = test.split(',')
test_inputs = (numpy.asfarray(test_values)/255.0 * 0.99) + 0.01
print(network.query(test_inputs))
# print(test_data_list[0].strip().split(','))
使用train.csv的数据集进行测试输出(带标签)
# from train.csv
test = data_list[999]
print('Answer is', test[0])
test_values = test.split(',')
test_inputs = (numpy.asfarray(test_values[1:])/255.0 * 0.99) + 0.01
print(network.query(test_inputs))
疑难杂症
tenserflow把numpy卸载了…
没关系,会安装对应版本的numpy的
Python关于%matplotlib inline报错
这个是 jupyter notebook 或者 jupyter qtconsole 的专属代码,使用%matplotlib inline
这段代码可以输出图像。但是vscode编辑器并没有这个功能。(但这并不妨碍vscode是宇宙第一编辑器的事实)
FileNotFoundError
PS F:\Programme_works\Python> python -u "f:\Programme_works\Python\DeepLearning\numRecog\neuralNetwork.py"
Traceback (most recent call last):
File "f:\Programme_works\Python\DeepLearning\numRecog\neuralNetwork.py", line 106, in \<module\>
with open('train.csv', 'r') as data_file:
FileNotFoundError: [Errno 2] No such file or directory: 'train.csv'
未找到文件,检查一下文件是否在命令执行时的目录(一般都是vscode打开的文件夹,或者jupyter notebook运行的文件所在的文件夹)
非jupyter编辑器输出csv图像
将
matplotlib.pyplot.imshow(image_array, cmap='Greys', interpolation='None')
改为
matplotlib.pyplot.imsave('temp.png', image_array, cmap='Greys')
便会保存在目录下
Living with bustle, hearing of isolation.