BP算法训练单隐层前馈神经网络

一、实践目的

用BP算法训练单隐层前馈神经网络,实现对Iris数据分类。

二、实践内容

数据划分:训练和测试数据划分参考网站上论文中的划分。
要求1:程序画出BP算法迭代过程中训练准确性曲线;
要求2:列表给出10次独立实验平均错误率和标准差;
要求3:讨论BP算法中学习系数的变化对训练错误率的影响,画出曲线;
要求4:在权值更新公式总加入动量项重复以上实验;
要求5:程序代码和实验结果均需拷贝回去。
1、人工神经网络概述
1.1、人工神经网络的概念
人工神经网络(Artificial Neural Network,ANN)简称神经网络(NN),是基于生物学中神经网络的基本原理,在理解和抽象了人脑结构和外界刺激响应机制后,以网络拓扑知识为理论基础,模拟人脑的神经系统对复杂信息的处理机制的一种数学模型。该模型以并行分布的处理能力、高容错性、智能化和自学习等能力为特征,将信息的加工和存储结合在一起,以其独特的知识表示方式和智能化的自适应学习能力,引起各学科领域的关注。它实际上是一个有大量简单元件相互连接而成的复杂网络,具有高度的非线性,能够进行复杂的逻辑操作和非线性关系实现的系统。
1.2、人工神经网络的结构
人工神经元结构:人工神经元的研究源于脑神经元学说,19世纪末,在生物、生理学领域,Waldeger等人创建了神经元学说。
人工神经网络是由大量处理单元经广泛互连而组成的人工网络,用来模拟脑神经系统的结构和功能。而这些处理单元我们把它称作人工神经元。人工神经网络可看成是以人工神经元为节点,用有向加权弧连接起来的有向图。在此有向图中,人工神经元就是对生物神经元的模拟,而有向弧则是轴突----突触----树突对的模拟。有向弧的权值表示相互连接的两个人工神经元间相互作用的强弱。人工神经元结构如下图1.1所示:
在这里插入图片描述
图1.1 人工神经元模型,对于某个处理单元(神经元)来说,假设来自其他处理单元(神经元)i的信息为 ,它们与本处理单元的互相作用强度即连接权值为 ,处理单元的内部阈值为 。那么本处理单元(神经元)的输入为: ,而处理单元的输出为: 。式中, 为第i个元素的输入, 为第i个处理单元与本处理单元的互联权重即神经元连接权值。 称为激活函数或作用函数,它决定节点(神经元)的输出。 表示隐含层神经节点的阈值。
神经网络的主要工作是建立模型和确定权值,一般有前向型和反馈型两种网络结构。通常神经网络的学习和训练需要一组输入数据和输出数据对,选择网络模型和传递、训练函数后,神经网络计算得到输出结果,根据实际输出和期望输出之间的误差进行权值的修正,在网络进行判断的时候就只有输入数据而没有预期的输出结果。神经网络一个相当重要的能力是其网络能通过它的神经元权值和阈值的不断调整从环境中进行学习,直到网络的输出误差达到预期的结果,就认为网络训练结束。
2、BP神经网络
BP算法最早由Werbos于1974年提出,1985年Rumelhart等人发展了该理论,是一种按照误差逆向传播算法训练的多层前馈神经网络。BP算法是由学习过程由信号的正向传播与误差的反向传播两个过程组成。由于多层前馈网络的训练经常采用误差反向传播算法,人们也常把将多层前馈网络直接称为BP网络。(来源于百度百科的解释)
基本BP算法包括信号的前向传播和误差的反向传播两个过程。即计算误差输出时按从输入到输出的方向进行,而调整权值和阈值则从输出到输入的方向进行。正向传播时,输入信号通过隐含层作用于输出节点,经过非线性变换,产生输出信号,若实际输出与期望输出不相符,则转入误差的反向传播过程。误差反传是将输出误差通过隐含层向输入层逐层反传,并将误差分摊给各层所有单元,以从各层获得的误差信号作为调整各单元权值的依据。通过调整输入节点与隐层节点的联接强度和隐层节点与输出节点的联接强度以及阈值,使误差沿梯度方向下降,经过反复学习训练,确定与最小误差相对应的网络参数(权值和阈值),训练即告停止。此时经过训练的神经网络即能对类似样本的输入信息,自行处理输出误差最小的经过非线形转换的信息。BP神经网络的一般结构如图2.1所示。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3、BP神经网络的训练算法
梯度下降法及其优化,利用一阶的梯度信息找到函数局部最优解的一种方法,也是机器学习里面最简单最常用的一种优化方法。梯度下降法是直线搜索方法中的一种,主要迭代公式如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
标准的梯度梯度下降算法是一种贪心算法,虽然可以很有效地求解优化问题,但是可能会陷入局部极小值。为了避免寻找优化解的过程中陷入局部极小值,D.E.Rumelhart提出了一种方法,该方法是在修改规则中增加一个动量项。该项会考虑之前时刻梯度的贡献,其权值迭代公式如下所示:
在这里插入图片描述
第一项是常规算法的学习因子项,第二项是动量项, 为动量因子。由于加入了之前时刻梯度的贡献,这相当于给迭代过程添加了一个低通滤波器,可以使网络忽略误差曲面上的细节特征,从而避免了陷入周部极小值的问题。
另外,在基本网络算法中,一般学习因子项n取为固定值,为了更好的控制网络的收敛性和学习速度,可以根据需要选择自适应的可变学习因子,则上述方法称之为自适应学习算法。

