初学CMAC,在网上搜了半天,找到的CMAC程序看起来效果可以的,发现实际上是《先进PID控制MATLAB仿真(第二版)》( 作者:刘金琨 著 出版社:电子工业出版社)P186页的例子。
对该例子进行整理,规划出了几个功能函数。例如,CMAC的网络输出计算函数,程序如下:
function ym=CmacOut(u,M,N,C,w_1,xmin,xmax)%(u(k),y(k),M,N,C,w_1,w_2,xite,alfa,xmin,xmax) %计算给定权值下CMAC网络的输出 %SISO系统CMAC神经网络的训练函数,本函数是在网上下载例程的基础上修正而来 %在这一次计算中,可以计算出CMAC网络的权值,并可以依据前步w值估算出当前的y值,即ym %来自于对《先进PID控制MATLAB仿真(第二版)》P186页的例子整理所得结果 %输入参数中,u为网络输入;M为量化系数;N为权向量的个数;C为泛化系数;w_1为权向量的初始值 %xmin和xmax为网络输入参数u的下限和上限 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%初始化%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% w=w_1; %权向量增值的初始值 k=1;
s(k)=round((u(k)-xmin)*M/(xmax-xmin)); %量化,其中xmax为输入u的最大值, %其中xmin为输入u的最小值 数据挖掘论坛
sum=0; for i=1:1:C %图形匹配和Hash变换:起始地址 ad(i)=mod(s(k)+i,N)+1; %Table mapping and Hash transfer:Start address %i=1为C个地址中的起始地址 sum=sum+w(ad(i)); %对起始地址开始的C个连续地址中对应的权值叠加 end
ym(k)=sum; %叠加所得和为网络给出来的估值 ym=ym(k);
CMAC的网络权值更新函数,程序如下: function w=CmacUpdate(u,err,M,N,C,w_1,w_2,xite,alfa,xmin,xmax)%(u(k),y(k),M,N,C,w_1,w_2,xite,alfa,xmin,xmax) %依据偏差信号修正CMAC网络的权值 %SISO系统CMAC神经网络的训练函数,本函数是在网上下载例程的基础上修正而来 %在这一次计算中,可以计算出CMAC网络的权值,并可以依据前步w值估算出当前的y值,即ym %来自于对《先进PID控制MATLAB仿真(第二版)》P186页的例子整理所得结果 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%初始化%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% w=w_1; %权向量增值的初始值 d_w=zeros(length(w),1); %权向量增值的初始值 k=1; s(k)=round((u(k)-xmin)*M/(xmax-xmin)); %量化,其中xmax为输入u的最大值, 数据挖掘工具 %其中xmin为输入u的最小值
d_w=xite*err(k)/C; %偏差与系数的乘积,参见42页式2.16
for i=1:1:C ad(i)=mod(s(k)+i,N)+1; %i=1为C个地址中的起始地址 w(ad(i))=w_1(ad(i))+ d_w+alfa*(w_1(ad(i))-w_2(ad(i))); %权系数的更新 end
%%%% Parameters Update %%%% w_2=w_1; %权向量的前两次值,进行更新 w_1=w; %权向量的前一次值,进行更新
然后,我发现CMAC的效果远不如例子给出的效果好。我发现书中给出的这个例子实际上是混淆了一个很重要的基本概念。
为了证明我的观点,不妨拿正弦函数为参考模型。 在已经建立前面的CMAC的两个函数后,采用以下程序进行分析和调用
%对CMAC网络的分块实现方法进行仿真 %对《先进PID控制MATLAB仿真(第二版)》P186页的例子整理所得 %这个算法有点问题 clear all; close all; %%%%%%%%%%%%%%%%%%%%%%%这部分为函数的参数设置过程%%%%%%%%%%%%%%%%%%%%%%%% xite=1.5; %y和ym的偏差系数带来的权系数w的更新的比例系数η,参见42页式2.16 alfa=0.05; %权系数的前一步和前两步的变化差带来的比例系数,这个书上没有 数据挖掘实验室 M=1000; %量化时用到的系数 N=700; %权相量的维数,是不是就是A到AP映射的维数? C=117; %泛化参数 ts=0.001; %采样时间T xmin=-1.00; %其中xmin为输入u的最小值 xmax=1.00; %xmax为输入u的最大值, %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%采用正弦函数%%%%%%%%%%%%%%%%%%%%%%%%%%% kk=1:1:755; time=kk*ts; %计算给定的时间序列:t=kT u=kk*ts; y=sin(4*2*pi*u); %依据u和t之间的关系u=sin(4*2*pi*t)计算u的瞬时值 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%这里是书中原本的非线性模型的生成过程,很弱智%%%%% %u_1=0; %输入u(k-1) %y_1=0; %输出y(k-1) %for k=1:1:1000 %time(k)=k*ts; %计算给定的时间序列:t=kT %u(k)=sin(4*2*pi*k*ts); %依据u和t之间的关系u=sin(4*2*pi*t)计算u的瞬时值 %y(k)=u_1^3+y_1/(1+y_1^2); %非线性模型 %u_1=u(k); %输入u(k-1)进行更新 %y_1=y(k); %输入y(k-1)进行更新 数据挖掘工具 %end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%这部分为原来函数中与权向量有关的向量的初始化过程%%%%%%%%%%%%%%% w0=zeros(N,1); %地址空间中对应的权向量的初始值 %w0=1*rands(N,1); w=w0; w_1=w0; w_2=w0; errvector=zeros(size(u)); for k = 1:1:length(u) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%训练CMAC网络%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%注意这里的输入中有上一次计算出的权向量w%%%%%%%%%%%%%%%%%% ym(k)=CmacOut(u(k),M,N,C,w_1,xmin,xmax); err=y(k)-ym(k); errvector(k) = err; w=CmacUpdate(u(k),err,M,N,C,w_1,w_2,xite,alfa,xmin,xmax); %plot(w,"o");grid on %[w,ym(k)]=buildcmac(u(k),y(k),M,N,C,w_1,w_2,xite,alfa,xmin,xmax); %这一步可以输出估值结果 w_2=w_1; %权向量的前两次值,进行更新 w_1=w; %权向量的前一次值,进行更新 end %%%%%%%%%%%%%%%%%%%测试CMAC网络的输出结果和真实值之间的对应关系%%%%%%%%%%%%%%% figure(1); 数据挖掘实验室 subplot(2,2,1) plot(time,y,"b",time,ym,"r"); xlabel("time(s)");ylabel("y,ym"); grid on subplot(2,2,2) plot(time,y-ym,"r"); grid on xlabel("time(s)");ylabel("delta=y-ym"); %%%%%%%%%%%%%%%%%%%固定权值w,测试网络输出%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%采用正弦函数%%%%%%%%%%%%%%%%%%%%%%%%%%% %u_1=0; %输入u(k-1) %y_1=0; %输出y(k-1) deltak=200; kk1=(kk(length(kk))-deltak):1 kk(length(kk))+deltak); time1=kk1*ts; %计算给定的时间序列:t=kT u1=kk1*ts; y1=sin(4*2*pi*u1); %依据u和t之间的关系u=sin(4*2*pi*t)计算u的瞬时值 %y(k)=u_1^3+y_1/(1+y_1^2); %非线性模型 %u_1=u(k); %输入u(k-1)进行更新 %y_1=y(k); %输入y(k-1)进行更新 %end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% for k1 = 1:1:length(u1) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%训练CMAC网络%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%注意这里的输入中有上一次计算出的权向量w%%%%%%%%%%%%%%%%%% ym1(k1)=CmacOut(u1(k1),M,N,C,w,xmin,xmax); %%%%%%%%%%%%%%%%%%%%%%%%%%%计算CMAC网络在给定输入的下的输出%%%%%%%%%%%%%% %ym(k)=runcmac(u(k),w,M,N,C,xmin,xmax);%这一步多余了 end %%%%%%%%%%%%%%%%%%%测试CMAC网络的输出结果和真实值之间的对应关系%%%%%%%%%%%%%%% %figure(1); subplot(2,2,3) plot(time1,y1,"b",time1,ym1,"r"); xlabel("time1(s)");ylabel("y1,ym1"); grid on %axis([time1(1),time1(length(time1)),-1,1]) subplot(2,2,4) plot(time1,y1-ym1,"r"); grid on xlabel("time1(s)");ylabel("delta=y1-ym1"); %axis([time1(1),time1(length(time1)),-2,2]) %%%%%%%%%%%%%%%%%%%固定权值w,测试网络输出%%%%%%%%%%%%%%% figure; plot(kk,errvector,"k") hold on plot(kk,y-ym,"r") grid on
程序有点长,分得比较细,我现在来一步一步的进行讨论。 数据挖掘实验室 首先是SISO的CMAC的参数设置:%%%%%%%%%%%%%%%%%%%%%%%这部分为函数的参数设置过程%%%%%%%%%%%%%%%%%%%%%%%% xite=1.5; %y和ym的偏差系数带来的权系数w的更新的比例系数η,参见42页式2.16 alfa=0.05; %权系数的前一步和前两步的变化差带来的比例系数,这个书上没有 M=1000; %量化时用到的系数 N=700; %权相量的维数,是不是就是A到AP映射的维数? C=117; %泛化参数 ts=0.001; %采样时间T xmin=-1.00; %其中xmin为输入u的最小值 xmax=1.00; %xmax为输入u的最大值,
然后建立正弦函数模型:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%采用正弦函数%%%%%%%%%%%%%%%%%%%%%%%%%%% kk=1:1:755; time=kk*ts; %计算给定的时间序列:t=kT u=kk*ts; y=sin(4*2*pi*u); %依据u和t之间的关系u=sin(4*2*pi*t)计算u的瞬时值 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CMAC网络权向量等向量的初始化
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%这部分为原来函数中与权向量有关的向量的初始化过程%%%%%%%%%%%%%%% w0=zeros(N,1); %地址空间中对应的权向量的初始值 %w0=1*rands(N,1); w=w0; w_1=w0; w_2=w0; errvector=zeros(size(u)); for k = 1:1:length(u)
前面一部分的for语句应该是这个部分的
这个部分是对CMAC的输出进行计算,并对权向量进行训练的过程
for k = 1:1:length(u) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%训练CMAC网络%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%注意这里的输入中有上一次计算出的权向量w%%%%%%%%%%%%%%%%%% ym(k)=CmacOut(u(k),M,N,C,w_1,xmin,xmax); err=y(k)-ym(k); errvector(k) = err; w=CmacUpdate(u(k),err,M,N,C,w_1,w_2,xite,alfa,xmin,xmax); w_2=w_1; %权向量的前两次值,进行更新 w_1=w; %权向量的前一次值,进行更新 end
上面的errvector只是用来观测误差的变化情况,我发现它并不收敛
现在开始是书中对所建立的CMAC网络的评价效果分析
%%%%%%%%%%%%%%%%%%%测试CMAC网络的输出结果和真实值之间的对应关系%%%%%%%%%%%%%%% figure(1); subplot(2,2,1) plot(time,y,"b",time,ym,"r"); xlabel("time(s)");ylabel("y,ym"); 数据挖掘论坛 grid on subplot(2,2,2) plot(time,y-ym,"r"); grid on xlabel("time(s)");ylabel("delta=y-ym");
这个效果分析看起来很不错,大家可以自己做图看看。
但实际上,我发现这个例子纯粹是胡扯,简直是骗人。因为这个例子中所训练的权向量w立即被用来估算下一步u输入时网络的输出。因为步长很小, ts=0.001,只能说明所训练的CMAC网络在有限区间的范围内可以逼近被模拟的对象。为了证明我的观点。准备以下程序:
%%%%%%%%%%%%%%%%%%%固定权值w,测试网络输出%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%采用正弦函数%%%%%%%%%%%%%%%%%%%%%%%%%%% kk1=(kk(length(kk))-deltak):1:(kk(length(kk))+deltak); time1=kk1*ts; %计算给定的时间序列:t=kT u1=kk1*ts; y1=sin(4*2*pi*u1); %依据u和t之间的关系u=sin(4*2*pi*t)计算u的瞬时值 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% for k1 = 1:1:length(u1) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%训练CMAC网络%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%注意这里的输入中有上一次计算出的权向量w%%%%%%%%%%%%%%%%%% 数据挖掘论坛 ym1(k1)=CmacOut(u1(k1),M,N,C,w,xmin,xmax);
end %%%%%%%%%%%%%%%%%%%测试CMAC网络的输出结果和真实值之间的对应关系%%%%%%%%%%%%%%% subplot(2,2,3) plot(time1,y1,"b",time1,ym1,"r"); xlabel("time1(s)");ylabel("y1,ym1"); grid on subplot(2,2,4) plot(time1,y1-ym1,"r"); grid on xlabel("time1(s)");ylabel("delta=y1-ym1");
上一部分打头漏了点东西:
deltak=200;
这个变量的作用是建立一个范围。以CMAC训练时的最后一个输入值为中心建立起一个范围,这个变量即表现了范围的大小。运行上一部分程序,可以发现,所建立起的CMAC网络实际上只是在很有限的范围内能逼近被跟踪的模型。
通过对这个模型的分析,我发现CMAC并不象传说的那样效果好。
是否很多人都在骗人?无论是书上给出的算法或证明都说其效果如何良好。但实际上并非如此。
有三本书讲的算法与这类似。除了《先进PID控制MATLAB仿真(第二版)》外,还有《非线性自适应逆控制及其应用》(卢志刚等,国防工业出版社),《人工神经网络的模型及其应用》(张立明,复旦大学出版社)。还有许多许多的论文。 数据挖掘研究院
我不知道我错在哪里,还是大家都错了?
Create By Any-Extract(WL-AE) 数据挖掘研究院
|