RBF神經網路簡單介紹與MATLAB實現

芥末的無奈發表於2017-05-30


對應課件的下載地址:https://download.csdn.net/download/weiwei9363/10766981

RBF的直觀介紹

RBF具體原理,網路上很多文章一定講得比我好,所以我也不費口舌了,這裡只說一說對RBF網路的一些直觀的認識

1 RBF是一種兩層的網路

是的,RBF結構上並不複雜,只有兩層:隱層和輸出層。其模型可以數學表示為:
yj=i=1nwijϕ(xui2),(j=1,,p) y_j = \sum_{i=1}^n w_{ij} \phi(\Vert x - u_i\Vert^2), (j = 1,\dots,p)
image_1bhb7ve1n1k694ld13e7ml4dv69.png-86.4kB
image_1bhb883omc001gpb1sgr1pdo13gom.png-59.4kB

2 RBF的隱層是一種非線性的對映

RBF隱層常用啟用函式是高斯函式:
ϕ(xu)=exu2σ2 \phi(\Vert x - u\Vert) = e^{-\frac{\Vert x-u\Vert^2}{\sigma^2}}

3 RBF輸出層是線性的

4 RBF的基本思想是:將資料轉化到高維空間,使其在高維空間線性可分

RBF隱層將資料轉化到高維空間(一般是高維),認為存在某個高維空間能夠使得資料在這個空間是線性可分的。因此啊,輸出層是線性的。這和核方法的思想是一樣一樣的。下面舉個老師PPT上的例子:
image_1bhb8jce7vfn1vernpf1g9a0e13.png-70kB
上面的例子,就將原來的資料,用高斯函式轉換到了另一個二維空間中。在這個空間裡,XOR問題得到解決。可以看到,轉換的空間不一定是比原來高維的。

RBF學習演算法

image_1bhb8rkpfasorc61g01ch11m211g.png-84.7kB
對於上圖的RBF網路,其未知量有:中心向量uiu_i,高斯函式中常數σ\sigma,輸出層權值WW
學習演算法的整個流程大致如下圖:
image_1bhb91mfg14nmve8amcji21vkf1t.png-31.9kB
具體可以描述為:

  1. 利用kmeans演算法尋找中心向量uiu_i
  2. 利用kNN(K nearest neighbor)rule 計算 σ\sigma
    σi=1Kk=1Kukui2 \sigma_i = \sqrt{\frac{1}{K}\sum_{k=1}^K \Vert u_k - u_i\Vert^2}
  3. WW可以利用最小二乘法求得

Lazy RBF

可以看到原來的RBF挺麻煩的,又是kmeans又是knn。後來就有人提出了lazy RBF,就是不用kmeans找中心向量了,將訓練集的每一個資料都當成是中心向量。這樣的話,核矩陣Φ\Phi就是一個方陣,並且只要保證訓練中的資料是不同的,核矩陣Φ\Phi就是可逆的。這種方法確實lazy,缺點就是如果訓練集很大,會導致核矩陣Φ\Phi也很大,並且要保證訓練集個數要大於每個訓練資料的維數。
image_1bhba9lrnh8f1n2o5pt1pmksv92a.png-54kB

MATLAB實現RBF神經網路

下面實現的RBF只有一個輸出,供大家參考參考。對於多個輸出,其實也很簡單,就是WW變成了多個,這裡就不實現了。

demo.m 對XOR資料進行了RBF的訓練和預測,展現了整個流程。最後的幾行程式碼是利用封裝形式進行訓練和預測。

clc;
clear all;
close all;

%% ---- Build a training set of a similar version of XOR
c_1 = [0 0];
c_2 = [1 1];
c_3 = [0 1];
c_4 = [1 0];

n_L1 = 20; % number of label 1
n_L2 = 20; % number of label 2


A = zeros(n_L1*2, 3);
A(:,3) = 1;
B = zeros(n_L2*2, 3);
B(:,3) = 0;

% create random points
for i=1:n_L1
   A(i, 1:2) = c_1 + rand(1,2)/2;
   A(i+n_L1, 1:2) = c_2 + rand(1,2)/2;
end
for i=1:n_L2
   B(i, 1:2) = c_3 + rand(1,2)/2;
   B(i+n_L2, 1:2) = c_4 + rand(1,2)/2;
end

% show points
scatter(A(:,1), A(:,2),[],'r');
hold on
scatter(B(:,1), B(:,2),[],'g');
X = [A;B];
data = X(:,1:2);
label = X(:,3);

%% Using kmeans to find cinter vector
n_center_vec = 10;
rng(1);
[idx, C] = kmeans(data, n_center_vec);
hold on
scatter(C(:,1), C(:,2), 'b', 'LineWidth', 2);

