如下代码摘自于《Python神经网络编程》。可以说,去掉注释和空行后,代码总量应该是100行出头,覆盖了多方面的内容:
1)神经网络初始化;
2)神经网络训练;
3)神经网络测试;
4)打印最终结果;
麻雀虽小,五脏俱全。能够读透如下的代码,可以说简单神经网络也就入门了。书中对代码有了一定的解释,注释也对代码做出了解释,不过由于使用者不一定太熟悉Python,对其一些语法及函数库调用会存疑虑,因此如后的几篇文章,将对代码逐段进行讲解,希望通过讲解,能够降低代码理解难度。
西方人讲课或者写书,一般都会说“这个好简单”,实际上在解释过程中还是会跳过一些点(当然也是为了控制书籍的厚度,以及应对不同阶段能力的人)。国内学者则喜欢把书写的晦涩难懂,不写成那样体现不出其学术能力(导致那些书要么没人看,要么只适合已经有一定的深入的人翻阅)。
代码如下,可在导入numpy和scipy(这个库其实也可以省略,后面讲到的时候会说明)即可运行(那条matplotlib引入可以注释掉,因为实际运行中并未调用)。
先上代码。代码里调用的两个CSV文件,可以在如下链接下载:
https://raw.githubusercontent.com/makeyourownneuralnetwork/makeyourownneuralnetwork/master/mnist_dataset/mnist_test_10.csv
https://raw.githubusercontent.com/makeyourownneuralnetwork/makeyourownneuralnetwork/master/mnist_dataset/mnist_train_100.csv
完整的数据链接为:
训练集http://www.pjreddie.com/media/files/mnist_train.csv
测试集http://www.pjreddie.com/media/files/mnist_test.csv
如果按训练集100个,测试集10个来测试,基本上最终的输出在60%的准确率,可以当能不能正常跑通代码来测试。我建议是自己从总集里,摘取1000条数据,然后测试集为100条,这样跑出来的结果为93%左右,精度能够达到一定要求,并且时间消耗也可控(我的商务本需要跑5-6秒),或者更大一点也行。
如果数据全跑一遍(几万条),那么我的电脑大概花了7分多时间,时间较长,不过精度是不错的能达到97%左右。如果电脑性能OK并且等得起的话,也可以按数据全集进行测试(尤其要对比一些参数设置效果等,全跑一遍的话会更清晰)。
# python notebook for Make Your Own Neural Network
# code for a 3-layer neural network, and code for learning the MNIST dataset
# (c) Tariq Rashid, 2016
# license is GPLv2
import numpy
# scipy.special for the sigmoid function expit()
import scipy.special
# library for plotting arrays
import matplotlib.pyplot
# 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.hnodes, -0.5), (self.hnodes, self.inodes))
? ? ? ? self.who =numpy.random.normal(0.0, pow(self.onodes, -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)
? ? # 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))
? ? # 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.2
# 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_100.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 = 5
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)
# load the mnist test data CSV file into a list
test_data_file =open("mnist_dataset/mnist_test_10.csv", 'r')
test_data_list =test_data_file.readlines()
test_data_file.close()
# test the neural network
# scorecard for how well the network performs, initially empty
scorecard =[]
# go through all the records in the test data set
for record in test_data_list:
? ? # split the record by the ', ' commas
? ? all_values =record.split(',')
? ? # correct answer is first value
? ? correct_label =int(all_values[0])
? ? # scale and shift the inputs
? ? inputs =(numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01
? ? # query the network
? ? outputs =n.query(inputs)
? ? # the index of the highest value corresponds to the label
? ? label =numpy.argmax(outputs)
? ? # append correct or incorrect to list
? ? if (label ==correct_label):
? ? ? ? # network's answer matches correct answer, add 1 to scorecard
? ? ? ? scorecard.append(1)
? ? else:
? ? ? ? # network's answer doesn't match correct answer, add 0 to scorecard
? ? ? ? scorecard.append(0)
# calculate the performance score, the fraction of correct answers
scorecard_array =numpy.asarray(scorecard)
print ("performance =", scorecard_array.sum() / scorecard_array.size)
建议安装anaconda,或者用jupyter notebook(anaconda也是带的),方便运行调测。