径向基网络(RBF network)

来源:http://blog.csdn.net/zouxy09/article/details/13297881

1、径向基函数

径向基函数(Radical Basis Function,RBF)方法是Powell在1985年提出的。所谓径向基函数,其实就是某种沿径向对称的标量函数。通常定义为空间中任一点x到某一中心c之间欧氏距离的单调函数,可记作k(||x-c||),其作用往往是局部的,即当x远离c时函数取值很小。例如高斯径向基函数:

当年径向基函数的诞生主要是为了解决多变量插值的问题。可以看下面的图。具体的话是先在每个样本上面放一个基函数,图中每个蓝色的点是一个样本,然后中间那个图中绿色虚线对应的,就表示的是每个训练样本对应一个高斯函数(高斯函数中心就是样本点)。然后假设真实的拟合这些训练数据的曲线是蓝色的那根(最右边的图),如果我们有一个新的数据x1,我们想知道它对应的f(x1)是多少,也就是a点的纵坐标是多少。那么由图可以看到,a点的纵坐标等于b点的纵坐标加上c点的纵坐标。而b的纵坐标是第一个样本点的高斯函数的值乘以一个大点权值得到的,c的纵坐标是第二个样本点的高斯函数的值乘以另一个小点的权值得到。而其他样本点的权值全是0,因为我们要插值的点x1在第一和第二个样本点之间,远离其他的样本点,那么插值影响最大的就是离得近的点,离的远的就没什么贡献了。所以x1点的函数值由附近的b和c两个点就可以确定了。拓展到任意的新的x,这些红色的高斯函数乘以一个权值后再在对应的x地方加起来,就可以完美的拟合真实的函数曲线了。

二、径向基网络

到了1988年, Moody和 Darken提出了一种神经网络结构,即RBF神经网络,属于前向神经网络类型,它能够以任意精度逼近任意连续函数,特别适合于解决分类问题。

RBF网络的结构与多层前向网络类似,它是一种三层前向网络。输入层由信号源结点组成;第二层为隐含层,隐单元数视所描述问题的需要而定,隐单元的变换函数是RBF径向基函数,它是对中心点径向对称且衰减的非负非线性函数;第三层为输出层,它对输入模式的作用作出响应。从输人空间到隐含层空间的变换是非线性的,而从隐含层空间到输出层空间变换是线性的。

RBF网络的基本思想是:用RBF作为隐单元的“基”构成隐含层空间,这样就可将输入矢量直接(即不需要通过权连接)映射到隐空间。根据Cover定理,低维空间不可分的数据到了高维空间会更有可能变得可分。换句话来说,RBF网络的隐层的功能就是将低维空间的输入通过非线性函数映射到一个高维空间。然后再在这个高维空间进行曲线的拟合。它等价于在一个隐含的高维空间寻找一个能最佳拟合训练数据的表面。这点与普通的多层感知机MLP是不同的。

当RBF的中心点确定以后,这种映射关系也就确定了。而隐含层空间到输出空间的映射是线性的,即网络的输出是隐单元输出的线性加权和,此处的权即为网络可调参数。由此可见,从总体上看,网络由输人到输出的映射是非线性的,而网络输出对可调参数而言却又是线性的。这样网络的权就可由线性方程组直接解出,从而大大加快学习速度并避免局部极小问题。

从另一个方面也可以这样理解,多层感知器(包括BP神经网络)的隐节点基函数采用线性函数,激活函数则采用Sigmoid函数或硬极限函数。而RBF网络的隐节点的基函数采用距离函数(如欧氏距离),并使用径向基函数(如Gaussian函数)作为激活函数。径向基函数关于n维空间的一个中心点具有径向对称性,而且神经元的输入离该中心点越远,神经元的激活程度就越低。隐节点的这一特性常被称为“局部特性”。

三、RBF网络的设计与求解

RBF的设计主要包括两个方面,一个是结构设计,也就是说隐藏层含有几个节点合适。另一个就是参数设计,也就是对网络各参数进行求解。由上面的输入到输出的网络映射函数公式可以看到,网络的参数主要包括三种:径向基函数的中心、方差和隐含层到输出层的权值。到目前为止,出现了很多求解这三种参数的方法,主要可以分为以下两大类:

1、方法一:

通过非监督方法得到径向基函数的中心和方差,通过监督方法(最小均方误差)得到隐含层到输出层的权值。具体如下:

(1)在训练样本集中随机选择h个样本作为h个径向基函数的中心。更好的方法是通过聚类,例如K-means聚类得到h个聚类中心,将这些聚类中心当成径向基函数的h个中心。