%% Calulate sigma 
n_data = size(X,1);

% calculate K
K = zeros(n_center_vec, 1);
for i=1:n_center_vec
   K(i) = numel(find(idx == i)); 
end

% Using knnsearch to find K nearest neighbor points for each center vector
% then calucate sigma
sigma = zeros(n_center_vec, 1);
for i=1:n_center_vec
    [n, d] = knnsearch(data, C(i,:), 'k', K(i));
    L2 = (bsxfun(@minus, data(n,:), C(i,:)).^2);
    L2 = sum(L2(:));
    sigma(i) = sqrt(1/K(i)*L2);
end

%% Calutate weights
% kernel matrix
k_mat = zeros(n_data, n_center_vec);

for i=1:n_center_vec
   r = bsxfun(@minus, data, C(i,:)).^2;
   r = sum(r,2);
   k_mat(:,i) = exp((-r.^2)/(2*sigma(i)^2));
end

W = pinv(k_mat'*k_mat)*k_mat'*label;
y = k_mat*W;
%y(y>=0.5) = 1;
%y(y<0.5) = 0;

%% training function and predict function
[W1, sigma1, C1] = RBF_training(data, label, 10);
y1 = RBF_predict(data, W, sigma, C1);
[W2, sigma2, C2] = lazyRBF_training(data, label, 2);
y2 = RBF_predict(data, W2, sigma2, C2);

image_1bhbap6djuvg9uu1trs145d1f3b2n.png-17.3kB
上圖是XOR訓練集。其中藍色的kmenas選取的中心向量。中心向量要取多少個呢?這也是玄學問題,總之不要太少就行,程式碼中取了10個,但是從結果yy來看,其實對於XOR問題來說,4個就可以了。

RBF_training.m 對demo.m中訓練的過程進行封裝

function [ W, sigma, C ] = RBF_training( data, label, n_center_vec )
%RBF_TRAINING Summary of this function goes here
%   Detailed explanation goes here

    % Using kmeans to find cinter vector
    rng(1);
    [idx, C] = kmeans(data, n_center_vec);
    
    % Calulate sigma 
    n_data = size(data,1);
    
    % calculate K
    K = zeros(n_center_vec, 1);
    for i=1:n_center_vec
        K(i) = numel(find(idx == i));
    end
    
    % Using knnsearch to find K nearest neighbor points for each center vector
    % then calucate sigma
    sigma = zeros(n_center_vec, 1);
    for i=1:n_center_vec
        [n] = knnsearch(data, C(i,:), 'k', K(i));
        L2 = (bsxfun(@minus, data(n,:), C(i,:)).^2);
        L2 = sum(L2(:));
        sigma(i) = sqrt(1/K(i)*L2);
    end
    % Calutate weights
    % kernel matrix
    k_mat = zeros(n_data, n_center_vec);
    
    for i=1:n_center_vec
        r = bsxfun(@minus, data, C(i,:)).^2;
        r = sum(r,2);
        k_mat(:,i) = exp((-r.^2)/(2*sigma(i)^2));
    end
    
    W = pinv(k_mat'*k_mat)*k_mat'*label;
end

RBF_lazytraning.m 對lazy RBF的實現,主要就是中心向量為訓練集自己,然後再構造核矩陣。由於Φ\Phi一定可逆,所以在求逆時,可以使用快速的’\‘方法

function [ W, sigma, C ] = lazyRBF_training( data, label, sigma )
%LAZERBF_TRAINING Summary of this function goes here
%   Detailed explanation goes here
    if nargin < 3
       sigma = 1; 
    end

    n_data = size(data,1);
    C = data;
    
    % make kernel matrix
    k_mat = zeros(n_data);
    for i=1:n_data
       L2 = sum((data - repmat(data(i,:), n_data, 1)).^2, 2);
       k_mat(i,:) = exp(L2'/(2*sigma));
    end
    
    W = k_mat\label;
end

RBF_predict.m 預測

function [ y ] = RBF_predict( data, W, sigma, C )
%RBF_PREDICT Summary of this function goes here
%   Detailed explanation goes here
    n_data = size(data, 1);
    n_center_vec = size(C, 1);
    if numel(sigma) == 1
       sigma = repmat(sigma, n_center_vec, 1);
    end
    
    % kernel matrix
    k_mat = zeros(n_data, n_center_vec);
    for i=1:n_center_vec
        r = bsxfun(@minus, data, C(i,:)).^2;
        r = sum(r,2);
        k_mat(:,i) = exp((-r.^2)/(2*sigma(i)^2));
    end
    
    y = k_mat*W;
end

相關文章