文章目录
第 2 章、使用Python进行DIY
2.4、使用Python制作神经网络
2.4.1、框架代码
神经网络至少有三个函数:
初始化函数——设定输入层节点、隐藏节点和输出层节点的数量。
训练——学习给定训练集样本后,优化权重。
查询——给定输入,从输出节点给出答案。
框架代码如下:
# 框架代码
# neural network class definition
class neuralNetwork:
# initialise the neural network
def __init__():
pass
# train the neural network
def train():
pass
# query the neural network
def query():
pass
2.4.2、初始化网络
即如何初始化整个神经网络。
填写之后代码如下:
# 框架代码
# neural network class definition
class neuralNetwork:
# initialise the neural network
# 初始化神经网络
# inputnodes是输入层网络节点的个数
# hiddennodes是中间层网络节点的个数
# outputnodes是输出层网络节点的个数
# learningrate是学习率
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.lr = learningrate
pass
# train the neural network
def train():
pass
# query the neural network
def query():
pass
# number of input, hidden and output nodes
# 设置输入,隐藏和输出层节点的数量
input_nodes = 3
hidden_nodes = 3
output_nodes = 3
# learning rate is 0.3
# 设置学习率为0.3
learning_rate = 0.3
# create instance of neural network
# 创建一个神经网络的实例
n = neuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
2.4.3、权重——网络的核心
因为对于一个如下的神经网络来说:
有:X=W·I,W是权重矩阵,I是输入矩阵,X是组合调节后的信号,即:
所以有,输入层和隐藏层之间的链接权重矩阵Winput_hidden的大小是hidden_nodes乘以input_nodes
同理,隐藏层和输出层之间的链接权重矩阵Whidden_output的大小是output_nodes乘以hidden_nodes
# 框架代码
# neural network class definition
import numpy
class neuralNetwork:
# initialise the neural network
# 初始化神经网络
# inputnodes是输入层网络节点的个数
# hiddennodes是中间层网络节点的个数
# outputnodes是输出层网络节点的个数
# learningrate是学习率
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 an who
# 链接权重矩阵
# wih是输入层和隐藏层之间的链接权重矩阵W_input_hidden
# who是输入层和隐藏层之间的链接权重矩阵W_hidden_output
# weights inside the arrays are w_i_j, where link is from node i to node j in the next layer
# 数组里的权重是wij,其中链接是从节点i到节点j的下一层
# w11 w21
# w12 w22
# numpy.random.rand(X,Y)的意思是生成一个随机数组,数组大小为X*Y,内容为0~1之间
# 书上之前说这个权重最好是-1~+1,但是他做了个减0.5的操作,就成了-0.5~+0.5
# 我觉得此处在乘以2效果更好些
self.wih = (numpy.random.rand(self.hnodes, self.inodes)-0.5)
self.who = (numpy.random.rand(self.onodes, self.hnodes)-0.5)
# learning rate
# 设置学习率
self.lr = learningrate
pass
# train the neural network
def train():
pass
# query the neural network
def query():
pass
# number of input, hidden and output nodes
# 设置输入,隐藏和输出层节点的数量
input_nodes = 3
hidden_nodes = 3
output_nodes = 3
# learning rate is 0.3
# 设置学习率为0.3
learning_rate = 0.3
# create instance of neural network
# 创建一个神经网络的实例
n = neuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
2.4.4、可选项——较复杂的权重
上一节在设置权重的时候是随机了一个-0.5~+0.5的数,但是第一章有说过,如果满足-1~+1中取值,并且在一个节点传入链接数量平方根倒数的大致范围内随机采样(见1.16)会更好。
其实就是中心值为0,标准方差为1/√(节点数),的一个分布。
用normal函数替代rand函数即可。
改进后代码如下:
# 框架代码
# neural network class definition
import numpy
class neuralNetwork:
# initialise the neural network
# 初始化神经网络
# inputnodes是输入层网络节点的个数
# hiddennodes是中间层网络节点的个数
# outputnodes是输出层网络节点的个数
# learningrate是学习率
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 an who
# 链接权重矩阵
# wih是输入层和隐藏层之间的链接权重矩阵W_input_hidden
# who是输入层和隐藏层之间的链接权重矩阵W_hidden_output
# weights inside the arrays are w_i_j,
# where link is from node i to node j in the next layer
# 数组里的权重是wij,其中链接是从节点i到节点j的下一层
# w11 w21
# w12 w22
# numpy.random.normal(a,b,(X,Y))的意思是生成一个随机数组
# 数组大小为X*Y,内容服从中心值为a,方差为b
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.inodes, -0.5), (self.onodes, self.hnodes))
# learning rate
# 设置学习率
self.lr = learningrate
pass
# train the neural network
def train():
pass
# query the neural network
def query():
pass
# number of input, hidden and output nodes
# 设置输入,隐藏和输出层节点的数量
input_nodes = 3
hidden_nodes = 3
output_nodes = 3
# learning rate is 0.3
# 设置学习率为0.3
learning_rate = 0.3
# create instance of neural network
# 创建一个神经网络的实例
n = neuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
2.4.5、查询网络
1、X=W·I公式转换成代码
公式:X=W·I,W是权重矩阵,I是输入矩阵,X是组合调节后的信号
输入层到中间层的计算,代码:
hidden_inputs = numpy.dot(self.wih, inputs)
中间层到输出层的计算,代码:
final_inputs = numpy.dot(self.who, hidden_outputs)
2、sigmod函数转换成代码
scipy.special这个模块中有sigmod函数的计算,自己就不用写逻辑了。
声明代码:
# scipy.special for the sigmoid function expit()
import scipy.special
使用sigmod函数的时候,将sigmod函数用lambda定义为一个内部的函数,不过我感觉这里最好还是使用def定义一个。
还有,这里使用scipy.special.expit的时候报警告,说是没有这个函数,警告如下:
[pylint] E1101:Module 'scipy.special' has no 'expit' member
但是,的确能使用,先放下吧。
定义函数的代码:
# activation function is the sigmod function
self.activation_function = lambda x: scipy.special.expit(x)
使用函数的代码:
# 计算隐藏层的输出
hidden_outputs = self.activation_function(hidden_inputs)
# 计算输出层的输出
final_outputs = self.activation_function(final_inputs)
3、改进后的代码:
# 框架代码
# neural network class definition
import numpy
# scipy.special for the sigmoid function expit()
import scipy.special
class neuralNetwork:
# initialise the neural network
# 初始化神经网络
# inputnodes是输入层网络节点的个数
# hiddennodes是中间层网络节点的个数
# outputnodes是输出层网络节点的个数
# learningrate是学习率
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 an who
# 链接权重矩阵
# wih是输入层和隐藏层之间的链接权重矩阵W_input_hidden
# who是输入层和隐藏层之间的链接权重矩阵W_hidden_output
# weights inside the arrays are w_i_j,
# where link is from node i to node j in the next layer
# 数组里的权重是wij,其中链接是从节点i到节点j的下一层
# w11 w21
# w12 w22
# numpy.random.normal(a,b,(X,Y))的意思是生成一个随机数组
# 数组大小为X*Y,内容服从中心值为a,方差为b
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.inodes, -0.5), (self.onodes, self.hnodes))
# learning rate
# 设置学习率
self.lr = learningrate
# activation function is the sigmod function
self.activation_function = lambda x: scipy.special.expit(x)
pass
# train the neural network
def train():
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
# 计算隐藏层的输入
# numpy.dot(X,Y)的意思是两个数组的点乘
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)
pass
# number of input, hidden and output nodes
# 设置输入,隐藏和输出层节点的数量
input_nodes = 3
hidden_nodes = 3
output_nodes = 3
# learning rate is 0.3
# 设置学习率为0.3
learning_rate = 0.3
# create instance of neural network
# 创建一个神经网络的实例
n = neuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
2.4.6、迄今为止的代码
改进上一节的一些小问题。
1、query函数最后要返回结果,即return final_outputs,然后就可以删除最后的pass 了。
2、随便加一个数据,进行测试,看看程序是不是能跑
print(n.query((1.0, 0.5, -1.5)))
3、改到现在的代码:
# 框架代码
# neural network class definition
import numpy
# scipy.special for the sigmoid function expit()
import scipy.special
class neuralNetwork:
# initialise the neural network
# 初始化神经网络
# inputnodes是输入层网络节点的个数
# hiddennodes是中间层网络节点的个数
# outputnodes是输出层网络节点的个数
# learningrate是学习率
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 an who
# 链接权重矩阵
# wih是输入层和隐藏层之间的链接权重矩阵W_input_hidden
# who是输入层和隐藏层之间的链接权重矩阵W_hidden_output
# weights inside the arrays are w_i_j,
# where link is from node i to node j in the next layer
# 数组里的权重是wij,其中链接是从节点i到节点j的下一层
# w11 w21
# w12 w22
# numpy.random.normal(a,b,(X,Y))的意思是生成一个随机数组
# 数组大小为X*Y,内容服从中心值为a,方差为b
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.inodes, -0.5), (self.onodes, self.hnodes))
# learning rate
# 设置学习率
self.lr = learningrate
# activation function is the sigmod function
self.activation_function = lambda x: scipy.special.expit(x)
pass
# train the neural network
def train():
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
# 计算隐藏层的输入
# numpy.dot(X,Y)的意思是两个数组的点乘
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 = 3
hidden_nodes = 3
output_nodes = 3
# learning rate is 0.3
# 设置学习率为0.3
learning_rate = 0.3
# create instance of neural network
# 创建一个神经网络的实例
n = neuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
# 测试query函数
print(n.query((1.0, 0.5, -1.5)))
2.4.7、训练网络
训练网络由两部分组成:
第一部分:针对给定的训练样本计算输出。这和query中的没啥区别。
第二部分:将计算得到的输出与所需要的输出进行对比,得到误差,指导网络的权重更新。
1、定义函数。形参列表,需要两个外部值,一个是输入网络的数据,另一个是目标数据。
def train(self, inputs_list, targets_list):
2、第一部分代码,和query中的一样,但是加了个target的初始化:
# vonvert 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
# 计算隐藏层的输入
# numpy.dot(X,Y)的意思是两个数组的点乘
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)
3、第二部分,计算误差部分:
输出层的误差就是目标输出值减去实际输出值,转换成代码:
output_error = targets-final_outputs
隐藏层的误差公式前面说过,如下所示:
所以,转换成代码如下:
hidden_error = numpy.dot(self.who.T, output_error)
4、第二部分,更新权值部分:
权值的增量公式为:
所以,转换成代码如下:
# 更新隐藏层到输出层的权重
self.who += self.lr * numpy.dot((output_error*final_outputs*(1.0-final_outputs)),numpy.transpose(hidden_outputs))
# 更新输入层到隐藏层的权重
self.wih += self.lr * numpy.dot((hidden_error*hidden_outputs * (1.0-hidden_outputs)), numpy.transpose(inputs))
5、目前的代码:
见下一节,此处不赘述了。
2.4.8、完整的神经网络代码
# 框架代码
# neural network class definition
import numpy
# scipy.special for the sigmoid function expit()
import scipy.special
class neuralNetwork:
# initialise the neural network
# 初始化神经网络
# inputnodes是输入层网络节点的个数
# hiddennodes是中间层网络节点的个数
# outputnodes是输出层网络节点的个数
# learningrate是学习率
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 an who
# 链接权重矩阵
# wih是输入层和隐藏层之间的链接权重矩阵W_input_hidden
# who是输入层和隐藏层之间的链接权重矩阵W_hidden_output
# weights inside the arrays are w_i_j, where link is from node i to node j in the next layer
# 数组里的权重是wij,其中链接是从节点i到节点j的下一层
# w11 w21
# numpy.random.normal(a,b,(X,Y))的意思是生成一个随机数组,数组大小为X*Y,内容服从中心值为a,方差为b
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.inodes, -0.5), (self.onodes, self.hnodes))
# learning rate
# 设置学习率
self.lr = learningrate
# activation function is the sigmod function
self.activation_function = lambda x: scipy.special.expit(x)
pass
# train the neural network
def train(self, inputs_list, targets_list):
# vonvert 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
# 计算隐藏层的输入
# numpy.dot(X,Y)的意思是两个数组的点乘
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_error = targets-final_outputs
# hidden layer error is the output_error, split by weight,recombined at hidden nodes
# 计算隐藏层的误差
hidden_error = numpy.dot(self.who.T, output_error)
# update the weights for the links between the hidden and output layers
# 更新隐藏层到输出层的权重
# 下面行末尾加的反斜杠\的意思是编译的时候忽略换行符
# 如果一行写不下,在代码末尾加上“\”即可
# 另外,在括号() {} [] 中的代码不需要换行符“\”,直接换行即可达到同样的效果
self.who += self.lr * \
numpy.dot((output_error*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_error*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
# 计算隐藏层的输入
# numpy.dot(X,Y)的意思是两个数组的点乘
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 = 3
hidden_nodes = 3
output_nodes = 3
# learning rate is 0.3
# 设置学习率为0.3
learning_rate = 0.3
# create instance of neural network
# 创建一个神经网络的实例
n = neuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
# 测试query函数
print(n.query((1.0, 0.5, -1.5)))
另:一些说明
1、本博客仅用于学习交流,欢迎大家瞧瞧看看,为了方便大家学习。
2、如果原作者认为侵权,请及时联系我,我的qq是244509154,邮箱是[email protected],我会及时删除侵权文章。
3、我的文章大家如果觉得对您有帮助或者您喜欢,请您在转载的时候请注明来源,不管是我的还是其他原作者,我希望这些有用的文章的作者能被大家记住。
4、最后希望大家多多的交流,提高自己,从而对社会和自己创造更大的价值。