来源: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  : zouxy09@qq.com

  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代码还可以改善的,但是不失为一篇学习的好文。

 

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

  1. MATLAB——径向基网络拟合曲线和分类

    1.:.:; rand('state',pi); %指定状态,产生相同的随机数 T=sin(*P)+rand(,length(P)); % 给正弦函数加噪声 plot(P,T,'o') % net=n ...

  2. 广义径向基网络(RBF网络)

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

    from numpy import array, append, vstack, transpose, reshape, \ dot, true_divide, mean, exp, sqrt, lo ...

  4. RBF(径向基)神经网络

    只要模型是一层一层的,并使用AD/BP算法,就能称作 BP神经网络.RBF 神经网络是其中一个特例.本文主要包括以下内容: 什么是径向基函数 RBF神经网络 RBF神经网络的学习问题 RBF神经网络与 ...

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

    本文基于台大机器学习技法系列课程进行的笔记总结. 主要内容如下图所示: 首先介绍一下径向基函数网络的Hypothesis和网络的结构,然后介绍径向基神经网络学习算法,以及利用K-means进行的学习, ...

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

    XVec表示X向量.||XVec||表示向量长度.r表示两点距离.r^2表示r的平方.k(XVec,YVec) = exp(-1/(2*sigma^2)*(r^2))= exp(-gamma*r^2) ...

  7. Java - 网络编程(NetWork)

    Java - 网络编程(NetWork)   一.java.net包下的 InetAddress 类的使用:     > 一个 InetAddress 代表着一个IP地址     > 主要 ...

  8. centos7 无法启动网络(service network restart)错误解决办法

    centos7 无法启动网络(service network restart)错误解决办法: (以下方法均为网上COPY,同时感谢原博主分享) systemctl status network.ser ...

  9. 解决React Native使用Fetch API请求网络报Network request failed

    问题来源: 1 . 在测试fetch数据请求时,Xcode9.0以上的无法请求https, 需要在Xcode中加载项目后修改Info.plist的相关配置,具体如下参考 问题及解决方法一模一样,不再重 ...

随机推荐

  1. vmware三种网络格式

    网络地址转换(NAT) 这种访问模式指的是虚拟机不占用主机所在局域网的ip,通过使用主机的NAT功能访问局域网和互联网,意味着虚拟机可以访问局域网中的其他电脑,但是其他电脑不知道虚拟机的存在. 使用这 ...

  2. Fiddler抓包工具使用详解

    一.Fiddler简介 Fiddler是最强大最好用的Web调试工具之一, 它能记录所有客户端和服务器的http和https请求.允许你监视.设置断点.甚至修改输入输出数据.Fiddler包含了一个强 ...

  3. JavaScript高级(01)

    前端开发工具 1.1. WebStorm介绍和下载 l  介绍 WebStorm是JetBrains 推出的一款强大的HTML5编辑工具,拥有丰富的代码快速编辑,可以智能的补全代码.代码格式化.htm ...

  4. vue学习之父组件与子组件之间的交互

    1.父组件数据传给子组件 父组件中的msgfather定义数据 在之组件中通过设置props来取得希望从父组件中获得的值 通过设置这两个属性就可以从父组件传数据到子组件 2.子组件传数据给父组件(这里 ...

  5. php中常用的字符串比较函数strcmp()实例解释

    int strcmp ( string $str1 , string $str2 ) 以二进制方式进行比较以该函数比较时区分大小写返回值,如果str1小于str2返回<0,如果str1大于str ...

  6. webpack2使用ch9-处理模板文件 .html .ejs .tpl模板使用

    1 目录展示 安装依赖 "ejs-loader": "^0.3.0","html-loader": "^0.4.5", ...

  7. ASP.NET没有魔法——ASP.NET与数据库

    在之前的文章中介绍了使用ASP.NET MVC来开发一个博客系统,并且已将初具雏形,可以查看文章列表页面,也可以点击文章列表的其中一篇文章查看详情,这已经完成了最开始需求分析的读者的查看列表和查看文章 ...

  8. 用C#实现字符串相似度算法(编辑距离算法 Levenshtein Distance)

    在搞验证码识别的时候需要比较字符代码的相似度用到"编辑距离算法",关于原理和C#实现做个记录. 据百度百科介绍: 编辑距离,又称Levenshtein距离(也叫做Edit Dist ...

  9. JDownload: 一款可以从网络上下载文件的小程序第四篇(整体架构描述)

    一 前言 时间过得真快,距离本系列博客第一篇的发布已经过去9个月了,本文是该系列的第四篇博客,将对JDownload做一个整体的描述与介绍.恩,先让笔者把记忆拉回到2017年年初,那会笔者在看Unix ...

  10. npm install 时--save-dev和--save的区别

    package.json中两个字段含义简介 一直在使用npm包管理器,对于npm install module --save-dev 和 npm install module --save这两个的区别 ...