一,说明
1)有以下几个文件:
BP_Net.m–用于网络训练;
BPTest.m–用于测试;
net_value.m–用于求输出值;
sigmod_func.m–定义激活函数;
test_func.m–逼近的函数;

2)实验说明
1、本实现隐藏层采用tanh作为激活函数,输出层线性函数为激活函数;
2、逼近函数为sin(x) + cos(x);
3、由于逼近函数值为1附近,所以没有进行归一化处理;

二、程序
% BP神经网络
% x:样本输入,y为样本输出,hide_node_arry为神经网络隐藏层神经元个数
% w:权重 b:偏置项
function [w, b] = BP_Net(x, y, hide_node_array)

eps = 1e-10;
% 神经元节点个数
[xnum, xlen] = size(x);
[~, ylen] = size(y);
node_array = [xlen, hide_node_array, ylen];

% 初始化权重和偏置项
[w, b] = init_w_b(node_array);

L = length(node_array) – 1;

d_error = 1;
maxItorNum = 100000000;
num = 0;
while abs(d_error) > eps

% 遍历样本
sum_error = 0;
for i = 1: xnum

% 计算网络中的输入和输出值
[layer_in, layer_out] = net_value(w, b, x(i, :));

% 计算各层神经元误差
d = layer_out{L + 1};
error = calc_error(d, y(i), w, b, layer_in);
sum_error = sum_error + error{L};

% 更新权重w和偏置项b
[w, b] = adjust_w_b(error, w, b, layer_out);

end

d_error = sum_error / xnum;

fprintf(‘Iteration number = %d; d_error = %d\n’, num, d_error);
num = num + 1;

if mod(num, 100) == 0
plotf(w, b, num);
end

if num > maxItorNum
fprintf(‘d_error = %d\n’, d_error);
break;
end

end

end

% 计算各层神经元误差
function error = calc_error(d, y, w, b, layer_in)

% 神经元层数(不包括输入层)
L = length(b);
error = cell(1, L);

% 计算输出层误差(输出层采用线性函数)
error{L} = (d-y);

% 计算2~L-1层误差
for i = 1: L-1
layer = L – i;
error{layer} = calc_error_2(error{layer+1}, w{layer+1}, layer_in{layer});
end

end

% 计算所有神经元节点误差(2~L-1层)
function delta = calc_error_2(back_error, back_w, layer_in)

diff_f = @sigmod_diff_func;

node_num = length(layer_in);
back_node_num = length(back_error);
delta = zeros(node_num, 1);
for i = 1: node_num
for j = 1: back_node_num
delta(i) = delta(i) + back_error(j)*back_w(j, i)*diff_f(layer_in(i));
end
end

end

% 调整权重w和偏置项b,从前往后调节
function [w, b] = adjust_w_b(delta, w, b, layer_out)

alpha = 0.005; % 步长
L = length(b);

for i = 1: L
w{i} = adjust_w(w{i}, delta{i}, layer_out{i}, alpha);
b{i} = adjust_b(b{i}, delta{i}, alpha);
end

end

% 调整权重w
function w = adjust_w(w, delta, pre_layer_out, alpha)

node_num = length(delta); % 该层神经元节点个数和误差个数一样
input_node_num = length(pre_layer_out); % 前一层神经元节点个数
% 调整每个神经元节点对应的权重
for i = 1: node_num
for j = 1: input_node_num
w(i, j) = w(i, j) – alpha.*delta(i).*pre_layer_out(j);
end
end

end

% 调整偏置项
function b = adjust_b(b, delta, alpha)
node_num = length(delta); % 该层神经元节点个数和误差个数一样
for i = 1: node_num
b(i) = b(i) – alpha.*delta(i);
end
end

% 初始化权重和偏置项
function [w, b] = init_w_b(node_array)
layer = length(node_array);
w = cell(1, layer-1);
b = cell(1, layer-1);
for i = 2: layer
input_node_num = node_array(i-1);
node_num = node_array(i);
w{i-1} = rands(node_num, input_node_num);
b{i-1} = rands(node_num);
end
end

% sigmod导数
function v = sigmod_diff_func(x)
f = @sigmod_func;
v = 1 – f(x)*f(x);
end

function plotf(w, b, num)

f = @test_func;
x = linspace(-pi, pi, 50)’;
y = f(x);

tx = -pi:0.01:pi;
ty = tx;
index = 1;
for xi = tx
[~,o] = net_value(w, b, xi);
ty(index) = o{4};
index = index + 1;
end

hold on; cla reset;
plot(x, y, ‘*r’);
hold on;
plot(tx, ty, ‘-g’);
legend(‘points on test_func’, ‘net fit line’);
title([‘Iteration Num = ‘, num2str(num)]);

pause(0.05);
end

% 计算网络值
% layer_in每一层输入值(不包括输入层),layer_out每一层输出值 x输入样本
function [layer_in, layer_out] = net_value(w, b, x)

layer = length(b);
layer_in = cell(1, layer);
layer_out = cell(1, layer + 1);
layer_out{1} = x’;
f = @sigmod_func;

for i = 1: layer
wl = w{i};
bl = b{i};
node_num = length(bl);
input_node_num = length(layer_out{i});
pre_in = layer_out{i};

in = zeros(node_num, 1);
for j = 1: node_num
for k = 1: input_node_num
in(j) = in(j) + wl(j, k)*pre_in(k);
end
in(j) = in(j) + bl(j);
end

layer_in{i} = in;

if i == layer
layer_out{i+1} = in; % 输出层采用线性函数
else
layer_out{i+1} = f(in);
end

end

end

% 获取sigmod值
function v = sigmod_func(x)
v = (exp(x) – exp(-x))./(exp(x) + exp(-x));
end

% 拟合的函数
function func = test_func(x)
func = (sin(x) + cos(x))/1;
end

% Test
clear;clc;close;
format long g;

f = @test_func;
x = linspace(-pi, pi, 50)’;
y = f(x);

close all; figure;

[w, b] = BP_Net(x, y, [3,3]);

三、结果

 

版权声明:本文为fengchuicaodong原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/fengchuicaodong/p/12965001.html