前言
在学习编写ADP算法程序时,需要用到神经网络以及神经网络的梯度,原本想采用自编神经网络函数,但训练的特别麻烦,还需要写收敛算法,用牛顿方法或最小二乘方法,精度和效果也不好。所以,研究了一下如何利用MATLAB的神经网络工具箱进行训练,并且如何写出训练好的BP神经网络函数,以及如何写出其导数。
一、MATLAB神经网络工具箱的调用——BP神经网络
采用代码的方式创建神经网络。
数据集为x,写成行向量的形式(每个
x
i
x_i
xi数据是列向量,以
[
x
1
,
x
2
,
.
.
.
,
x
n
]
[x_1,x_2,...,x_n]
[x1,x2,...,xn]的形式拼在一起);
结果为u,也要写成行向量的形式。
%% 搭建网络
net = newff(x, u, 8, {'tansig', 'purelin'},'trainlm'); % 建立BP神经网络,8个隐藏层节点,激活函数为tansig形式
%% 网络参数
net.trainParam.show = 10; % 每10轮回显示一次结果
net.trainParam.epochs = 5000; % 最大训练次数
net.trainParam.lr = 0.02; % 网络的学习速率
net.trainParam.goal = 1e-5; % 训练网络所要达到的目标误差
net.divideFcn = ''; % 网络误差如果连续6次迭代都没变化,则matlab会默认终止训练。为了让程序继续运行,用以下命令取消这条设置
%% 训练
net = train(net, x, u,'useGPU','only'); % 调用GPU加快训练速度
二、BP神经网络函数化表示
1.函数表示
设计的BP神经网络可以表示为如下形式
F N = W 2 tanh ( W 1 X + B 1 ) + B 2 {F_N} = {W_2}\tanh \left( {{W_1}X + {B_1}} \right) + {B_2} FN=W2tanh(W1X+B1)+B2
代码如下所示:
%% 从神经网络工具箱中获取训练好的参数
w1 = net.iw{1,1};
b1 = net.b{1};
w2 = net.lw{2,1};
b2 = net.b{2};
z_n = purelin(w2*tansig(w1*x_n + b1) + b2); % 神经网络拟合函数 记为(a)
可以注意到这里输入和输出分别是x_n和z_n,这是因为在新版的神经网络工具箱中会自动自动对输入和输出的数据进行归一化,x_n和z_n是归一化后的结果。
2.归一化的修正
归一化采用的是mapminmax()函数。
输入是x,归一化后的输出是y,归一化的区间是
[
−
1
,
1
]
[-1,1]
[−1,1],归一化的公式如下所示:
y
=
(
y
m
a
x
−
y
m
i
n
)
∗
(
x
−
x
m
i
n
)
/
(
x
m
a
x
−
x
m
i
n
)
+
y
m
i
n
;
y = (y_{max}-y_{min})*(x-x_{min})/(x_{max}-x_{min}) + y_{min};
y=(ymax−ymin)∗(x−xmin)/(xmax−xmin)+ymin;
在mapminmax()提供的参数中可以表示为:
x
n
=
(
x
−
x
o
f
f
s
e
t
)
∗
k
−
1
;
x_n = (x -x_{offset})*k - 1;
xn=(x−xoffset)∗k−1;
所以将上面代码的最后一句(a)替换为进行归一化后的代码,如下所示:
%% 这是只是求神经网络工具箱归一化的参数,并不作为训练的输入
[x_, inputStr1] = mapminmax(x); % 输入
[u_, outputStr1] = mapminmax(u); % 结果
%% 取出归一化的参数
k1 = inputStr1.gain;
k2 = outputStr1.gain;
off1 = inputStr1.xoffset;
off2 = outputStr1.xoffset;
%% 函数表达
x_n = (x - off1).*k1 - 1;
z_n = purelin(w2*tansig(w1*x_n + b1) + b2); % 神经网络拟合函数
z = (z_n + 1)./k2 + off2;
这就实现了BP神经网络的函数化表示。
F
N
′
=
W
2
{
W
1
[
1
−
tanh
(
W
1
X
+
B
1
)
⋅
×
tanh
(
W
1
X
+
B
1
)
]
}
\begin{array}{rl} F_{N}^{\prime}=W_{2}\left\{W_{1}\left[1-\tanh \left(W_{1} X+B_{1}\right) \cdot \times \tanh \left(W_{1} X+B_{1}\right)\right]\right\} \end{array}
FN′=W2{W1[1−tanh(W1X+B1)⋅×tanh(W1X+B1)]}
三、BP神经网络梯度\求导函数
BP神经网络的梯度表达为:
F
N
′
=
W
2
{
W
1
[
1
−
tanh
(
W
1
X
+
B
1
)
⋅
×
tanh
(
W
1
X
+
B
1
)
]
}
\begin{array}{rl} F_{N}^{\prime}=W_{2}\left\{W_{1}\left[1-\tanh \left(W_{1} X+B_{1}\right) \cdot \times \tanh \left(W_{1} X+B_{1}\right)\right]\right\} \end{array}
FN′=W2{W1[1−tanh(W1X+B1)⋅×tanh(W1X+B1)]}
但这里也要注意归一化,故修正为:
F
N
′
=
W
2
{
(
W
1
⋅
×
K
1
T
)
[
1
−
tanh
(
W
1
X
+
B
1
)
⋅
×
tanh
(
W
1
X
+
B
1
)
]
}
\begin{array}{rl} F_{N}^{\prime}=W_{2}\left\{(W_{1}\cdot \times K_1^T)\left[1-\tanh \left(W_{1} X+B_{1}\right) \cdot \times \tanh \left(W_{1} X+B_{1}\right)\right]\right\} \end{array}
FN′=W2{(W1⋅×K1T)[1−tanh(W1X+B1)⋅×tanh(W1X+B1)]}
导数的拟合效果确实差了一些,在数据足够多的时候,还是比较接近的。
全部代码放在了文件全部的BP网络函数化的程序中。
总结
尝试了BP神经网络函数化表示,并推导出BP神经网络梯度\求导函数。