人工神经网络是典型的机器学习模式随着深度学习的发展神经网络模式日益完善
联想到大家熟悉的回归问题,神经网络模型实际上是根据训练样本建立多维输入多维输出的函数,并利用该函数进行预测,网络训练过程就是调节该函数参数以提高预测精度的过程。 神经网络要解决的问题与最小二乘法回归要解决的问题没有根本区别。
回归和分类是常用神经网络处理的两类问题,如果你已经知道神经网络是如何工作的,在http://playground.tensor flow.org /体验浅层神经网络的工作过程
感知机(Perceptron )是一种简单的线性二分类器,用于存储输入权重,并根据输入和内置函数计算输出。 人工神经网络中的每个神经元都是感知机。
在前馈神经网络预测过程中,数据流从输入到输出单向流动,不存在循环和反馈通道。
目前大多数神经网络模型都属于前馈神经网络,以下对前馈过程进行详细讨论
多层感知机(MLP )是由多个感知层完全连接而构成的前馈神经网络,该模型在非线性问题中表现较好。
全连接是指层a的任意神经元和相邻层b上的任意神经元之间存在连接。
反向传播(Back Propagation,BP )是误差反向传播的简称,它是训练人工神经网络的常用算法,通常与梯度下降法等优化方法结合使用。
本文介绍的神经网络模型在结构上属于MLP,由于采用BP算法进行训练,人们也称为BP神经网络。
BP神经网络原理经典的BP神经网络通常是由三层组成的:输入层、抑制层和输出层。 通常,输入层的神经元数与特征数相关,输出层数与类数相同,抑制层层数和神经元数均可定制。
每个神经元代表数据的一次处理:
各抑制层和输出层神经元输出和输入的函数关系为:
Ij=iWijOi
Ij=iWijOi
OJ=SIGmod(il )=11 eIl
OJ=SIGmod(il )=11 eIl
其中,WijWij表示神经元I和神经元j之间的连接权重,OjOj表示神经元j的输出,sigmod是用于将任意实数映射到(0,1 )区间的特殊函数。
上述sigmod函数被称为神经元激发函数(activation function ),除了sigmod函数11 eIl11 eIl之外,还经常使用tanh和ReLU函数。
我们用结束训练的神经网络处理回归问题,每个样本有n个输入。相应地神经网络有n个输入神经元和1个输出神经元。
在实际应用中,我们通常在输入层中添加偏置神经元,以提供可控的输入修改,或者为每个抑制层神经元设置偏移参数
我们把n个特征依次发送到输入神经元,抑制层神经元得到输入层的输出计算自输出值,输出层神经元根据抑制层的输出计算回归值。
上述过程通常被称为前馈过程,在该过程中神经网络的输入和输出与多维函数相同。
现在我们的问题是如何训练这个神经网络.
作为监控学习算法,BP神经网络的训练过程是基于前馈得到的预测值与参考值的比较,根据误差调整连接权重WijWij的过程。
训练过程称为反向传播过程(BackPropagation ),数据流与前馈过程正好相反。
首先,我们随机初始化连接权重WijWij,对某训练样本进行一次前馈过程,得到各神经元的输出。
首先计算输出层的误差:
EJ=SIGmod () OJ ) ) tjoj )=OJ ) 1OJ ) ) ) ) )。
EJ=SIGmod () OJ ) ) tjoj )=OJ ) 1OJ ) ) ) ) )。
其中,EjEj表示神经元j的误差,OjOj表示神经元j的输出,TjTj表示当前训练样本的参考输出,并且SIGmod’(x ) SIG mod’(x ) x是上述SIG mod函数的一阶导数。
计算隐含层误差:
EJ=SIGmod () OJ )kEkWjk=OJ ) 1OJ ) kekwjk
EJ=SIGmod () OJ )kEkWjk=OJ ) 1OJ ) kekwjk
隐含图层的输出中不存在参照值,用“tjoj”“tjoj”替换下一个图层的误差加权和。
误差计算结束后,可以更新WijWij和jj:
Wij=Wij EjOi
Wij=Wij EjOi
这里是被称为学习率的参数,一般在(0,0.1 )区间取值。
实际上,为了提高学习效率,引入了一种称为矫正矩阵的机制,矫正矩阵记录了上一次反向传播过程中的EjOiEjOi值,从而使WjWj更新公式为:
Wij=Wij EjOi Cij
Wij=Wij EjOi Cij
是称为矫正率的参数,然后更新矫正矩阵:
Cij=EjOi
Cij=EjOi
每个训练样本都会更新整个网络的参数
.我们需要额外设置训练终止的条件.最简单的训练终止条件为设置最大迭代次数, 如将数据集迭代1000次后终止训练.
单纯的设置最大迭代次数不能保证训练结果的精确度, 更好的办法是使用损失函数(loss function)作为终止训练的依据.
损失函数可以选用输出层各节点的方差:
L=∑j(Tj−Oj)2
L=∑j(Tj−Oj)2
为了避免神经网络进行无意义的迭代, 我们通常在训练数据集中抽出一部分用作校验.当预测误差高于阈值时提前终止训练.
Python实现BP神经网络首先实现几个工具函数:
def rand(a, b): return (b - a) * random.random() + adef make_matrix(m, n, fill=0.0): # 创造一个指定大小的矩阵 mat = [] for i in range(m): mat.append([fill] * n) return mat定义sigmod函数和它的导数:def sigmoid(x): return 1.0 / (1.0 + math.exp(-x))def sigmod_derivate(x): return x * (1 - x)定义BPNeuralNetwork类, 使用三个列表维护输入层,隐含层和输出层神经元, 列表中的元素代表对应神经元当前的输出值.使用两个二维列表以邻接矩阵的形式维护输入层与隐含层, 隐含层与输出层之间的连接权值, 通过同样的形式保存矫正矩阵.
定义setup方法初始化神经网络:
def setup(self, ni, nh, no): self.input_n = ni + 1 self.hidden_n = nh self.output_n = no # init cells self.input_cells = [1.0] * self.input_n self.hidden_cells = [1.0] * self.hidden_n self.output_cells = [1.0] * self.output_n # init weights self.input_weights = make_matrix(self.input_n, self.hidden_n) self.output_weights = make_matrix(self.hidden_n, self.output_n) # random activate for i in range(self.input_n): for h in range(self.hidden_n): self.input_weights[i][h] = rand(-0.2, 0.2) for h in range(self.hidden_n): for o in range(self.output_n): self.output_weights[h][o] = rand(-2.0, 2.0) # init correction matrix self.input_correction = make_matrix(self.input_n, self.hidden_n) self.output_correction = make_matrix(self.hidden_n, self.output_n)定义predict方法进行一次前馈, 并返回输出:
def predict(self, inputs): # activate input layer for i in range(self.input_n - 1): self.input_cells[i] = inputs[i] # activate hidden layer for j in range(self.hidden_n): total = 0.0 for i in range(self.input_n): total += self.input_cells[i] * self.input_weights[i][j] self.hidden_cells[j] = sigmoid(total) # activate output layer for k in range(self.output_n): total = 0.0 for j in range(self.hidden_n): total += self.hidden_cells[j] * self.output_weights[j][k] self.output_cells[k] = sigmoid(total) return self.output_cells[:]定义back_propagate方法定义一次反向传播和更新权值的过程, 并返回最终预测误差:
def back_propagate(self, case, label, learn, correct): # feed forward self.predict(case) # get output layer error output_deltas = [0.0] * self.output_n for o in range(self.output_n): error = label[o] - self.output_cells[o] output_deltas[o] = sigmod_derivate(self.output_cells[o]) * error # get hidden layer error hidden_deltas = [0.0] * self.hidden_n for h in range(self.hidden_n): error = 0.0 for o in range(self.output_n): error += output_deltas[o] * self.output_weights[h][o] hidden_deltas[h] = sigmod_derivate(self.hidden_cells[h]) * error # update output weights for h in range(self.hidden_n): for o in range(self.output_n): change = output_deltas[o] * self.hidden_cells[h] self.output_weights[h][o] += learn * change + correct * self.output_correction[h][o] self.output_correction[h][o] = change # update input weights for i in range(self.input_n): for h in range(self.hidden_n): change = hidden_deltas[h] * self.input_cells[i] self.input_weights[i][h] += learn * change + correct * self.input_correction[i][h] self.input_correction[i][h] = change # get global error error = 0.0 for o in range(len(label)): error += 0.5 * (label[o] - self.output_cells[o]) ** 2 return error定义train方法控制迭代, 该方法可以修改最大迭代次数, 学习率λλ, 矫正率μμ三个参数.
def train(self, cases, labels, limit=10000, learn=0.05, correct=0.1): for i in range(limit): error = 0.0 for i in range(len(cases)): label = labels[i] case = cases[i] error += self.back_propagate(case, label, learn, correct)编写test方法,演示如何使用神经网络学习异或逻辑:
def test(self): cases = [ [0, 0], [0, 1], [1, 0], [1, 1], ] labels = [[0], [1], [1], [0]] self.setup(2, 5, 1) self.train(cases, labels, 10000, 0.05, 0.1) for case in cases: print(self.predict(case))完整源代码参见bpnn.py
整理不易,如果觉得有所帮助,希望可以留下您的精彩言论再走。赶快为你们最喜欢的框架打Call吧。
大家如果需要Python的学习资料可以加我的Qun:834179111,小编整理了,从Python入门零基础到项目
实战的资料。欢迎还没有找到方向的小伙伴来学习。
本文转自网络 如有侵权 请联系小编删除