传送门
- BP神经网络
- 简述
- 流程
- BP神经网络PID控制算法(BPNN-PID)
- 与单神经元PID控制算法的对比
- 前向激励
- 反向传播
- matlab仿真
- 总结
BP神经网络
简述
老规矩不废话,直接上链接 BP神经网络维基百科 BP神经网络是人工神经网络中的一种常用结构,其由输入层(input)-隐含层(hidding)-输出层三层构成(output)。
上图中,是输入层,是隐含层,是输出层,是输入-隐含层之间的权重系数矩阵,是隐含-输出层的权重系数矩阵,是隐含层神经元函数的激励函数,是隐含层神经元的偏置阈值,是输出层神经元的激励函数,是输出层神经元的偏置阈值。
假设输入向量为,输入-隐含层系数矩阵为,则隐含层的中每个神经元的输出为:
对于偏置阈值来说,同样也会影响到损失函数的大小,因此也要将其和权重系数一样作为可变参数,应用梯度下降求解最优值。
利用矩阵运算的技巧,假设输入层的输入为1x3的向量,对应的权重系数为,则为了方便计算,可以将输入向量变为,相应的权重系数会多出一行变为,最后这一行就对应每一个隐含层神经元的偏置阈值。
流程
BP神经网络的运作机理主要包含两个流程
- 前向激励传播:将输入送入网络进行运算获得结果。
- 反向传播更新权重:将运算结果得到的反馈信息计算损失函数,以最优化目标更新各神经元连接权重值。
BP神经网络PID控制算法(BPNN-PID)
与单神经元PID控制算法的对比
从输入输出关系上来看,单神经元PID控制算法输入三项误差项,输出控制律。而BP神经网络输入的是系统输入,系统输出,系统误差,输出的是PID参数。可以理解成BP神经网络根据系统输入输出和误差项的信息和损失函数的反馈来不断迭代优化各位置的权重系数,以实现损失函数达到最小的目的。
为什么输入的三项分别是而不是其他的变量。
- 首先排除妈妈生的(狗头)
- 个人认为,在进行权值更新的损失函数就是以系统误差作为基础进行计算的——,因此对于整个BP神经网络部分来说,输出的PID系数值的优劣(以损失函数大小评判)是直接和输入以及二者的差决定的。因此才将这三个作为BP神经网络的输入变量。
- 从神经网络的角度来说,输入的数据是服务于损失函数的训练样本,样本中就需要包含训练结果()及参考答案()以及他们的差距。当然输入的信息不是一成不变的,根据不同的代价函数和系统结构,可以提供更多数据类型来达到最终的收敛目的。
前向激励
在BPNN-PID控制算法中,前向激励是指从输入层信号输入通过隐含层最终从输出层输出的通道,也是算法中的主要流程之一。
- 假设隐含层中的神经元个数为,隐含层和输出层的激励函数分别为:
- 假设从输入层-隐含层的权重系数为,隐含层-输出层的权重系数为。对应的系数矩阵分别为
假设三个输入分别为,则隐含层第一个神经元的输入为
假设隐含层N个输出为,则输出层第一个神经元的输入为
此处内容用于辅助理解权重系数下标数字的含义,为后续公式推导提供帮助
- 为了简化公式,采用矩阵形式来描述前向激励过程。输入向量为
1x3的行向量
,则隐含层的输入向量为
显然为1xN的行向量
。
隐含层的激励函数为,则隐含层的激励输出为
显然,对向量的每一个元素进行函数映射转换后,不改变其向量的维度,仍然为1xN的行向量
。
输出层的神经元输入向量为1x3的行向量
为
输出层的神经元激励输出向量为1x3的行向量
为
在matlab中,对一个向量或者矩阵进行函数运算会得到维度相同的新向量或新矩阵,其元素是原先向量或矩阵中每个元素经过函数之后的结果。
- 控制算法输出的是三个参数,即。
设误差向量3x1列向量
为
根据增量PID公式计算控制器增量
则控制律公式为
假设系统函数满足以下关系
其中为状态量,为系统输出,可以为任意形式的函数形式,包括各类非线性函数。
反向传播
反向传播的目的是根据系统响应结果,来判断当前系统参数的优化方向,使得系统响应按照期望的方向演变。
- 如何评价响应结果
对于机器来说,它判断当前系统响应状态好坏的方式只能是通过数值,因此需要定义能够描述系统响应标准的数学表达式,以表达式的计算结果衡量响应结果。这种数学表达式就是损失函数cost function
,也可以称作代价函数。常见的表达式为:
其中,分别系统期望和系统状态。显然,越小,系统的响应性能越好。 - 如何判断系统参数的优化方向
从数值上很容易看出,我们优化的目的就是让损失函数尽可能的变小甚至达到并保持在0。也就是说,损失函数下降的方向就是优化的方向,在工程上一般用梯度下降法来实现。而能够影响到损失函数数值大小的系统参数只有各层之间的权重系数(若神经元中的偏置阈值不恒为0的话同样会作为系统参数影响损失函数数值大小,此文中不讨论)。
以下为梯度下降法的基本公式基本公式(式1)和动量梯度下降法(式2)
其中,为学习速率或者叫下降步长,为惯性因子。
在整个神经网络中,存在着总共个权重系数,为了找到最优的方向,则令对每个权重系数求偏导,根据梯度下降法得到变化值,最终完成整个网络参数的优化迭代。以输入层-隐含层权重系数 为例,它是第一个输入连接隐含层第一个神经元的权重系数,则它的梯度下降过程为:
这里面设计到对向量求偏导,对矩阵求偏导,其本质是复合函数的求偏导,因为将矩阵运算拆开来就是线性方程组,其本质依然是链式求偏导法则。
例如, = [,,],=[,,]。并且满足,则可以将等效成:
则当我们令对求导时,得到:
其中,分别为:
即。同理可得
当变成一个向量或者是矩阵时,情况稍微复杂一些,但本质是一样的。
假设,令,可以等效成一个方程组:
则当令对向量求导时,得到:
同理可得但事实上这个梯度下降过程的本质是损失函数对每个权值参数的直接求偏导,再将每个结果放回权值矩阵中。
整理可以得到对于输入-隐含层的权重系数的梯度下降公式为:
同理可得,损失函数对隐含-输出层权重系数的梯度下降过程为:
每一项的公式为:
整理可以得到对于隐含-输出层的权重系数的梯度下降公式为:
这里面的矩阵向量直接相乘是不对的,会出现维度不满足矩阵相乘条件的情况。但其实也只需要做一些转置或者元素直接相乘就可以完成。具体的原理用下面的两个图来描述。
这里就是求偏导链式法则的体现,只不过以矩阵形式展示可以简化表达式,这里就不再赘述了,自行推导!
matlab仿真
废话不多说,直接上代码
close,clear all;
warning off
xita = 1; %学习因子
alfa = 0.05; %惯量因子
hl_number = 5; %隐藏层神经元个数
hidding_wi = 0.5*rands(4,hl_number); %4xN
output_wi = 0.5*rands(hl_number+1,3); %Nx3
%抽奖
%初始化隐含层和输出层的两组权重系数
hidding_wi_1 = hidding_wi;
hidding_wi_2 = hidding_wi;
output_wi_1 = output_wi;
output_wi_2 = output_wi;
%权重系数记录
error_1 = 0;error_2 = 0;
u_1 = 0;u_2 = 0;u_3 = 0;
y_1 = 0;y_2 = 0;y_3 = 0;
%控制律及系统状态序列
last_error_ventor = [0;0;0];
ts = 0.001;
for t = 1:1:5000
time(t) = t*ts;
rin(t) = 1*sin(5*2*pi*t*ts);
%输入信号
a(t) = 1.2*(1-0.8*exp(-0.1*t));
y(t) = a(t)*y_1/(1+y_1^2)+u_1;
%系统模型输出
J(t) = 0.5*(rin(t)-y(t))^2;
error(t) = rin(t) - y(t);
%计算误差
x_input = [rin(t),y(t),error(t),1];
%神经网络输入向量 1x4
error_ventor = [error(t)-error_1;error(t);error(t)-2*error_1+error_2];
%计算误差向量 3x1
hiddingLayer_input = x_input * hidding_wi;
%计算隐含层输入 1xN
hiddingLayer_output = (exp(hiddingLayer_input) - exp(-hiddingLayer_input))./(exp(hiddingLayer_input) + exp(-hiddingLayer_input));
%计算隐含层输出 激励函数为 (exp(x) - exp(-x))/(exp(x) + exp(-x) )
%1xN
outputLayer_input_offset = [hiddingLayer_output(:);1]';
%加入输出层神经元的偏置 1x(N+1)
outputLayer_input = outputLayer_input_offset * output_wi;
%计算输出层输入 1x3
outputLayer_output = exp(outputLayer_input) ./ (exp(outputLayer_input) + exp(-outputLayer_input));
%计算输出层输出 1x3
%激励函数为 exp(x) / (exp(x) + exp(-x))
delta_u = outputLayer_output * error_ventor;
%计算控制律增量
u(t) = u_1 + delta_u;
%计算控制律
dJdy = error_1;
dydu = sign((y_1-y_2)/(u_1-u_2+0.0000001));
dudoutput3 = last_error_ventor;
%3x1
doutput3dnet3 = 2 ./((exp(outputLayer_input)+exp(-outputLayer_input)).^2);
%1x3 g'(x)
dnet3dv = outputLayer_input_offset;
%1x(N+1)
delta_output_wi = (xita * dJdy * dydu) .* dudoutput3 .* doutput3dnet3' * dnet3dv + alfa*(output_wi_1-output_wi_2)';
%计算输出层权重增量
output_wi_2 = output_wi_1;
output_wi_1 = output_wi;
output_wi = output_wi_1 + delta_output_wi';
%更新输出层权重系数
dJdy = error_1;
dydu = sign((y_1-y_2)/(u_1-u_2+0.0000001));
dudoutput3 = last_error_ventor;
%3x1
doutput3dnet3 = 2 ./((exp(outputLayer_input)+exp(-outputLayer_input)).^2);
%1x3
dnet3dv = hiddingLayer_output;
%1xN
dnet3doutput2 = output_wi_1(1:hl_number,:);
% Nx3
doutput2dnet2 = 4 ./(exp(hiddingLayer_input)+exp(-hiddingLayer_input)).^2;
% 1x(N) 针对的是N个隐含层神经元
dnet2dw = x_input;
% 1x4 针对三个输入和一个偏置
delta_hidding_wi = ( ( dnet3doutput2 * ( (xita * dJdy *dydu ) .* dudoutput3 .* doutput3dnet3' ) ) .* doutput2dnet2' ) * dnet2dw + alfa * (hidding_wi_1 - hidding_wi_2)';
%计算隐含层权重增量
hidding_wi_2 = hidding_wi_1;
hidding_wi_1 = hidding_wi;
hidding_wi = hidding_wi_1 + delta_hidding_wi';
%更新隐含层权重系数
error_2 = error_1;
error_1 = error(t);
y_3 = y_2;y_2 = y_1;y_1 = y(t);
u_3 = u_2;u_2 = u_1;u_1 = u(t);
last_error_ventor = error_ventor;
%更新序列
end
%绘图
figure(1);
plot(time,rin,'r',time,y,'b','linewidth',2);
xlabel('time(s)');ylabel('rin,yout'); % 输入和输出
运行结果如下图
总结
从测试的规律来看,学习因子对于整个神经网络的影响较大。过大的学习因子会让系统出现振荡,过小的学习因子则会使系统在初始阶段发散,无法收敛(系统参数的初始值是随机产生的)。当然也可以考虑训练出一组较为理想的参数作为系统初始值,再以较小的学习因子来提高控制器的精度,使系统的动态性能提高。
另外,神经网络的迭代周期对于控制器性能的影响也较大,理想上周期越小,系统状态拟合的更好,收敛的越快。