python学习与神经网络

利用python编写神经网络

参考《Python 神经网络编程》

编写神经网络类

先建立一个大体的框架,从宏观到微观地填充框架
神经网络类,大体应该具有三个函数

  1. 初始化函数,其中参数应该有

    • 输入层节点数目
    • 隐藏层
    • 输出层
  2. 训练函数
    训练函数在于学习给定训练集样本后,能够更新权重

  3. query 查询
    也就是给定一个输入,能够从输出节点处输出答案

所以大致代码就是

## neural network class definition



class Neural_Network:

    # initialize the neural network
    def __init__(self):
        pass;


    ## train the neural network
    def Train(self):
        pass;

    ## query the outputs of the neutal network
    def Query(self):
        passs;
逐渐丰富第一个方法,初始化
def __init__(self, input_nodes, hidden_nodes, output_nodes, learning_rate):
    #pass
    ## 初始化各个参数
    self.Input_Nodes = input_nodes;
    self.Hidden_Nodes = hidden_nodes;
    self.Output_Nodes = output_nodes;

    ## set learning rate
    self.Learning_Rate = learning_rate;

因此第一阶段的代码就丰富为如下所示

class Neural_Network:

    # initialize the neural network
    def __init__(self, input_nodes, hidden_nodes, output_nodes, learning_rate):
        # pass
        ## 初始化各个参数
        self.Input_Nodes = input_nodes;
        self.Hidden_Nodes = hidden_nodes;
        self.Output_Nodes = output_nodes;

        ## set learning rate
        self.Learning_Rate = learning_rate;

    ## train the neural network
    def Train(self):
        pass;

    ## query the outputs of the neutal network
    def Query(self):
        passs;

于是一开始就可以这样测试代码

input_nodes = 3;
hidden_nodes = 3;
output_nodes = 3;

learning_rate = 0.1;

## 创建一个神经网络对象
network1 = Neural_Network(input_nodes,hidden_nodes, output_nodes, learning_rate);
权重

接下来就是构造神经网络类最难最复杂的一步,声明权重属性和声明关于权重更新的方法
权重用于

  • 计算前馈信号
  • 计算反向传播的误差
  • 作为更新自身的参数

易知可以用矩阵简明紧凑地表示权重,因此我们可以创建

  • 输入层和隐藏层之间的权重矩阵Weights_Of_Input_Hidden,其size为Hidden_Nodes × Input_Nodes(因为要左乘输入向量)
  • 隐藏层和输出层之间的权重矩阵Weights_Of_Hidden_Output,其size为 Output_Nodes× Hidden_Nodes

易知,初始的各个权重值应该比较小,为了一般化,我们可以将各个权重赋予从标准正态分布中取的值
比如要初始化权重矩阵Weights_Of_Input_Hidden,我们可以用如下的代码
import numpy
numpy.random.rand(Hiiden_Nodes, Input_Nodes) ;

为了使权重更一般化,权重有正有负,因此可以用这句代码改善
numpy.random.rand(Hiiden_Nodes, Input_Nodes) - 0.5;

权重矩阵作为神经网络类的一个固有属性,也应该包含在初始化过程中,因此我们改进初始化方法如下

## 权重不必从外部输入
def __init__(self, input_nodes, hidden_nodes, output_nodes, learning_rate):
    # pass
    ## 初始化各个参数
    self.Input_Nodes = input_nodes;
    self.Hidden_Nodes = hidden_nodes;
    self.Output_Nodes = output_nodes;

    ## set learning rate
    self.Learning_Rate = learning_rate;

    ##SET THE MATRIX OF WEIGHTS
    self.Weights_Of_Input_Hidden = numpy.random.rand(Hidden_Nodes,Input_Nodes)-0.5;
    self.Weights_Of_Hidden_Output = numpy.random.rand(Output_Nodes, Hidden_Nodes)-0.5;

