冰冰点灯,照亮我家门前~
欢迎进入nnetinfo
用户名:
密码:
深圳学习数据分析,数据挖掘,请联系yahushuxue@163.com~
nnetinfo : 本网发布神经网络相关的学习与研讨内容。
当前位置:教学区
径向基myNewrb(动手写自己的代码)
作者:梁小h   日期:2015-11-06 19:01:58.0

      =====  <文档仅供查阅和简单了解,深入了解请关注神经网络之家发布的___神经网络教学视频___>   ====

      本文介绍径向基神经网络(matlab 的newrb模型)的代码实现,对径向基神经网络原理不懂的请参考

                                                  <一篇文章读懂径向基神经网络原理(上)>

                                                    <一篇文章读懂径向基神经网络原理(下)>

      使用matlab工具箱直接调用newrb实现径向基神经网络请参考文章:

                                                             <径向基(matlab工具箱)>

好,开始正文,

  一.算法分析

      径向基神经网络(matlab 中的newrb模型)最大的特点就是用尽量少的隐层神经元去满足目标误差.

      我们假设,最终选用了k个隐层神经元,那么径向基模型的数学表达式如下:

                                 

       说明:以下提到隐节点的值是指综合权值,阈值,输入后得到的值,;而径向基的值是指隐节点的值经过径向基函数变换后的值.

模型中待求的参数是:

输入到隐层的权重 W1
隐层阈值 B1
隐层到输出层的权重 W2
输出层阈值 B2

 

         其中W1的值来自训练样本的输入,但希望尽量选用较少的样本作为W1.

         B1是隐层的阈值,它影响径向基的肥瘦, 在matlab工具箱里,会先由用户设定spread的值,再由公式

B1=sqrt(-ln(0.5))/spread;  获得B1 ----请参考文章<一篇文章读懂径向基神经网络原理(下)>

         W2和B2 则是通过径向基与输出组成的线性方程组求解得到.

 二. 代码流程:

          Newrb模型训练的难点在于如何选取最少的隐节点,matlab工具箱里使用的是正交最小二乘法(OLS).

 这里给出简要流程如下:

          1.计算各个径向基的值,计算哪个径向基与输出的相关系数最大,将它作为网络的第一个隐节点.

          2.将剩余径向基相对已用径向基进行正交,计算各个剩余径向基的正交后与输出的相关系数,将与输出

             相关系数最大的径向基,作为新的隐节点.

         3.计算选用当前节点,误差(求解误差要求W2)是否达到要求,没达到要求就返回2.达到要求就输出结果.

 

具体实现请看下面代码:

三.代码实现

注:代码已测试,在matlab2012b上运行成功

function testNewrbCode()
%本代码来自www.nnetinfo.com
%本代码模仿matlab神经网络工具箱的newrb神经网络,
%代码主旨用于教学,供大家学习理解newrb神经网络原理

%用于训练的输入输出数据
x1 = 1:0.2:10;
x2 = -5:0.2:4;
X  = [x1;x2];     
Y  = sin (X(1,:))+X(2,:);

%参数设置
eg = 0.1;        %目标误差
sp = 2;           %扩展系数spread
mn = length(Y);  %最大隐节点个数

%通过自己建立模型训练网络,获得w1,b1,w2,b2
[w1,b1,w2,b2] = myNewrb(X,Y,eg,sp,mn);

%直接调用工具箱训练网络
net = newrb(X,Y,eg,sp,mn);

%测试数据
x=[2 ;5];

simYByBox = sim( net,x);
simY      = mySim( w1, b1, w2, b2, x);

testResult = isequal( simY, simYByBox);  
disp(['testResult = ',num2str(testResult)]);

web('www.nnetinfo.com')
end

function y =mySim(w1,b1,w2,b2,x)
%根据w1,b1,w2,b2计算输入为x时,网络的输出是多少

