上面我们说了神经网络的基础知识,根据上章的基础尝试搭建一个标准的3层神经网络,参考https://www.cnblogs.com/bestExpert/p/9128645.html
1.框架代码
1.>初始化函数 — 设定输入层节点、隐藏层节点、输出层节点的数量,设置学习率和各层的权重
2.>训练 — 学习给定训练集样本后,优化权重
3.>查询 — 给定输入,从输出节点给出答案
2.初始化网络
在init函数里面增加节点、学习率的初始化
3.权重--网络的核心
网路中最重要的部分是链接权重,我们使用这些权重来计算前馈信号、反向传播误差,并且在试图改进网路时优化链接权重本身。可以使用矩阵简明地表示权重,因为是三层结构,所以我们需要创建:
♦ 在输入层与隐藏层之间的连接权重矩阵Winput_hidden,大小为hidden_nodes乘以input_nodes
♦ 在隐藏层与输出层之间的连接权重矩阵Whidden_output,大小为output_nodes乘以hidden_nodes
我们使用 numpy.randon.rand(row,columns) 或者numpy.random.normal()生成权重
如下生成一个3*3大小,数值区间为±根号下hnodes的倒数
4.查询网络
query()函数接受神经网络的输入,返回网络的输出。需要传递来自输入层节点的输入信号,通过隐藏层,最后从输出层输出。当信号馈送至给定的隐藏层节点或输出层节点时,我们使用链接权重调节信号,还应用S激活函数抑制来自这些节点的信号。
1.>定义输入值为input_list,拆分成多维数组,利用python的nmpy.array(input_list,ndmin=2).T
2.>利用输入矩阵点乘于链接权重计算出隐藏层输出:Xhidden=Whidden_input * I ,在python中我们可以利用numpy.dot()来实现矩阵的点乘
3.>对输出矩阵应用激活函数:Ohidden=sigmoid(Xhidden),在python中我们可以利用scipy.special.expit(x)
隐藏层到输出层过程同上,整合之后代码如下:
5.训练网络:目的是根据误差优化权重
第一部分:针对给定的训练样本计算输出,这与我们刚刚在query()函数上所做的没什么区别
第二部分:将计算得到的输出与所需输出对比,使用差值来指导网络权重的更新。
第一部分和上面的一样,将不再细分,下来主要细分第二部分
1.>train()函数增加目标值列表参数,并转换成多维数组,方式同input的转换,在python中我们通过targets=numpy.array(target_input,ndmin=2).T
2.>计算输出层误差,为目标值减去输出值,output_errors=target-final_output
3.>计算得到隐藏层误差,errorhidden=weightThidden_output*erroroutput,在python中我们可以通过dot()方法计算矩阵点乘得到hidden_errors
4.>计算隐藏层到输出层的权重变化量,根据公式ΔWJ,K = & * Ek * sigmoid( Ofinal_input) * (1 - sigmoid(Ofinal_input)) • OjT ,&为学习率,sigmoid为激活函数,Oj为输出值的输入矩阵
5.>计算输入层到隐藏层的权重变化量,同上。
总结前面5步如下:
一个简单的3层神经网络就搭建完了,这些代码可用于创建、训练、查询3层神经网络,进行几乎任何任务,下面我们将进行特定任务,学习识别手写数字,上面的代码合起来如下:
import numpy as np
import scipy.special as spc
class neuralNetwork:
def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
self.inodes = inputnodes
self.hnodes = hiddennodes
self.onodes = outputnodes
self.lr = learningrate
self.wih = np.random.normal(0.0, pow(self.hnodes, -0.5), (self.hnodes, self.inodes))
self.who = np.random.normal(0.0, pow(self.onodes, -0.5), (self.onodes, self.hnodes))
self.activation_function = lambda x: spc.expit(x)
pass
def train(self, input_list, target_list):
inputs = np.array(input_list, ndmin=2).T
hidden_input = np.dot(self.wih, input)
hidden_output = self.activation_function(hidden_input)
final_input = np.dot(self.who, hidden_output)
final_output = self.activation_function(final_input)
targets = np.array(target_list, ndmin=2).T
output_error = targets - final_output
hidden_errors = np.dot(self.who.T, output_error)
self.who += self.lr * np.dot(output_error * final_output * (1.0 - final_output), np.transpose(hidden_output))
self.wih += self.lr * np.dot(hidden_errors * hidden_output * (1.0 - hidden_output), np.transpose(inputs))
pass
def query(self, input_list):
inputs = np.array(input_list, ndmin=2).T
hidden_input = np.dot(self.wih, inputs)
hidden_output = self.activation_function(hidden_input)
final_input = np.dot(self.who, hidden_output)
final_output = self.activation_function(final_input)
return final_output
也可以在github上面下载,里面有详细的注释:https://github.com/pythonAndAI/nerve-net/tree/master/threeLayerDome