(2)RBF神经网络的基函数为高斯函数时,方差可由下式求解:

式中cmax 为所选取中心之间的最大距离,h是隐层节点的个数。扩展常数这么计算是为了避免径向基函数太尖或太平。

(3)隐含层至输出层之间神经元的连接权值可以用最小均方误差LMS直接计算得到,计算公式如下:(计算伪逆)(d是我们期待的输出值)

2、方法二:

采用监督学习算法对网络所有的参数(径向基函数的中心、方差和隐含层到输出层的权值)进行训练。主要是对代价函数(均方误差)进行梯度下降,然后修正每个参数。具体如下:

(1)随机初始化径向基函数的中心、方差和隐含层到输出层的权值。当然了,也可以选用方法一中的(1)来初始化径向基函数的中心。

(2)通过梯度下降来对网络中的三种参数都进行监督训练优化。代价函数是网络输出和期望输出的均方误差:

然后每次迭代,在误差梯度的负方向已一定的学习率调整参数。

四、代码实现:

1、第一种方法

第一种方法在zhangchaoyang的博客上面有C++的实现,只是上面针对的是标量的数据(输入和输出都是一维的)。而在Matlab中也提供了第一种方法的改进版(呵呵,个人觉得,大家可以在Matlab中运行open newrb查看下源代码)。

Matlab提供的一个函数是newrb()。它有个技能就是可以自动增加网络的隐层神经元数目直到均方差满足我们要求的精度或者神经元数数目达到最大(也就是我们提供的样本数目,当神经元数目和我们的样本数目一致时,rbf网络此时的均方误差为0)为止。它使用方法也能简单:

rbf = newrb(train_x, train_y);

output = rbf(test_x);

直接把训练样本给它就可以得到一个rbf网络了。然后我们把输入给它就可以得到网络的输出了。

2、第二种方法

第二种方法在zhangchaoyang的博客上面也有C++的实现,只是上面针对的还是标量的数据(输入和输出都是一维的)。但我是做图像的,网络需要接受高维的输入,而且在Matlab中,向量的运算要比for训练的运算要快很多。所以我就自己写了个可以接受向量输入和向量输出的通过BP算法监督训练的版本。BP算法可以参考这里:BackpropagationAlgorithm ,主要是计算每层每个节点的残差就可以了。另外,我的代码是可以通过梯度检查的,但在某些训练集上面,代价函数值却会随着迭代次数上升,这就很奇怪了,然后降低了学习率还是一样。但在某些简单点的训练集上面还是可以工作的,虽然训练误差也挺大的(没有完全拟合训练样本)。所以大家如果发现代码里面有错误的部分,还望大家告知下。

主要代码见下面:

learnRBF.m

[cpp] view plain copy

  1. %// This is a RBF network trained by BP algorithm
  2. %// Author : zouxy
  3. %// Date   : 2013-10-28
  4. %// HomePage : http://blog.csdn.net/zouxy09
  5. %// Email  : [email protected]
  6. close all; clear; clc;
  7. %%% ************************************************
  8. %%% ************ step 0: load data ****************
  9. display(‘step 0: load data...‘);
  10. % train_x = [1 2 3 4 5 6 7 8]; % each sample arranged as a column of train_x
  11. % train_y = 2 * train_x;
  12. train_x = rand(5, 10);
  13. train_y = 2 * train_x;
  14. test_x = train_x;
  15. test_y = train_y;
  16. %% from matlab
  17. % rbf = newrb(train_x, train_y);
  18. % output = rbf(test_x);
  19. %%% ************************************************
  20. %%% ******** step 1: initialize parameters ********
  21. display(‘step 1: initialize parameters...‘);
  22. numSamples = size(train_x, 2);
  23. rbf.inputSize = size(train_x, 1);
  24. rbf.hiddenSize = numSamples;        % num of Radial Basis function
  25. rbf.outputSize = size(train_y, 1);
  26. rbf.alpha = 0.1;  % learning rate (should not be large!)
  27. %% centre of RBF
  28. for i = 1 : rbf.hiddenSize
  29. % randomly pick up some samples to initialize centres of RBF
  30. index = randi([1, numSamples]);
  31. rbf.center(:, i) =  train_x(:, index);
  32. end
  33. %% delta of RBF
  34. rbf.delta = rand(1, rbf.hiddenSize);
  35. %% weight of RBF
  36. r = 1.0; % random number between [-r, r]
  37. rbf.weight = rand(rbf.outputSize, rbf.hiddenSize) * 2 * r - r;
  38. %%% ************************************************
  39. %%% ************ step 2: start training ************
  40. display(‘step 2: start training...‘);
  41. maxIter = 400;
  42. preCost = 0;
  43. for i = 1 : maxIter
  44. fprintf(1, ‘Iteration %d ,‘, i);
  45. rbf = trainRBF(rbf, train_x, train_y);
  46. fprintf(1, ‘the cost is %d \n‘, rbf.cost);
  47. curCost = rbf.cost;
  48. if abs(curCost - preCost) < 1e-8
  49. disp(‘Reached iteration termination condition and Termination now!‘);
  50. break;
  51. end
  52. preCost = curCost;
  53. end
  54. %%% ************************************************
  55. %%% ************ step 3: start testing ************
  56. display(‘step 3: start testing...‘);
  57. Green = zeros(rbf.hiddenSize, 1);
  58. for i = 1 : size(test_x, 2)
  59. for j = 1 : rbf.hiddenSize
  60. Green(j, 1) = green(test_x(:, i), rbf.center(:, j), rbf.delta(j));
  61. end
  62. output(:, i) = rbf.weight * Green;
  63. end
  64. disp(test_y);
  65. disp(output);

