赛博大陆官网
采用增量PID的神经网络有三层,分别为
i
,
j
,
l
i,j,l
i,j,l层,输入层有三个量
x
1
(
k
)
=
e
(
k
)
=
r
(
k
)
−
y
(
k
)
x_1(k)=e(k)=r(k)-y(k)
x1(k)=e(k)=r(k)−y(k)
x
2
(
k
)
=
Δ
e
(
k
)
=
e
(
k
)
−
e
(
k
−
1
)
x_2(k)=\Delta e(k)=e(k)-e(k-1)
x2(k)=Δe(k)=e(k)−e(k−1)
x
3
(
k
)
=
Δ
2
e
(
k
)
=
Δ
e
(
k
)
−
Δ
e
(
k
−
1
)
=
e
(
k
)
−
2
e
(
k
−
1
)
+
e
(
k
−
2
)
x_3(k)=\Delta^2 e(k)=\Delta e(k)-\Delta e(k-1)=e(k)-2e(k-1)+e(k-2)
x3(k)=Δ2e(k)=Δe(k)−Δe(k−1)=e(k)−2e(k−1)+e(k−2)
其中
e
(
k
)
e(k)
e(k)表示
k
k
k时刻的误差,
r
(
k
)
r(k)
r(k)表示
k
k
k时刻的目标值,
y
(
k
)
y(k)
y(k)表示
k
k
k时刻的实际值。
输出层有一个量
Δ
u
(
k
)
=
k
1
x
1
(
k
)
+
k
2
x
2
(
k
)
+
k
3
x
3
(
k
)
\Delta u(k)=k_1x_1(k)+k_2x_2(k)+k_3x_3(k)
Δu(k)=k1x1(k)+k2x2(k)+k3x3(k)
表示
k
k
k时刻控制器应当给出的输入控制量的增量。
训练的目标函数为
J
=
1
2
(
r
(
k
+
1
)
−
y
(
k
+
1
)
)
2
J=\frac{1}{2}(r(k+1)-y(k+1))^2
J=21(r(k+1)−y(k+1))2
训练系数时的导数为
∂
J
∂
w
=
−
λ
∂
J
∂
y
(
k
+
1
)
∂
y
(
k
+
1
)
∂
u
(
k
)
∂
u
(
k
)
∂
w
\frac{\partial J}{\partial w}=-\lambda\frac{\partial J}{\partial y(k+1)}\frac{\partial y(k+1)}{\partial u(k)}\frac{\partial u(k)}{\partial w}
∂w∂J=−λ∂y(k+1)∂J∂u(k)∂y(k+1)∂w∂u(k)
当系统未知时,
∂
y
(
k
+
1
)
∂
u
(
k
)
\frac{\partial y(k+1)}{\partial u(k)}
∂u(k)∂y(k+1)无法求出,采用NNI辨识对象模型,估计出
∂
y
^
(
k
+
1
)
∂
u
(
k
)
\frac{\partial \hat{y}(k+1)}{\partial u(k)}
∂u(k)∂y^(k+1),如果不采用辨识器,则用
s
g
n
(
∂
y
(
k
+
1
)
∂
u
(
k
)
)
sgn(\frac{\partial y(k+1)}{\partial u(k)})
sgn(∂u(k)∂y(k+1))或
y
(
k
+
1
)
−
y
(
k
)
u
(
k
)
−
u
(
k
−
1
)
\frac{y(k+1)-y(k)}{u(k)-u(k-1)}
u(k)−u(k−1)y(k+1)−y(k)代替,由此带来的计算不精确可通过调整学习率
η
\eta
η来补偿。
通过计算可以知道网络输出层权系数的学习算法为
Δ
w
j
l
3
(
k
)
=
α
Δ
w
j
l
3
(
k
−
1
)
+
η
δ
l
3
O
j
2
(
k
)
\Delta w_{jl}^3(k)=\alpha\Delta w_{jl}^3(k-1)+\eta\delta_l^3O_j^2(k)
Δwjl3(k)=αΔwjl3(k−1)+ηδl3Oj2(k)
δ
l
3
=
e
(
k
)
s
i
g
n
(
∂
y
o
u
t
(
k
)
∂
u
(
k
)
)
⋅
∂
u
(
k
)
∂
O
l
3
(
k
)
⋅
g
′
(
n
e
t
l
3
(
k
)
)
\delta_l^3=e(k)sign(\frac{\partial yout(k)}{\partial u(k)})\cdot\frac{\partial u(k)}{\partial O_l^3(k)}\cdot g'(net_l^3(k))
δl3=e(k)sign(∂u(k)∂yout(k))⋅∂Ol3(k)∂u(k)⋅g′(netl3(k))
同样,隐层学习算法为
Δ
w
i
j
3
=
a
Δ
w
i
j
2
(
k
−
1
)
+
η
δ
i
2
O
j
l
(
k
)
\Delta w_{ij}^3=a\Delta w_{ij}^2(k-1)+\eta\delta_i^2O_j^l(k)
Δwij3=aΔwij2(k−1)+ηδi2Ojl(k)
δ
j
2
(
k
)
=
f
′
(
n
e
t
j
2
(
k
)
)
∑
l
=
1
3
δ
l
3
w
j
l
3
(
k
)
\delta_j^2(k)=f'(net_j^2(k))\sum_{l=1}^3\delta_l^3w_{jl}^3(k)
δj2(k)=f′(netj2(k))l=1∑3δl3wjl3(k)
f
(
x
)
=
e
x
p
(
x
)
−
e
x
p
(
−
x
)
e
x
p
(
x
)
+
e
x
p
(
−
x
)
f(x)=\frac{exp(x)-exp(-x)}{exp(x)+exp(-x)}
f(x)=exp(x)+exp(−x)exp(x)−exp(−x)
g
(
x
)
=
e
x
p
(
x
)
e
x
p
(
x
)
+
e
x
p
(
−
x
)
g(x)=\frac{exp(x)}{exp(x)+exp(-x)}
g(x)=exp(x)+exp(−x)exp(x)
其中
O
1
3
(
k
)
=
K
p
,
O
2
3
(
k
)
=
K
i
,
O
3
3
(
k
)
=
K
d
O_1^3(k)=K_p,O_2^3(k)=K_i,O_3^3(k)=K_d
O13(k)=Kp,O23(k)=Ki,O33(k)=Kd
∂
u
(
k
)
∂
O
1
3
(
k
)
=
e
(
k
)
\frac{\partial u(k)}{\partial O_1^3(k)}=e(k)
∂O13(k)∂u(k)=e(k)
∂
u
(
k
)
∂
O
2
3
(
k
)
=
e
(
k
)
−
e
(
k
)
\frac{\partial u(k)}{\partial O_2^3(k)}=e(k)-e(k)
∂O23(k)∂u(k)=e(k)−e(k)
∂
u
(
k
)
∂
O
3
3
(
k
)
=
e
(
k
)
−
2
e
(
k
−
1
)
+
e
(
k
−
2
)
\frac{\partial u(k)}{\partial O_3^3(k)}=e(k)-2e(k-1)+e(k-2)
∂O33(k)∂u(k)=e(k)−2e(k−1)+e(k−2)
NNI辨识器
输入层为
u
(
k
)
,
u
(
k
−
1
)
,
…
,
u
(
k
−
n
u
+
1
)
,
y
(
k
)
,
y
(
k
−
1
)
,
…
,
y
(
k
−
n
y
+
1
)
u(k),u(k-1),\dots,u(k-n_u+1),y(k),y(k-1),\dots,y(k-n_y+1)
u(k),u(k−1),…,u(k−nu+1),y(k),y(k−1),…,y(k−ny+1)
输出层为一个量,训练的目标函数为
J
=
1
2
(
y
(
k
+
1
)
−
y
^
(
k
+
1
)
)
2
J=\frac{1}{2}(y(k+1)-\hat{y}(k+1))^2
J=21(y(k+1)−y^(k+1))2
%% 定义神经网络结构
classdef PID_NN
properties %PID_NN网络参数
num_neuron_1=3; %神经元个数1
num_neuron_2=0; %神经元个数2
num_neuron_3=3; %神经元个数3
W_1=[]; %权重1
W_2=[]; %权重2
b_1=[]; %偏置1
b_2=[]; %偏置2
delta_2=[]; %梯度1
delta_3=[]; %梯度2
net_2=[]; %网络节点值1
net_3=[]; %网络节点值2
eta=10; %学习率
% f=@(x)(tanh(x));%激活函数1
% df=@(x)(4*exp(2*x))./(1+exp(4*x)+2*exp(2*x)); %导函数1
% g=@(x)(logsig(x)); %激活函数2
% dg=@(x)((1./(1+exp(-x))).*(1-(1./(1+exp(-x))))); %导函数2
trainData_x=[]; %训练数据x
trainData_y=[]; %训练数据y
batch_size=100; %训练批次的大小
N_sample=0; %训练数据的总量
end
methods
function obj=PID_NN(num) %构造函数
obj.num_neuron_2=num;
end
function [obj]=train(obj,trainData_x,trainData_e,Iter,model)%训练
%输入参数为,训练数据x,训练数据y,辨识器数据y_partial_u,迭代次数Iter,模型model
%初始化参数
obj.num_neuron_1=size(trainData_x,2);
% obj.num_neuron_3=size(trainData_e,2);
obj.N_sample=size(trainData_x,1);
obj.b_1=rand(1,obj.num_neuron_2);
obj.b_2=rand(1,obj.num_neuron_3);
obj.W_1=rand(obj.num_neuron_1,obj.num_neuron_2);
obj.W_2=rand(obj.num_neuron_2,obj.num_neuron_3);
obj.batch_size=1;
y_partial_u=model.df(model.input(2:end))';
%训练
for i=1:Iter
rand_index=randperm(obj.N_sample , obj.batch_size);
trainData_x_batch=trainData_x(rand_index,:);
trainData_e_batch=-trainData_e(rand_index,:);
y_partial_u_batch=y_partial_u(rand_index,:);
[net_2_,~,net_20,net_30]=Forward_propagation(obj,trainData_x_batch);%计算向前传播
delta_3_=repmat(trainData_e_batch.*y_partial_u_batch,1,obj.num_neuron_3).*dg(net_30).*trainData_x_batch;
delta_w_3=obj.eta*net_2_'*delta_3_;
delta_2_=df(net_20).*repmat((sum(delta_3_,1)*obj.W_2'),obj.batch_size,1);
delta_w_2=obj.eta*trainData_x_batch'*delta_2_;
obj.W_1=obj.W_1-delta_w_2;
obj.W_2=obj.W_2-delta_w_3;
obj.b_1=obj.b_1-obj.eta*sum(delta_2_,1);
obj.b_2=obj.b_2-obj.eta*sum(delta_3_,1);
% disp(sum(delta_3_,1))
end
obj.delta_2=delta_2_;
obj.delta_3=delta_3_;
end
function [obj]=train2(obj,trainData_x,trainData_y,Iter)%训练
%输入参数为,训练数据x,训练数据y,辨识器数据y_partial_u,迭代次数Iter,模型model
%初始化参数
obj.num_neuron_1=size(trainData_x,2);
obj.num_neuron_3=size(trainData_y,2);
obj.N_sample=size(trainData_x,1);
obj.b_1=rand(1,obj.num_neuron_2);
obj.b_2=rand(1,obj.num_neuron_3);
obj.W_1=rand(obj.num_neuron_1,obj.num_neuron_2)*0.01;
obj.W_2=rand(obj.num_neuron_2,obj.num_neuron_3)*0.01;
obj.batch_size=obj.N_sample;
obj.batch_size=1;
%训练
for i=1:Iter
rand_index=randperm(obj.N_sample , obj.batch_size);
trainData_x_batch=trainData_x(rand_index,:);
trainData_y_batch=trainData_y(rand_index,:);
[net_2_,net_3_,net_20,net_30]=Forward_propagation(obj,trainData_x_batch);%计算向前传播
trainData_e_batch=net_3_-trainData_y_batch;
% net_30
% dg(net_30)
delta_3_=trainData_e_batch.*dg(net_30);
delta_w_3=obj.eta*net_2_'*delta_3_;
% net_20
% df(net_20)
delta_2_=df(net_20).*repmat((sum(delta_3_,1)*obj.W_2'),obj.batch_size,1);
delta_w_2=obj.eta*trainData_x_batch'*delta_2_;
obj.W_1=obj.W_1-delta_w_2;
obj.W_2=obj.W_2-delta_w_3;
obj.b_1=obj.b_1-obj.eta*sum(delta_2_,1);
obj.b_2=obj.b_2-obj.eta*sum(delta_3_,1);
end
obj.delta_2=delta_2_;
obj.delta_3=delta_3_;
end
function [net_2,net_3,net_20,net_30]=Forward_propagation(obj,trainData_x_batch)
net_20=trainData_x_batch*obj.W_1+obj.b_1;
net_2=tanh(net_20);
net_30=net_2*obj.W_2+obj.b_2;
net_3=logsig(net_30);
end
%--------------------------
function obj=output(obj,e) %输出对象被调量
obj.e=e;
obj.delta_u=obj.K_P*obj.e(end) + obj.K_I*sum(obj.e,2) + ...
obj.K_D*(obj.e(end)-obj.e(end-1));
end
end
end
pidnn=PID_NN(10);
%% 设置参数
trainData_x_batch=([0 0 0]);
num_thread=size(trainData_x_batch,1);%设置并行模拟的线程数
input=0; %系统对象的输入
model=Model(input); %创建系统对象
pid(1:num_thread)=PID(0.1,0.7,0.003); %创建PID控制器
targetValue=repmat([ones(1,20) zeros(1,20)],1,20);
model(1:num_thread).targetValue=targetValue; %设置系统输出目标值
%% 产生训练数据
[trainData_x,trainData_y]=PID_Data(model(1),pid);
%% 训练网络
pidnn=pidnn.train(trainData_x,trainData_y,10);
%% 仿真
model_list=simulink_with_NN(pidnn,pid,model,trainData_x_batch);
%% 绘制动态图
close all;
figureout(model_list(1));
%% 定义PID控制器结构
classdef PID
properties %PID控制器参数
% k=10;
e=[]; %长度为k的列表,存储了最近k步的偏差记录
K_P=0; %比例元系数
K_I=0; %积分元系数
K_D=0; %微分元系数
delta_u=0;
end
methods
function obj=PID(K_P,K_I,K_D) %构造函数
obj.K_P=K_P;
obj.K_I=K_I;
obj.K_D=K_D;
end
function obj=output_1(obj,e)%输出对象被调量——位置式
obj.e=e;
obj.delta_u=obj.K_P*obj.e(end) + obj.K_I*sum(obj.e,2) + ...
obj.K_D*(obj.e(end)-obj.e(end-1));
end
function obj=output_2(obj,e)%输出对象被调量——增量式
obj.e=e;
obj.delta_u=obj.K_P*(obj.e(end)-obj.e(end-1)) + ...
obj.K_I*sum(obj.e(end)) + ...
obj.K_D*(obj.e(end)-2*obj.e(end-1)+obj.e(end-2));
end
end
end
%% 定义模型
classdef Model
properties %系统模型参数
input=0; %模型输入
output=0; %模型输出
e_list=[]; %模型误差
K_list=[];
targetValue=0;
f=@(x)(x); %模型函数
df=@(x)(1+x*0);
end
methods
function obj=Model(input) %构造函数
obj.input=input;
obj.output=obj.f(input);
end
function obj=step(obj,input)%步进输出函数
obj.input=[obj.input input];
obj.output=[obj.output obj.f(input)];
end
function obj=target(obj,targetValue)%步进输出函数
obj.targetValue=targetValue;
end
end
end
function [model,trainData_x,trainData_y]=simulink_with_NN(obj,pid,model,trainData_x_batch)
%% PID控制过程
num_thread=size(trainData_x_batch,1);%设置并行模拟的线程数
% k=3; %误差长度
e=trainData_x_batch; %误差
size(model(1).targetValue,2)
for j=1:size(model(1).targetValue,2)
for i=1:num_thread %依次对每个线程进行计算
[~,net_3]=Forward_propagation(obj,e);
model.K_list=[model.K_list;net_3];
pid(i).K_P=net_3(i,1)*0.05;
pid(i).K_I=net_3(i,2)*0.05;
pid(i).K_D=net_3(i,3)*0.05;
% pid(i).K_P=0.1;
% pid(i).K_D=0.005;
e0=model(i).targetValue(j)-model(i).output(end);
model(i).e_list=[model(i).e_list e0];
e=[e(2:end) e0];
pid(i)=pid(i).output_2(e);
input0=model(i).input(end) + pid(i).delta_u(end);
model(i)=model(i).step(input0);
end
end
%% 整理出系统对象运行的训练数据
x1=model.e_list(3:end);
x2=model.e_list(3:end)-model.e_list(2:end-1);
x3=model.e_list(3:end)-2*model.e_list(2:end-1)+model.e_list(1:end-2);
trainData_x=[x1' x2' x3'];
trainData_y=x1';
trainData_x(end,:)=[];
trainData_y(1,:)=[];
end
%% 为PID_NN提供系统对象的训练数据和辨识器输出——离线训练
function [model,trainData_x,trainData_y]=PID_Data(model,pid)
% tic
%% PID控制过程
k=5;%误差长度
e=zeros(1,k);%误差
for i=1:size(model.targetValue,2)
e0=model.targetValue(i)-model.output(end);
model.e_list=[model.e_list e0];
e=[e(2:end) e0];
pid=pid.output_2(e);
input0=model.input(end);% + pid.delta_u(end);
model=model.step(input0);
end
toc
%% 整理出系统对象运行的训练数据
x1=model.e_list(3:end);
x2=model.e_list(3:end)-model.e_list(2:end-1);
x3=model.e_list(3:end)-2*model.e_list(2:end-1)+model.e_list(1:end-2);
trainData_x=[x1' x2' x3'];
trainData_y=x1';
trainData_x(end,:)=[];
trainData_y(1,:)=[];
%% 给出辨识器数据
% [y_partial_u]=Identifier(model.df,model.input(3:end-1));
end
%% 定义动态图展示函数
function figureout(model)
figure;
%设置图像背景
colordef white;
set(gcf,'Units','normalized','Position',[0 0 1 1]);
for i=1:size(model.input,2)-1
% plot(1:i,model.output(i:-1:1),'b-')
plot([1:i;1:i]',[model.output(i:-1:1);model.targetValue(i:-1:1)]')
%画出轨迹上的点
line('xdata',1,'ydata',model.output(:,i),'Color','b','Marker','.','MarkerSize',40);
filed_y=[min(model.output) max(model.output) max(model.output)-min(model.output)];
axis([0,size(model.input,2),filed_y(1)-0.15*filed_y(3),filed_y(2)+0.15*filed_y(3)]);
drawnow;
end
legend('实际值','目标值')
end