三、实践结果

本实验用python进行模拟分类,部分示意图由matlab库进行仿真实验。
1.实验数据集
Iris数据集是常用的分类实验数据集,由Fisher收集整理。Iris也称鸢尾花卉数据集,是一类多重变量分析的数据集。数据集包含150个数据集,分为3类,每类50个数据,每个数据包含4个属性[4]。可通过花萼长度,花萼宽度,花瓣长度,花瓣宽度4个属性预测鸢尾花卉属于(Setosa,Versicolour,Virginica)三个种类中的哪一类。如下图
在这里插入图片描述
本实验中将Iris数据集分为2组,每组各75个样本,每组中每种花各有25个样本。其中一组作为训练样本,另外一组作为检验样本。为了方便训练,将3类花分别编号为1,2,3。
2.创建BP神经网络
使用python的sklearn库进行读取数据,并用numpy等专业数据分析工具进行函数的建立和部分图形的绘制,自己编写函数(网上借鉴)建立BP神经网络模型。本实验采用如图4.1所示的BP神经网络通用模型,其中,输入层神经元数目为4,分别读取Iris数据集的4个属性,即花萼长度、花萼宽度、花瓣长度和花瓣宽度。共设置两个隐含层,隐含层节点数目分别为10和3。输出层神经元数目为3,分别对应样本属于某一品种的可能性的大小。
经过代码运行,
程序画出BP算法迭代过程中训练准确性曲线如下:
在这里插入图片描述
经过实验,10次平均错误率与错误方差为:
在这里插入图片描述
部分运行结果如图,其中,1代表失败,0 代表成功
在这里插入图片描述
在这里插入图片描述
首先对梯度下降法及其改进算法进行实验,分别使用标准梯度下降法,带有动量项的梯度下降法,以及带有动量项的自适应学习算法进行对比实验,实验结果如图4.2到4.3所示
在这里插入图片描述
图4.2标准梯度下降法训练性能,识别率为86.667%
在这里插入图片描述
图4.3带有动量项的梯度下降法训练性能,识别率为94.667%
3.代码实现

rom __future__ import division
import pandas
import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics import roc_auc_score
from sklearn.metrics import confusion_matrix
################定义激活函数~##########################################

def sigmoid_activation(x, theta):
    x = np.asarray(x)
    theta = np.asarray(theta)
    return 1 / (1 + np.exp(-np.dot(theta.T, x)))



# 将模型的函数凝结为一个类,这是很好的一种编程习惯
class NNet3:
    # 初始化必要的几个参数
    def __init__(self, learning_rate=0.5, maxepochs=1e4, convergence_thres=1e-5, hidden_layer=4):
        self.learning_rate = learning_rate
        self.maxepochs = int(maxepochs)
        self.convergence_thres = 1e-5
        self.hidden_layer = int(hidden_layer)

    #  计算最终的误差
    def _multiplecost(self, X, y):
        # l1是中间层的输出,l2是输出层的结果
        l1, l2 = self._feedforward(X)
        # 计算误差,这里的l2是前面的h
        inner = y * np.log(l2) + (1-y) * np.log(1-l2)
        # 添加符号,将其转换为正值
        return -np.mean(inner)

    # 前向传播函数计算每层的输出结果
    def _feedforward(self, X):
        # l1是中间层的输出
        l1 = sigmoid_activation(X.T, self.theta0).T
        # 为中间层添加一个常数列
        l1 = np.column_stack([np.ones(l1.shape[0]), l1])
        # 中间层的输出作为输出层的输入产生结果l2
        l2 = sigmoid_activation(l1.T, self.theta1)
        return l1, l2

    # 传入一个结果未知的样本,返回其属于1的概率
    def predict(self, X):
        _, y = self._feedforward(X)
        return y

    # 学习参数,不断迭代至参数收敛,误差最小化
    def learn(self, X, y):
        nobs, ncols = X.shape
        self.theta0 = np.random.normal(0,0.01,size=(ncols,self.hidden_layer))
        self.theta1 = np.random.normal(0,0.01,size=(self.hidden_layer+1,1))

        self.costs = []
        cost = self._multiplecost(X, y)
        self.costs.append(cost)
        costprev = cost + self.convergence_thres+1
        counter = 0

        for counter in range(self.maxepochs):
            # 计算中间层和输出层的输出
            l1, l2 = self._feedforward(X)

            # 首先计算输出层的梯度,再计算中间层的梯度
            l2_delta = (y-l2) * l2 * (1-l2)
            l1_delta = l2_delta.T.dot(self.theta1.T) * l1 * (1-l1)

            # 更新参数
            self.theta1 += l1.T.dot(l2_delta.T) / nobs * self.learning_rate
            self.theta0 += X.T.dot(l1_delta)[:,1:] / nobs * self.learning_rate

            counter += 1
            costprev = cost
            cost = self._multiplecost(X, y)  # get next cost
            self.costs.append(cost)
            if np.abs(costprev-cost) < self.convergence_thres and counter > 500:
                break
  • 13
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Conn_w

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值