trainRBF.m

[cpp] view plain copy

  1. function [rbf] = trainRBF(rbf, train_x, train_y)
  2. %%% step 1: calculate gradient
  3. numSamples = size(train_x, 2);
  4. Green = zeros(rbf.hiddenSize, 1);
  5. output = zeros(rbf.outputSize, 1);
  6. delta_weight = zeros(rbf.outputSize, rbf.hiddenSize);
  7. delta_center = zeros(rbf.inputSize, rbf.hiddenSize);
  8. delta_delta =  zeros(1, rbf.hiddenSize);
  9. rbf.cost = 0;
  10. for i = 1 : numSamples
  11. %% Feed forward
  12. for j = 1 : rbf.hiddenSize
  13. Green(j, 1) = green(train_x(:, i), rbf.center(:, j), rbf.delta(j));
  14. end
  15. output = rbf.weight * Green;
  16. %% Back propagation
  17. delta3 = -(train_y(:, i) - output);
  18. rbf.cost = rbf.cost + sum(delta3.^2);
  19. delta_weight = delta_weight + delta3 * Green‘;
  20. delta2 = rbf.weight‘ * delta3 .* Green;
  21. for j = 1 : rbf.hiddenSize
  22. delta_center(:, j) = delta_center(:, j) + delta2(j) .* (train_x(:, i) - rbf.center(:, j)) ./ rbf.delta(j)^2;
  23. delta_delta(j) = delta_delta(j)+ delta2(j) * sum((train_x(:, i) - rbf.center(:, j)).^2) ./ rbf.delta(j)^3;
  24. end
  25. end
  26. %%% step 2: update parameters
  27. rbf.cost = 0.5 * rbf.cost ./ numSamples;
  28. rbf.weight = rbf.weight - rbf.alpha .* delta_weight ./ numSamples;
  29. rbf.center = rbf.center - rbf.alpha .* delta_center ./ numSamples;
  30. rbf.delta = rbf.delta - rbf.alpha .* delta_delta ./ numSamples;
  31. end

green.m

[plain] view plain copy

  1. function greenValue = green(x, c, delta)
  2. greenValue = exp(-1.0 * sum((x - c).^2) / (2 * delta^2));
  3. end

五、代码测试

首先,我测试了一维的输入,需要拟合的函数很简单,就是y=2x。

train_x = [1 2 3 4 5 6 7 8];

train_y = 2 * train_x;

所以期待的输出就是:

2    4     6     8   10    12    14   16

我代码训练迭代200次后的网络输出是:

2.0042   4.0239    5.9250    8.0214  10.0692   11.9351   14.0179  15.9958

Matlab的newrb的输出是:

2.0000   4.0000    6.0000    8.0000  10.0000   12.0000   14.0000  16.0000

可以看到,Matlab的是完美拟合啊。我的那个还是均方误差还是挺大的。

然后,我测试了高维的输入,训练样本是通过Matlab的rand(5, 10)来得到的,它生成的是5行10列[0 1]之间的随机数。也就是说我们的样本是10个,每个样本的维度是5维。我们测试的也是很简单的函数y=2x。结果如下:

关于这个结果,我也不说什么了。期待大家发现代码里面错误的地方,然后告知下,非常感谢。

以上均为拷贝过来的,博主提供的matlab代码还可以改善的,但是不失为一篇学习的好文。

 

时间: 2024-07-30 10:19:50

径向基网络(RBF network)的相关文章

径向基网络(RBF network)之BP监督训练

