简单易学的机器学习算法——神经网络之BP神经网络
时间:2022-05-04
本文章向大家介绍简单易学的机器学习算法——神经网络之BP神经网络,主要内容包括一、BP神经网络的概念、二、BP神经网络的流程、2、隐含层的输出、3、输出层的输出、4、误差的计算、5、权值的更新、6、偏置的更新、7、判断算法迭代是否结束、三、实验的仿真、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
一、BP神经网络的概念
BP神经网络是一种多层的前馈神经网络,其主要的特点是:信号是前向传播的,而误差是反向传播的。具体来说,对于如下的只含一个隐层的神经网络模型:
(三层BP神经网络模型)
BP神经网络的过程主要分为两个阶段,第一阶段是信号的前向传播,从输入层经过隐含层,最后到达输出层;第二阶段是误差的反向传播,从输出层到隐含层,最后到输入层,依次调节隐含层到输出层的权重和偏置,输入层到隐含层的权重和偏置。
二、BP神经网络的流程
在知道了BP神经网络的特点后,我们需要依据信号的前向传播和误差的反向传播来构建整个网络。
1、网络的初始化
2、隐含层的输出
如上面的三层BP网络所示,隐含层的输出
为
3、输出层的输出
4、误差的计算
5、权值的更新
权值的更新公式为:
这里需要解释一下公式的由来:
这是误差反向传播的过程,我们的目标是使得误差函数达到最小值,即
,我们使用梯度下降法:
- 隐含层到输出层的权重更新
则权重的更新公式为:
- 输入层到隐含层的权重更新
其中
则权重的更新公式为:
6、偏置的更新
偏置的更新公式为:
- 隐含层到输出层的偏置更新
则偏置的更新公式为:
- 输入层到隐含层的偏置更新
其中
则偏置的更新公式为:
7、判断算法迭代是否结束
有很多的方法可以判断算法是否已经收敛,常见的有指定迭代的代数,判断相邻的两次误差之间的差别是否小于指定的值等等。
三、实验的仿真
在本试验中,我们利用BP神经网络处理一个四分类问题,最终的分类结果为:
MATLAB代码
主程序
%% BP的主函数
% 清空
clear all;
clc;
% 导入数据
load data;
%从1到2000间随机排序
k=rand(1,2000);
[m,n]=sort(k);
%输入输出数据
input=data(:,2:25);
output1 =data(:,1);
%把输出从1维变成4维
for i=1:2000
switch output1(i)
case 1
output(i,:)=[1 0 0 0];
case 2
output(i,:)=[0 1 0 0];
case 3
output(i,:)=[0 0 1 0];
case 4
output(i,:)=[0 0 0 1];
end
end
%随机提取1500个样本为训练样本,500个样本为预测样本
trainCharacter=input(n(1:1600),:);
trainOutput=output(n(1:1600),:);
testCharacter=input(n(1601:2000),:);
testOutput=output(n(1601:2000),:);
% 对训练的特征进行归一化
[trainInput,inputps]=mapminmax(trainCharacter');
%% 参数的初始化
% 参数的初始化
inputNum = 24;%输入层的节点数
hiddenNum = 50;%隐含层的节点数
outputNum = 4;%输出层的节点数
% 权重和偏置的初始化
w1 = rands(inputNum,hiddenNum);
b1 = rands(hiddenNum,1);
w2 = rands(hiddenNum,outputNum);
b2 = rands(outputNum,1);
% 学习率
yita = 0.1;
%% 网络的训练
for r = 1:30
E(r) = 0;% 统计误差
for m = 1:1600
% 信息的正向流动
x = trainInput(:,m);
% 隐含层的输出
for j = 1:hiddenNum
hidden(j,:) = w1(:,j)'*x+b1(j,:);
hiddenOutput(j,:) = g(hidden(j,:));
end
% 输出层的输出
outputOutput = w2'*hiddenOutput+b2;
% 计算误差
e = trainOutput(m,:)'-outputOutput;
E(r) = E(r) + sum(abs(e));
% 修改权重和偏置
% 隐含层到输出层的权重和偏置调整
dw2 = hiddenOutput*e';
db2 = e;
% 输入层到隐含层的权重和偏置调整
for j = 1:hiddenNum
partOne(j) = hiddenOutput(j)*(1-hiddenOutput(j));
partTwo(j) = w2(j,:)*e;
end
for i = 1:inputNum
for j = 1:hiddenNum
dw1(i,j) = partOne(j)*x(i,:)*partTwo(j);
db1(j,:) = partOne(j)*partTwo(j);
end
end
w1 = w1 + yita*dw1;
w2 = w2 + yita*dw2;
b1 = b1 + yita*db1;
b2 = b2 + yita*db2;
end
end
%% 语音特征信号分类
testInput=mapminmax('apply',testCharacter',inputps);
for m = 1:400
for j = 1:hiddenNum
hiddenTest(j,:) = w1(:,j)'*testInput(:,m)+b1(j,:);
hiddenTestOutput(j,:) = g(hiddenTest(j,:));
end
outputOfTest(:,m) = w2'*hiddenTestOutput+b2;
end
%% 结果分析
%根据网络输出找出数据属于哪类
for m=1:400
output_fore(m)=find(outputOfTest(:,m)==max(outputOfTest(:,m)));
end
%BP网络预测误差
error=output_fore-output1(n(1601:2000))';
k=zeros(1,4);
%找出判断错误的分类属于哪一类
for i=1:400
if error(i)~=0
[b,c]=max(testOutput(i,:));
switch c
case 1
k(1)=k(1)+1;
case 2
k(2)=k(2)+1;
case 3
k(3)=k(3)+1;
case 4
k(4)=k(4)+1;
end
end
end
%找出每类的个体和
kk=zeros(1,4);
for i=1:400
[b,c]=max(testOutput(i,:));
switch c
case 1
kk(1)=kk(1)+1;
case 2
kk(2)=kk(2)+1;
case 3
kk(3)=kk(3)+1;
case 4
kk(4)=kk(4)+1;
end
end
%正确率
rightridio=(kk-k)./kk
激活函数
%% 激活函数
function [ y ] = g( x )
y = 1./(1+exp(-x));
end
- 线段树入门总结
- 从零基础学三分查找
- Codeforces Beta Round #1 A,B,C
- 线性分类器-中篇
- isupper()函数
- HDU 5882 Balanced Game
- 超级玛丽游戏
- POJ 3673 Cow Multiplication
- HDU 5144 NPY and shot(物理运动学+三分查找)
- 深度|Python股票数据分析
- HDU 2438 Turn the corner(三分查找)
- UVAlive 3708 Graveyard(最优化问题)
- HDU 1754 I Hate It(线段树之单点更新,区间最值)
- Selenium2+python自动化19-单选和复选框
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- c语言之指向指针的指针
- c语言之利用#if #endif来进行注释或者运行不同的主函数
- c++之对组pair
- c++STL容器之set/multiset容器
- c++STL容器之list容器
- c++STL容器之deque容器
- Web自动化必会「Web基础、元素定位、元素操作、Selenium运行原理、项目实战+框架」
- HTML5 meta viewport参数详解
- 二分查找应该都会,那么二分查找的变体呢?
- TypeScript 实战算法系列(三):实现链表与变相链表
- JavaScript 测试系列实战(一):使用 Jest 和 Enzyme 测试 React 组件
- TypeScript 实战算法系列(二):实现队列与双端队列
- VBA位操作
- VBA编写Ribbon Custom UI编辑器07——写入xml
- Linux下在文件夹所有文件中查找相关内容