有些人喜欢用稍微复杂的方法初始化群众,即不用标准normal dist,
而是用均值为0,标准差为1/sqrt(传出节点数目)
所以可以改为


    self.Weights_Of_Input_Hidden = numpy.random.normal(0.0, pow(Hidden_Nodes,-0.5, (HiddenNodes,Input_Nodes));
    self.Weights_Of_Hidden_Output = numpy.random.normal(0.0, pow(Output_Nodes,-0.5, (Output_Nodes,HiddenNodes));
查询函数

查询函数的编写较为简单
首先要明确query函数的作用、输入、输出
query函数

  • 输入:神经网络的输入(一个Input_Nodes×1向量)
  • 输出:神经网络的输出(一个Output_Nodes×1向量)

首先分而析之
输入层的输入有用户给定,不妨设为input
易知,隐藏层的输入为 Weights_Of_Input_Hidden×input
所以可以这么写
Inputs_Of_Hidden = numpy.dot(self.Weights_Of_Input_Hidden, input);

隐藏层的作用,就在于作为一个阈值阀门,接受输入,处理后输出一个向量作为输出层的输入
怎么处理?Sigmoid函数!

神经网络类需要有一个关于激活函数的方法,激活函数有很多,我们暂且使用sigmoid
import scipy.special

self.Activation_Funtion = lambda x:scipy.special.expit(x);

Outputs_Of_Hidden = self.self.Activation_Funtion(Inputs_Of_Hidden);
于是照猫画虎,可以写出输出层的输入输出

Inputs_Of_Output = numpy.dot(self.Weights_Of_Hidden_Output, Outputs_Of_Hidden);
Outputs_Of_Output = self.Activation_Funtion(Inputs_Of_Output);

因此这部分工作完成后,代码填充的成果如下

class Neural_Network:

    # initialize the neural network
    def __init__(self, input_nodes, hidden_nodes, output_nodes, learning_rate):
        # pass
        ## 初始化各个参数
        self.Input_Nodes = input_nodes;
        self.Hidden_Nodes = hidden_nodes;
        self.Output_Nodes = output_nodes;

        ## set learning rate
        self.Learning_Rate = learning_rate;

        ##SET THE MATRIX OF WEIGHTS

        self.Weights_Of_Input_Hidden = numpy.random.normal(0.0,pow(self.Hidden_Nodes, -0.5), (self.Hidden_Nodes, self.Input_Nodes));
        self.Weights_Of_Hidden_Output = numpy.random.normal(0.0, pow(self.Output_Nodes, -0.5), (self.Output_Nodes, self.Hidden_Nodes));
        ## INNITIALIZE THE ACTIVATION FUNTCITON AS SIGMOID FUNTION
        self.Activation_Funtion = lambda x: scipy.special.expit(x);


    ## train the neural network
    def Train(self):
        pass;

    ## query the outputs of the neutal network
    def Query(self,list_of_inputs):
        # passs;
    ## 这里我们会接受一个list作为输入
    ##由于我们可能会输入一组输入而不是一个输入,也就是是说,可能会输入一个矩阵
    ##为了不失一般性,我们将输入转化为一个2d的数组
        inputs = numpy.array(list_of_inputs,ndmin = 2).T;

        Inputs_Of_Hidden = numpy.dot(self.Weights_Of_Input_Hidden, inputs);
        Outputs_Of_Hidden = self.Activation_Funtion(Inputs_Of_Hidden);

        Inputs_Of_Output = numpy.dot(self.Weights_Of_Hidden_Output, Outputs_Of_Hidden);
        Outputs_Of_Output = self.Activation_Funtion(Inputs_Of_Output);

        return Outputs_Of_Output;
训练函数

另外一个最难的地方就是训练函数的编写,主要的难点就是
把数学公式转化为程序代码
训练神经网络有两个阶段

  • 计算输出
  • 反向传播误差并优化权重

因此可以将具体的训练任务划分为两部分

  • 针对给定的训练样本计算出输出
  • 对比实际输出和理想输出,以误差来指导权重的更新
def train(self, inputs_list, target_list):
    Inputs = numpy.array(list_of_inputs, ndmin=2);
    Targets = numpy.array(target_list,ndmin = 2).T;

    Real_Outputs = self.Query(inputs_list);

    Errors_Of_Output = Targets - Real_Outputs;
    Errors_Of_Hidden = numpy.dot(self.Weights_Of_Hidden_Output.T,Errors_Of_Output);

对于隐藏层和输出层之间的权重,我们使用Errors_Of_Output进行优化
对于输入层和隐藏层之间的权重,我们使用Errors_Of_Hidden进行优化

    ## update the weights for the links between the hidden and output layers

    self.Weights_Of_Hidden_Output += self.Learning_Rate * numpy.dot(Errors_Of_Output * Outputs_Of_Output * (1.0-Outputs_Of_Output),Outputs_Of_Hidden.T);
    
    ## update the weights for the links between the input and hidden layers
    self.Weights_Of_Hidden_Output += self.Learning_Rate * numpy.dot(Errors_Of_Hidden * Outputs_Of_Hidden * (1.0-Outputs_Of_Hidden),Inputs.T);

游戏结束

最终代码
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值