径向基网络(RBF network)之BP监督训练 转载:http://blog.csdn.net/zouxy09/article/details/13297881 分类: 机器学习 神经网络 C/C++编程2013-10-28 18:17 3083人阅读 评论(1) 收藏 举报 神经网络机器学习RBF 径向基网络(RBF network)之BP监督训练 [email protected] http://blog.csdn.net/zouxy09 之前看了流行学习的时候,感觉它很神奇,可以将一个

径向基网络对蝴蝶花分类

1.径向基网络简介 径向基网络的拓扑结构图如下所示,其网络有三层构成,第一层是输入层,第二层是隐含层,第三层是输出层.采用径向基函数(常用高斯函数)作为基函数,将输入向量空间转换到隐含层空间,实现对原问题的线性可分.径向基网络核心是隐含层采用了径向基函数,它计算的是输入向量和基函数中心之间的欧式距离,而不是输入向量与权值的内积.基函数一般采用的是高斯函数. 2.径向基网络学习算法 径向基网络需要训练的有三个参数 隐含层中基函数的中心 隐含层中基函数的标准差 隐含层与输出层间的权值 算法核心步骤

径向基(RBF)神经网络

RBF网络能够逼近任意非线性的函数.可以处理系统内难以解析的规律性,具有很好的泛化能力,并且具有较快的学 习速度.当网络的一个或多个可调参数(权值或阈值)对任何一个输出都有影响时,这样的网络称为全局逼近网络. 由于对于每次输入,网络上的每一个权值都要调整,从而导致全局逼近网络的学习速度很慢,比如BP网络.如果对于 输入空间的某个局部区域只有少数几个连接权值影响输出,则该网络称为局部逼近网络,比如RBF网络.接下来重点 先介绍RBF网络的原理,然后给出其实现.先看如下图 正则化的RBF网络参考这里

径向基(RBF)神经网络python实现

1 from numpy import array, append, vstack, transpose, reshape, 2 dot, true_divide, mean, exp, sqrt, log, 3 loadtxt, savetxt, zeros, frombuffer 4 from numpy.linalg import norm, lstsq 5 from multiprocessing import Process, Array 6 from random import sa

机器学习之径向基神经网络(RBF NN)

本文基于台大机器学习技法系列课程进行的笔记总结. 主要内容如下图所示: 首先介绍一下径向基函数网络的Hypothesis和网络的结构,然后介绍径向基神经网络学习算法,以及利用K-means进行的学习,最后通过一个实例加深对RBF神经网络认识和理解. RBF神经网络的Hypothesis和网络结构 我们从基于Gaussian kernel的support vector machine中在无限维度中进行特征转换来获取一个large margin的边界,这个Gaussian kernel就是一个Rad

RBF高斯径向基核函数【转】

XVec表示X向量.||XVec||表示向量长度.r表示两点距离.r^2表示r的平方.k(XVec,YVec) = exp(-1/(2*sigma^2)*(r^2))= exp(-gamma*r^2)...... 公式-1这里, gamma=1/(2*sigma^2)是参数, r=||XVec-YVec||实际上,可看作是计算2个点X与Y的相似性.很多参考书上,把YVec写作XVec',即 k(XVec, XVec'),也是一样的含义:两点相似性.由于Matlab上面XVec'代表XVec的转置

径向基函数网络

介绍 径向基函数网络(Radial Basis Function,RBF)是由三层构成的前向网络:第一层为输入层,节点数等于输入的维数:第二层为隐含层,节点个数视问题复杂度而定:第三层为输出层,节点数等于输出数据的维度.RBF的隐含层是非线性的,采用径向基函数作为基函数,从而将输入向量空间转换到隐含层空间,使原来的线性不可分问题变为线性可分,输出层则是线性的. 径向基神经网络可以分为正则化网络和广义网络,在实践中被广泛应用的是广义网络. 径向基函数 A radial basis function

转:径向基核函数

转:径向基核函数 (2011-05-20 16:53:54) 转载▼   分类: AboutResearch 所谓径向基函数 (Radial Basis Function 简称 RBF), 就是某种沿径向对称的标量函数. 通常定义为空间中任一点x到某一中心xc之间欧氏距离的单调函数 , 可记作 k(||x-xc||), 其作用往往是局部的 , 即当x远离xc时函数取值很小. 最常用的径向基函数是高斯核函数 ,形式为 k(||x-xc||)=exp{- ||x-xc||^2/(2*σ)^2) }

径向基神经网络初学

[径向基神经网络训练算法及其性能研究 2.1]-RBF定义:假设x,x0属于Rn,以x0为中心,x到x0的径向距离为半径形成的||x-x0||构成的函数系φ(||x-x0||)称为径向基函数.