模式识别合集-多层感知器网络(附BP算法matlab代码)
一、网络结构
- 三层网络结构,输入层->隐层->输出层
- 前向传播:
h = W 1 ∗ x h=W_1*x h=W1∗x
O u t = W 2 ∗ h Out=W_2*h Out=W2∗h
二、BP算法
- 选择损失函数为均方根损失函数
- 链式法则计算损失到各个权值的偏导
- 隐层 -> 输出层
ϑ E ϑ W i j = ϑ E ϑ O u t o i ∗ ϑ O u t o i ϑ I n o i ∗ ϑ I n o i ϑ W i j = − ( t a r g e t o i − o u t o i ) ∗ o u t o i ∗ ( 1 − o u t o i ) ∗ o u t h j \frac{\vartheta E}{\vartheta W_{ij}}=\frac{\vartheta E}{\vartheta Out_{oi}}*\frac{\vartheta Out_{oi}}{\vartheta In_{oi}}*\frac{\vartheta In_{oi}}{\vartheta W_{ij}}=-(target_{oi}-out_{oi})*out_{oi}*(1-out_{oi})*out_{hj} ϑWijϑE=ϑOutoiϑE∗ϑInoiϑOutoi∗ϑWijϑInoi=−(targetoi−outoi)∗outoi∗(1−outoi)∗outhj - 输入层 -> 隐层
ϑ E ϑ W i j = ϑ E ϑ O u t h i ∗ ϑ O u t h i ϑ I n h i ∗ ϑ I n h i ϑ W i j \frac{\vartheta E}{\vartheta W_{ij}}=\frac{\vartheta E}{\vartheta Out_{hi}}*\frac{\vartheta Out_{hi}}{\vartheta In_{hi}}*\frac{\vartheta In_{hi}}{\vartheta W_{ij}} ϑWijϑE=ϑOuthiϑE∗ϑInhiϑOuthi∗ϑWijϑInhi
= ( ϑ E ϑ O u t o 1 ∗ ϑ O u t o 1 ϑ I n o 1 + ϑ E ϑ O u t o 2 ∗ ϑ O u t o 2 ϑ I n o 2 ) ∗ ϑ O u t h i ϑ I n h i ∗ ϑ I n h i ϑ W i j =(\frac{\vartheta E}{\vartheta Out_{o1}}*\frac{\vartheta Out_{o1}}{\vartheta In_{o1}}+\frac{\vartheta E}{\vartheta Out_{o2}}*\frac{\vartheta Out_{o2}}{\vartheta In_{o2}})*\frac{\vartheta Out_{hi}}{\vartheta In_{hi}}*\frac{\vartheta In_{hi}}{\vartheta W_{ij}} =(ϑOuto1ϑE∗ϑIno1ϑOuto1+ϑOuto2ϑE∗ϑIno2ϑOuto2)∗ϑInhiϑOuthi∗ϑWijϑInhi
- 隐层 -> 输出层
- 更新权值
W i j = W i j − R ∗ ϑ E ϑ W i j Wij=Wij-R*\frac{\vartheta E}{\vartheta W_{ij}} Wij=Wij−R∗ϑWijϑE
三、Matlab代码实现
- datagen.m
function [points,group] = datagen(radio)
% 随机生成1000个数据
points = rand(1000,2);
group = zeros(1000,1);
% 给数据分类做标记
for i = 1:1000
if sqrt((points(i,1)-0.5)^2+(points(i,2)-0.5)^2) < radio
group(i,1) = 1;
else
group(i,1) = 0;
end
end
- sigmoid.m
function y=sigmoid(x)
y=1./(1+exp(-x));
end
- BP.m
clear;
% 预定义参数
learn_rate = 0.01; % 学习率
train_times = 1000; % 训练轮数
hidden_nodes = 12; % 隐层节点数
% 生成数据
[data,lable] = datagen(0.5);
group = [lable,1-lable];
total_loss = zeros(train_times,1);
x_axis = 1:1:train_times;
% 选取90%作为训练集,剩下的作为测试集
index = randperm(1000,900);
train = data(index,:);
test = data;
test(index,:)=[];
train_target = group(index,:);
test_target = group;
test_target(index,:)=[];
% 预定义权值
% 输入层
% 隐层
W1 = rand(hidden_nodes,2);
b1 = zeros(hidden_nodes,1);
% 输出层
W2 = rand(2,hidden_nodes);
b2 = zeros(2,1);
% 训练
sumMSE = 1;
runCount = 0;
for j = 1:train_times
sumMSE = 0;
for i = 1:900
% 前向传播
target = train_target(i,:)';
X = train(i,:)';
layer1 = sigmoid(W1*X+b1);
out = sigmoid(W2*layer1+b2);
error = target-out;
% 反向传播
% 链式法则
delta_out = -diag(out.*(1-out))*error;
% delta_hide = (delta_out(1)*W2(1,:)+delta_out(2)*W2(2,:))'.*layer1.*(1-layer1);
delta_hide = diag(layer1.*(1-layer1))*W2'*delta_out;
% 更新权值
update_W2 = delta_out*layer1';
update_W1 = delta_hide*X';
W2 = W2 - update_W2*learn_rate;
W1 = W1 - update_W1*learn_rate;
sumMSE = sumMSE + sum(error .* error);
end
sumMSE = sqrt(sumMSE) / 900;
runCount = runCount + 1;
total_loss(j) = sumMSE;
fprintf("loss = %.4f\r\n",sumMSE);
end
% 测试
total_acc = 0;
for i = 1:100
target = test_target(i,:)';
X = test(i,:)';
layer1 = sigmoid(W1*X+b1);
out = sigmoid(W2*layer1+b2);
if find(target==1)==find(out==max(out))
total_acc = total_acc+1;
end
end
% 输出准确率
total_acc = total_acc/100;
fprintf("acc : %.2f\r\n",total_acc);
plot(x_axis,total_loss);
四、实验结果
从数据集中随机选取900个数据作为训练集,训练1000次,剩下的100个数据作为测试集
-
隐层节点数为4
- 学习率为0.1,测试准确率为0.83
图1 学习率为0.1时模型收敛变化 - 学习率为0.05,测试准确率为0.82
图2 学习率为0.05时模型收敛变化 - 学习率为0.01,测试准确率为0.81
图1 学习率为0.01时模型收敛变化 - 学习率为0.1,测试准确率为0.83
-
隐层节点数为 6
- 学习率为0.1,测试准确率为0.87
图1 学习率为0.1时模型收敛变化 - 学习率为0.05,测试准确率为0.94
图1 学习率为0.05时模型收敛变化 - 学习率为0.01,测试准确率为0.77
图1 学习率为0.01时模型收敛变化 - 学习率为0.1,测试准确率为0.87
-
隐层节点数为 12
- 学习率为0.1,测试准确率为0.97
图1 学习率为0.1时模型收敛变化 - 学习率为0.05,测试准确率为0.89
图1 学习率为0.05时模型收敛变化 - 学习率为0.01,测试准确率为0.81
图1 学习率为0.01时模型收敛变化 - 学习率为0.1,测试准确率为0.97