hb = myRadbas( calDist( w1, x) .* b1);
y = w2 * hb + b2;

end

function [w1,b1,w2,b2] = myNewrb(X,Y,goal,spread,MN)
[~, Q]  = size(X);                %获得样本个数
b1  = sqrt(-log(.5))/spread;      %计算b1

%计算相关系数
P   = myRadbas(calDist(X',X)*b1);   %P(i,j)第i个样本的第j个径向基(RBF后)的值(每列代表一个神经元),
cor = ((Y * P) .^ 2) ./ (sum(Y.*Y,2) *sum(P.*P));  %cor(i,j):第i个输出与与第j个隐节点的相关系数
pick = findLargeColumn(cor);          %找到相关系数最大的一个径向基,投入使用

used = [];               %初始化已用样本池
left = 1:Q;              %初始化未用样本池
newW    = P(:,pick);
P(:,pick)  = [];         %将已用隐节点的数据屏蔽掉
used = [used left(pick)];%更新已用样本池
left(pick) = [];         %更新未用样本池


w1 = X(:,used)';                %更新当前w1
a1 = myRadbas(calDist(w1,X)*b1);%计算径向基(RBF后)的值
[w2,b2] = solvelin2(a1,Y);      %求解线性方程组,获得隐节点到输出层的权值和输出层的阈值
a2 = w2*a1 + b2*ones(1,Q);      %计算网络最终输出
sse = sumsqr(Y-a2);             %求拟合均方误差。   mse([1 2 3])=mean([1 4 9])

for k = 2:MN   
  %剩余样本径向基需与新加入的样本进行正交处理     
  P = P - newW * newW' * P / (newW'*newW);
  cor = ((Y * P) .^ 2) ./ (sum(Y.*Y,2) *sum(P.*P));  %cor(i,j):第i个输出与与第j个隐节点的相关系数
  pick = findLargeColumn(cor);  %找到相关系数最大的一个神经节点,投入使用
 
  newW    = P(:,pick);
  P(:,pick)  = [];           %将已用隐节点的数据屏蔽掉
  used = [used left(pick)];  %更新已用隐节点池
  left(pick) = [];           %更新未用隐节点池

  w1 = X(:,used)';                 %更新当前w1
  a1 = myRadbas(calDist(w1,X)*b1); %计算径向基(RBF后)的值
  [w2,b2] = solvelin2(a1,Y);       %求解线性方程组,获得隐节点到输出层的权值和输出层的阈值
  a2 = w2*a1 + b2*ones(1,Q);       %计算网络最终输出
  sse = sumsqr(Y-a2);              %求拟合均方误差。   mse([1 2 3])=mean([1 4 9])
 

  if (sse < goal), break, end       %若误差满足要求,则退出循环
end

S1 = size(w1,1);
b1 = ones(S1,1)*b1;
end


function i = findLargeColumn(m)
%找出m平方和最大的一列.
m(isnan(m)) = 0;
m = sum(m .^ 2,1);    %计算每列平方和
[~,i] = max(m);     
end

function [w,b] = solvelin2(p,t)
if nargout <= 1
  w= t/p;
else
  [pr,pc] = size(p);
  x = t/[p; ones(1,pc)];
  w = x(:,1:pr);
  b = x(:,pr+1);
end
end

function dist = calDist(a,b)
%计算欧氏距离
ALen = size(a,1);
BLen = size(b,2);
dist = zeros(ALen,BLen);
for i = 1 : ALen
    for j = 1 :BLen
        dist(i,j) = sum((a(i,:)-b(:,j)').^2);
    end
end
dist = sqrt( dist);
end

function y = myRadbas(x)
%径向基函数
y = exp( -( x .*x));
end

 

结束语

 阅读代码,调试代码,才能真正的理解算法的原理,希望本文能够帮助大家进一步掌握神经网络原理.

==============<原创文章,转载请说明来自神经网络之家www.nnetinfo.com>     ==========