简单的三层神经网络
上一篇是手动编写了一个感知机,对手写数字的数据集进行识别训练。趁热打铁,手动编写了一个三层的简单神经网络再次对手写数字的数据集进行识别训练,来看看最后的识别率能够达到什么程度。有兴趣的可以从这里下载上一次的感知机代码和数据集(收费是自动设置的,好像没有办法更改……有积分就直接下载吧,哈哈)
CSDN下载链接
再附上一个百度云盘链接:
百度云盘链接
提取码:zd0h
和上一次的感知机相比,三层神经网络多了一层的隐藏层,所以我们重新的设计一下各层的激活函数,以及重新推导一下反向传播的推导公式。
设置各层的激活函数
从输入层到隐藏层的激活函数设置为sigmoid函数(不要问我为什么,对于这个函数情有独钟,可能和从高中就喜欢生物学有关吧,看见它就好像看见了生物中的神经元激活的样子……),隐藏层到输出层的激活函数我设置为softmax函数。因为最后的结果是统计每一种数字的可能性,加一层softmax函数可以将最后的数字的可能性作归一化处理,用百分数的形式表示每一个数字的可能性,最后选出可能性最大的数字。
正向的推导如下图所示(手写方便……),并对误差函数进行设置:
反向传播的推导
话不多说,直接上公式推导的图片:
代码编写
代码稍微有点变化,但是变化真的不大(不然我也不可能在两天之内就写了两篇文章)
不说了,直接的上代码,和上次相比换一种方法,因为这一次的注释写的较多,这一次就直接的粘贴所有的代码。
class neuralNetwork:
# 用于计算softmax函数
def softmax_function(self, x):
return numpy.exp(x)/numpy.sum(numpy.exp(x))
pass
# 神经网络的初始化
def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
# 输入各自的输入结点、隐藏结点、输出结点
self.input_nodes = inputnodes
self.hidden_nodes = hiddennodes
self.output_nodes = outputnodes
# 学习率
self.learning_rate = learningrate
# 权重(通过减去0.5保证出现的数字一定在-1~1之间的权重)
self.wih = (numpy.random.rand(self.hidden_nodes, self.input_nodes)-0.5)
self.who = (numpy.random.rand(self.output_nodes, self.hidden_nodes)-0.5)
# 神经网络的激活函数
# 输入层到隐藏层的激活函数为sigmoid
self.activation_function = lambda x: scipy.special.expit(x)
# 隐藏层到输出层的函数为softmax
pass
"""
训练神经网络
训练任务主要分为两个部分:
1.将输入的样本序列进行计算(和query的计算方法相同);
2.将计算的到的输出和真实的数据进行比较,使用其中的差值来指导网络权重的更新
"""
def training(self, input_list, target_list):
# 得到输入的数组
inputs = numpy.array(input_list, ndmin=2).T
# 目标输出序列(真实的实际数据)
targets = numpy.array(target_list, ndmin=2).T
# 以下代码照抄函数query
hidden_inputs = numpy.dot(self.wih, inputs)
hidden_outputs = self.activation_function(hidden_inputs)
final_inputs = numpy.dot(self.who, hidden_outputs)
final_outputs = self.softmax_function(final_inputs)
# 输出的误差序列(用于优化隐藏层和输出层之间的权重矩阵)
output_errors = targets - final_outputs
# 隐藏层的误差序列(用于优化输入层和隐藏层之间的权重矩阵)
hidden_errors = numpy.dot(self.who.T, output_errors)
self.who += self.learning_rate*numpy.dot((output_errors*final_outputs*(1.0-final_outputs)), numpy.transpose(hidden_outputs))
self.wih += self.learning_rate*numpy.dot((hidden_errors*hidden_outputs*(1.0-hidden_outputs)), numpy.transpose(inputs))
pass
# 计算输出
def query(self, inputs_list):
inputs = numpy.array(inputs_list, ndmin=2).T
hidden_inputs = numpy.dot(self.wih, inputs)
hidden_outputs = self.activation_function(hidden_inputs)
final_inputs = numpy.dot(self.who, hidden_outputs)
final_outputs = self.softmax_function(final_inputs)
return final_outputs
pass
pass
test_input = 784
test_hidden = 100
test_out = 10
learning = 0.3
n = neuralNetwork(test_input, test_hidden, test_out, learning)
# 读取文件的数据
training_data_file = open("data\神经网络1.0\mnist_train_100.csv", 'r')
training_data_list = training_data_file.readlines()
training_data_file.close()
for record in training_data_list:
all_value = record.split(',')
inputs = (numpy.asfarray(all_value[1:])*0.99)+0.01
targets = numpy.zeros(test_out)+0.01
targets[int(all_value[0])-1] = 0.99
n.training(inputs, targets)
pass
"""训练完成"""
# 开始测试数据
test_data_file = open("data\神经网络1.0\mnist_test_10.csv", 'r')
test_data_list = test_data_file.readlines()
test_data_file.close()
test_score = 0
for record in test_data_list:
all_value = record.split(',')
correct_answer = all_value[0]
print("正确答案:"+all_value[0])
inputs = (numpy.asfarray(all_value[1:])*0.99)+0.01
outputs = n.query(inputs)
answer = numpy.argmax(outputs)
print("测试结果:")
print(answer)
if int(correct_answer) == int(answer):
test_score += 1
else:
test_score += 0
pass
pass
print(test_score)
代码直接复制就可以运行,最后粘贴一张运行的结果:
Emmmm,结果并没有想象中的好,100个训练数据,10个测试数据的正确率才0.6,哈哈,只能这样啦,当然如果提高训练数据的数量,也许能达到更高的水平,可以试试哈,文件我全部都上传到资源了,谁喜欢就下载看看,包含一个完整测试集和训练集的数据。
百度云盘链接:神经网络1.0
提取码:udny
CSDN的还在审核,如果可以我会下一次发出来的,不过估计没有多少人愿意这样下载,嘿嘿。