首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

详解 BP 神经网络基本原理及 C 语言实现

BP(Back Propagation)即反向传播,指的是一种按照误差反向传播来训练神经网络的方法。而 BP 神经网络即为一种按照误差反向传播的方法训练的神经网络,是一种应用十分广泛的神经网络。

BP 神经网络主要可以解决以下两种问题:

分类问题:用给定的输入向量和标签训练网络,实现网络对输入向量的合理分类。

函数逼近问题:用给定的输入向量和输出向量训练网络,实现对函数的逼近。

本文主要介绍 BP 神经网络的基本结构,而后简单介绍用 C 语言实现神经网络必需要用到的语法知识(老手请放心跳过),最后一步一步从构建单个神经元开始到完成整个神经网络的构建和训练。

VS2013 安装及新建工程

安装过程

由于本文主要还是面向初学者,考虑到有些小白朋友的需求,所以还是简单介绍下软件安装和使用,此部分可选择性跳过。

下载完成后如下图。

解压后,如下图所示。

双击运行如下的 exe 文件。

出现下图所示的界面,在此可以修改安装位置,建议设置成全英文路径。

之后按照默认设置一路下一步到安装完成即可。但安装完成后默认不会生成桌面快捷方式,需要从开始菜单栏运行,也可以从开始菜单栏创建桌面快捷方式。

新建工程

首先运行VS2013,得到如下界面。

点击左上角的 “文件" -> "新建” -> "项目"。在下图所示的界面上可以修改保存名称和路径。

选择 “visual c++” -> “Win32 控制台应用程序"后点击“确定”,出现如下界面。

单击下一步,如下图所示。

勾选“空项目”后单击“完成”后,出现如下界面,此处重点是观察右侧的工程结构。

我们在右边的“解决方案管理器”选择“源文件”,右键选择“添加” -> “新建项”,如下图所示。

在出现的新界面的下方重命名为 main.cpp,如下图所示。

按照相同的方法在源文件中再添加一个 neuralnetwork.cpp,在头文件中添加 neuralnetwork.h。

最后完成的工程结构非常简单,如下图所示。

我们写点简单的代码,测试下整个工程能否编译通过,三部分的代码如下。

main.cpp

neural_network.cpp:

neural_network.h:

这是个简单的测试程序,如果一切正常就会输出 HelloWorld,至此软件安装和工程新建就结束了。

BP 神经网络原理

人工神经元模型

人工神经元模型如下图所示。

一般神经元模型包含这样几个要素:

输入:X1、X2、X3......Xn(可以有多个)。

权重:W1、W2、W3......Wn。

偏置:Bias。

激活函数:f(x)。

输出:y(仅一个)。

这里需要重点说明的是激活函数。如果不加入激活函数,只是简单的对输入进行加权求和,那么整个模型就是个线性模型,而线性模型的表示能力是非常有限的,因此通过加入激活函数的方式给模型引入非线性因素,以提高模型的表示能力,所以一般情况下会采用非线性函数作为激活函数。常见的激活函数有 Sigmoid、Tanh、Step、ReLU、Softmax 等。

本文只用 Sigmoid 函数,下图给出了 Sigmoid 函数图像。

现在神经元模型的结构比较清楚了,下面看看如何计算模型的输出。通过给定的权重对输入进行加权求和后(默认加上偏置 Bias),再将得到的和作为参数输入一个激活函数,得到的激活函数的输出值即为神经元的输出。

对应的数学公式如下:

下面举个例子来说明一下计算输出的过程。

设 X1=1,X2=0,X3=0,W1=0.1,W2=0.2,W3=0.3,Bias=0.1,f(x)=x。

由上面给出的计算公式可得:

z = X1W1+X2W2+X3*W3+Bias = 0.1+0+0+0.1 = 0.2

y = f(z) = z = 0.2

学过初高中生物的朋友应该可以看出,人工神经元模型的 X1、X2、X3 作为输入,和生物神经元的树突是非常相似的。而模型的 y 作为唯一的输出,和生物神经元的轴突也是非常相似。仔细观察对比还能发现更多的相似之处,此处不做更多讨论。

下面简单介绍一下人工神经元模型的训练方法。为了减少不必要的演示计算步骤,这里我们用只有两个输入一个输出(只有 X1、X2)的模型进行演示,方法如下。

先给模型一个任意权值和偏置,设 W1=0,W2=0,Bias=0,再设激活函数为:

再给定两组训练用的数据,模拟一个简单的二分类问题:

第一组:data1=1,data2=1,期望输出aim_output1=1

第二组:data3=-1,data4=-1,期望输出aim_output2=0

然后我们先把第一组 data 代入模型根据前面所说的计算神经元输出的方法进行计算,得到实际输出real_output1=f(data1W1+data2W2+Bias)=f(0)=0。

实际输出realoutput1和期望输出aimoutput1之间就存在一个差值err1=aimoutput1-realoutput1=1。

根据这个差值,可以通过如下公式来修正我们随机给定的权值和偏置:

W1=W1+etaerr1data1

W2=W2+etaerr1data2

Bias=Bias+eta*err1

这里的 eta 表示学习率,一般取 0~1 之间的值。eta 值越大学习速率也越快,也就是每一次训练,权值和偏置的变动越大,但也并不是越大越好。如果 eta 过大容易产生震荡而不能稳定到目标值,若 eta 值越小,则效果相反。这里我们简单的取 eta=1,带入计算式可得经过一次修正过后的权值和偏置:

W1=1,W2=1,Bias=1

注意,这里第一次训练还没结束,还要继续代入第二组的 data,并且要记住 W1、W2、Bias 已经改变,通过相同的方法计算输出:

real_output2=f(data3W1+data4W2+Bias)=f(-1-1+1)=0

计算差值为:

err2=aimoutput2-realoutput2=0

由于实际输出和期望输出没有误差,所以不用修正权值和偏置(也可以看做变化量为0)。

这样第一次训练结束,继续下一次训练。

还是先把第一组 data 代入模型进行计算得到实际输出:

real_output1=f(data1W1+data2W2+Bias)=f(11+11+1)=1

计算差值:

err1=aimoutput1-realoutput1=0

由于实际输出和期望输出没有误差,所以不修正权值和偏置。

再把第二组 data 代入模型得输出:

real_output2=f(data3W1+data4W2+Bias)=f(-1-1+1)=0

计算差值:

err2=aimoutput2-realoutput2=0

由于实际输出和期望输出没有误差,所以不修正权值和偏置。

至此训练完成,这个模型已经能对输入的两组数据准确分类,现在给出解决这个二分类问题的 C 语言代码。

运行结果如下图所示。

和我们的计算结果一致,也是第二次训练得出正确的分类。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180405B1902U00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券