精华内容
下载资源
问答
  • 本例中包含两层BP神经网络模板程序(可以直接调用,可定制中间层神经元个数,设置学习率,绘制衰减曲线,可用于简单的模式识别和预测)、一个调用的例程(包括简单的数据预处理如归一化的使用,测试结果准确率为98.3...
  • 设计一个BP神经网络对蝴蝶花进行分类 实验内容包括: BP神经网络的结构设计; 通过Python实现BP神经网络; 实验进行参数优化,对比不同参数的效果性能; 分析实验结果,优化BP神经网络结构;
  • 自己写的,编程渣渣,写的很乱,但也基本实现了,仅供参考。有朋友可以联系我相互讨论学习,
  • 前两期线性回归及逻辑回归项目已发布(见文末链接),今天来讲讲BP神经网络BP神经网络 全部代码 https://github.com/lawlite19/MachineLearning_Python/blob/master/NeuralNetwok/NeuralNetwork.py 神经网络...
  • bp神经网络python实现

    2018-11-17 12:23:20
    利用python实现bp神经网络,采用误差逆传播算法训练模型,并在一个toy set上进行了验证
  • 本文来自于cnblogs,人工神经网络是一种经典...回归和分类是常用神经网络处理的两类问题,如果你已经了解了神经网络的工作原理可以在http://playground.tensorflow.org/上体验一个浅层神经网络的工作过程.感知机(Percept
  • bp神经网络python代码实验,欢迎下载学习,注释详细
  • 主要为大家详细介绍了Python使用numpy实现BP神经网络,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • BP神经网络Python代码实现,短短的代码,实现大大的功能。附加详细注释。
  • 主要介绍了python实现BP神经网络回归预测模型,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • pythonBP神经网络做预测
  • python代码实现,可以调整网络结构,适用分类与回归问题,包含随机梯度下降、动量梯度下降,RMSProp、Adam优化算法。
  • 本文用Python实现了BP神经网络分类算法,根据鸢尾花的4个特征,实现3种鸢尾花的分类。 算法参考文章: iris_data_classification_bpnn_V1.py 需使用 bpnn_V1数据集 文件夹中的数据 iris_data_classification_bpnn_V2...
  • 波士顿房价预测的BP神经网络实现 1) 训练数据 housing.csv 使用波士顿房价数据 2) 使用Python代码实现前向和后向传播 3) 损失函数使用方差
  • 基于Python语言实现的Bp神经网络
  • 代码功能:对山东某地区历史温度数据进行BP神经网络训练,通过前三小时温度数据,预测第四小时温度值。数据来源:2016年4月份山东某地区温度数据,共30*24小时。1日到20日(20*24小时)数据为训练数据集,21到30日...
  • BP神经网络实现分类问题(python

    万次阅读 热门讨论 2018-11-14 20:06:12
    python版本:3.6 梯度更新 下面的代码 是对输出层和隐层的梯度计算,具体可参考周志华机器学习103页梯度更新公式 for i in range(self.outputn):#计算输出层的梯度 y=self.o[i] g[i]=y*(1-y)*(n[i]-y) for i ...

    一些代码解释

    python版本:3.6

    梯度更新

    下面的代码 是对输出层和隐层的梯度计算,具体可参考周志华机器学习103页梯度更新公式

            for i in range(self.outputn):#计算输出层的梯度
                y=self.o[i]
                g[i]=y*(1-y)*(n[i]-y)
          
            for i in range(self.hiddenn):#计算隐层的梯度
                wg=0
                for j in range(self.outputn):
                    wg=wg+self.ow[i][j]*g[j]
                #print(self.h[i])
                e[i]=self.h[i]*(1-self.h[i])*wg
    

    参数更新

    根据梯度更新权值和阈值

    for i in range(self.hiddenn): #更新隐层到输出层的权值ow
                for j  in range(self.outputn):
                    self.ow[i][j]=self.ow[i][j]+self.n*g[j]*self.h[i]
            for i in range(self.inputn):#更新输入层到隐层的权值iw
                for j in range(self.hiddenn):
                    self.iw[i][j]=self.iw[i][j]+self.n*e[j]*self.i[i]
    
            for i in range(self.hiddenn):#更新隐层的阈值
                self.hiddencells[i]=self.hiddencells[i]-self.n*e[i]
            for i in range(self.outputn):#更新输出层阈值
                self.outputcells[i]=self.outputcells[i]-self.n*g[i]
    

    代码

    import math
    import random
    #-*- coding:utf-8 -*-
    #random.seed(0) #使得随机值可预测
    
    class tools(): #定义一些工具函数
        def rand(a,b):#a到b之间一个随机数
            return (b-a)*random.random()+a
        def set_m(n,m):#产生一个n*m的矩阵
            a=[]
            for i in range(n):
                a.append([0.0]*m)
            return a 
        
        def sigmoid(x):#定义sigmoid函数和它的导数
            return 1.0/(1.0+math.exp(-x))
        def sigmoid_derivate(x):
            return x*(1-x) #sigmoid函数的导数
        
    class bpnn():
        def __init__(self):#初始化定义各个参数
            self.inputn=0
            self.hiddenn=0
            self.outputn=0 #分别初始化输入层,隐层和输出层的神经元个数
            self.outputcells=[]
            self.hiddencells=[]#定义输出和隐层神经元的阈值
            self.iw=[]
            self.ow=[]#输入层权值和输出层权值
            self.iwco=[]
            self.owco=[]#隐层和输出层矫正矩阵
            self.i=[]
            self.h=[]
            self.o=[]#神经元的值
            self.n=0.05#学习率
        def setup(self,inn,outn,hiddenn):#输入参数,建立一个神经网络
             self.inputn=inn;#输入层 
             self.outputn=outn;#输出层
             self.hiddenn=hiddenn;#隐层
    
             #随机初始化权值和阈值
             self.i=[0.0]*self.inputn
             self.o=[0.0]*self.outputn
             self.h=[0.0]*self.hiddenn
    
             self.iwc0o=tools.set_m(self.inputn,self.hiddenn)
             self.owco=tools.set_m(self.hiddenn,self.outputn)#初始化矫正矩阵备用
    
             self.hiddencells=[1.0]*self.hiddenn
             self.outputcells=[1.0]*self.outputn
             for i in range(self.hiddenn): #随机初始化阈值(0,1)
                 self.hiddencells[i]=tools.rand(0,1)
             for i in range(self.outputn):
                 self.outputcells[i]=tools.rand(0,1)
                 
             self.iw=tools.set_m(self.inputn,self.hiddenn)
             self.ow=tools.set_m(self.hiddenn,self.outputn)
             for i in range(self.inputn):#随机初始化权值(0,1)
                 for j  in range(self.hiddenn):
                     self.iw[i][j]=tools.rand(0,1)
             for i in range(self.hiddenn):   #随机初始化权值(0,1)
                 for j  in range(self.outputn):
                     self.ow[i][j]=tools.rand(0,1)
    
        def predict(self,n):#预测输出,n是输入列表
            self.i=n;
            for i in range(self.hiddenn):#更新隐层
                self.h[i]=0.0
                for j in range(self.inputn):
                    self.h[i]=self.h[i]+self.i[j]*self.iw[j][i]
                
                self.h[i]=tools.sigmoid(self.h[i]-self.hiddencells[i])
             
            for i in range(self.outputn):#更新输出层
                self.o[i]=0.0
                for j in range(self.hiddenn):
                    self.o[i]=self.o[i]+self.h[j]*self.ow[j][i]
                #print(self.o,self.outputcells)
    
                self.o[i]=tools.sigmoid(self.o[i]-self.outputcells[i])
                #print(self.o)
        def update(self,n):#更新权值和阈值,n是正确的输出
            g=[0.0]*self.outputn#输出层的梯度
            e=[0.0]*self.hiddenn#隐层的梯度
            for i in range(self.outputn):#计算输出层的梯度
                y=self.o[i]
                g[i]=y*(1-y)*(n[i]-y)
          
            for i in range(self.hiddenn):#计算隐层的梯度
                wg=0
                for j in range(self.outputn):
                    wg=wg+self.ow[i][j]*g[j]
                #print(self.h[i])
                e[i]=self.h[i]*(1-self.h[i])*wg
            
            for i in range(self.hiddenn): #更新隐层到输出层的权值ow
                for j  in range(self.outputn):
                    self.ow[i][j]=self.ow[i][j]+self.n*g[j]*self.h[i]
            for i in range(self.inputn):#更新输入层到隐层的权值iw
                for j in range(self.hiddenn):
                    self.iw[i][j]=self.iw[i][j]+self.n*e[j]*self.i[i]
    
            for i in range(self.hiddenn):#更新隐层的阈值
                self.hiddencells[i]=self.hiddencells[i]-self.n*e[i]
            for i in range(self.outputn):#更新输出层阈值
                self.outputcells[i]=self.outputcells[i]-self.n*g[i]
        def test(self,tn,tp):#测试测试集
             acc=0
             k=0
             for i in tn:
                 self.predict(i)
                 print(self.o,tp[k],)
                 if self.o[0]>0.5 and self.o[1]<0.5 and tp[k][0]==1 and tp[k][1]==0:
                     acc=acc+1
                     print(acc,)
                 if self.o[0]<0.5 and self.o[1]>0.5 and tp[k][0]==0 and tp[k][1]==1:
                     acc=acc+1
                     print(acc)
                 k=k+1
             acc=acc/k
             print(acc)
                     
        def train(self,n,p,tn,tp,vn,vp):#n是训练集数据,p是训练集的真实输出,tn是测试集输入,tp是测试集输出,vn,vp是训练集
            self.setup(len(n[0]),len(p[0]),int(math.sqrt(len(n[0])+len(p[0])))+5)#新建一个神经
    
            for time in range(1000):#最大训练次数
                acct1=0#训练集累计误差
                accv1=0#验证机累计误差
                acct2=0#训练集累计误差
                accv2=0#验证机累计误差
                k=0
                for i in n:
                    self.predict(i)
                    self.update(p[k])
                    
                    ek=0
                    
                    for j  in range(self.outputn):
                        ek=ek+math.pow((p[k][j]-self.o[j]),2)
                    ek=ek/2#均方误差
                    acct2=acct2+ek#平均误差
                    k=k+1
                acct2=acct2/k
                k=0
                for i in vn:
                    self.predict(i)
                    
                    ek=0
                    for j  in range(self.outputn):
                        ek=ek+math.pow((vp[k][j]-self.o[j]),2)
                    ek=ek/2#均方误差
                    accv2=accv2+ek#平均误差
                    k=k+1
                accv2=accv2/k
                if acct2>acct1 and accv2<accv1 and i!=0:#早停
                    break;
                if acct2<0.01:
                    break;
                acct1=acct2
                accv1=accv2
                #print(acct1)
    if __name__ == '__main__':
        nn = bpnn()
        #nn.train([[1,2,3],[4,5,6]],[[1,2],[1,2]],[[4,5,6],[4,1,6]],[[2,1],[1,1]],[[4,5,6],[4,1,6]],[[2,1],[1,1]])
        f = open('D:/毕业设计\数据集1/australian.txt','r')
        a=f.readlines()
        b=[]
        for i in a:#一些对数据的简单的处理 ,可以忽略
            i=i.strip("\n")
            i=i.split(",")
            c=list(i)
            for j in range(len(c)):
                c[j]=float(c[j])
            max1=max(c[0:len(c)-1])
            min1=min(c[0:len(c)-1])
            for j in range(len(c)-1):
                c[j]=(c[j]-min1)/(max1-min1)
            b.append(c)
        n=[]
        p=[]
        tn=[]
        tp=[]
        vn=[]
        vp=[]
        k=0
        for i in b:#一些对数据的简单的处理 ,可以忽略
            p.append(i[len(i)-1:len(i)])
            if p[k][0]==0:
                p[k].append(1.0)
            if p[k][0]==1:
                p[k].append(0.0)
            n.append(i[0:len(i)-1:1])
            k=k+1
        tn=n[500:600]
        tp=p[500:600]
        vn=n[600:620]
        vp=p[600:620]
        n=n[0:500]
        p=p[0:500]
        nn.train(n,p,tn,tp,vn,vp)
        nn.test(tn,tp)
        f.close()
    
    
                     
             
    
    
    展开全文
  • python实现bp神经网络

    2017-03-11 14:17:48
    使用python实现bp神经网络经典代码列子
  • 主要介绍了Python实现的三层BP神经网络算法,结合完整实例形式分析了Python三层BP神经网络算法的具体实现与使用相关操作技巧,需要的朋友可以参考下
  • 深度学习-BP神经网络(python3代码实现)

    万次阅读 多人点赞 2018-03-11 22:19:21
    BP神经网络 哈尔滨工程大学-537 一、试验数据 在试验开始前必定要先导入所需要的python库,%matplotlib inline是为了使绘制的图形能够显示在浏览器上。 import numpy as np import matplotlib.pyplot as ...

    BP神经网络

    哈尔滨工程大学-537


    一、试验数据

    在试验开始前必定要先导入所需要的python库,%matplotlib inline是为了使绘制的图形能够显示在浏览器上。

    import numpy as np
    import matplotlib.pyplot as plt
    import random
    %matplotlib inline

    之后我们需要产生一些难以进行线性分类的数据集,这里直接copy斯坦福CS231n课程里的螺旋数据集,代码如下:

    N = 100 # number of points per class
    D = 2 # dimensionality
    K = 3 # number of classes
    X = np.zeros((N * K, D)) # data matrix (each row = single example)
    y = np.zeros(N * K, dtype='uint8') # class labels
    for j in range(K):
        ix = list(range(N*j, N*(j + 1)))
        r = np.linspace(0.0, 1, N) # radius
        t = np.linspace(j*4, (j+1)*4, N) + np.random.randn(N)*0.2 # theta
        X[ix] = np.c_[r*np.sin(t), r*np.cos(t)]
        y[ix] = j
    plt.scatter(X[:, 0], X[:, 1], c=y, s=40, cmap=plt.cm.gist_rainbow)
    plt.show()

    我认为没有必要纠结于这段代码里的具体内容,不然就偏离了主题,总之就是通过一些奇奇怪怪的函数来画出这么一个布满随机点的图形。


    所绘制的图形如下图所示:

    这里写图片描述

    图中共有300个点,每一个点代表数据集中的一个样本点,横坐标和纵坐标分别作为样本的两个特征,样本点一共分为三种类型,红色、紫色和绿色。如果用矩阵来表示的话就应该是这样的:

    样本点特征1特征2类标签
    1-0.753-0.745红色
    2-0.7540.501紫色
    30.7520.258绿色

    二、softmax线性分类器

    在开始神经网络之前,先训练一个softmax线性分类器。

    所谓softmax,举例来说,就是有三个数字,分别为3、4、7,如果取max,那么每次都会取到7,因为7永远是三个数里最大的,但是把它们softmax一下,就映射为三个概率0.27、0.28、0.45,这样取到7的概率最大,但是也有取到其他两个数的可能。这样,我们取的就不是max值,而是softmax值,没有取max值那么硬。

    而这三个数字是如何通过softmax映射为三个概率值的,即softmax函数是什么样的,接下来会提到。


    而既然是线性分类器,必然离不开经典的公式 y=wx+b y = w x + b 。所以,就先初始化一下 w w b吧,代码如下:

    # initialize parameters randomly
    W = 0.01 * np.random.randn(D,K)
    b = np.zeros((1,K))

    这里的random库下的randn()函数是生成服从标准正态分布的随机数,这不同于生成在某一区间内均匀分布的随机数。生成D行K列,即2行3列。而偏置是1行3列的零向量。
    权值 w w 和偏置b打印出来如下:

    这里写图片描述


    由于这是一个线性分类器,所以只需做简单的矩阵乘法,即可得到各个类别的分数。

    # compute class scores for a linear classifier
    scores = np.dot(X, W) + b

    这里将300行2列的矩阵与2行3列的矩阵相乘,再加上偏置,得到300行3列的矩阵。每行代表一个样本点,共300个样本点,每列代表样本点对应各个类别的分数,共三个类别。

    将score矩阵部分打印出来,如下图:

    这里写图片描述


    接下来的一个关键因素就是损失函数,我们需要用它来计算我们的损失,即预测结果和真实情况相差多少。在这里,我们希望正确的类别应该比其他类别有更高的分数,若确实如此,则损失应该很低,否则损失应该很高。量化这种直觉的方法有很多种,但在这个例子中我们可以使用与softmax分类器相关的交叉熵损失。公式如下:

    Li=log(prob(i)) L i = − l o g ( p r o b ( i ) )

    公式其实比较直观,比如对某一个样本 i 预测,正确类别的概率值 prob(i) p r o b ( i ) 越大,损失就越小,反之其值越小,损失就越大。由于概率值在0和1之间,所以保证了 log l o g 函数自变量的取值范围(斯坦福CS231n上面是如此写交叉熵的,可是和别的资料都不一样)。

    将每个样本的损失累加在一起再除以样本个数,得到训练样本的平均交叉熵损失: 1NiLi 1 N ∑ i L i

    而完整的softmax分类器的损失则定义为:

    L=1NiLi+12λklW2k,l L = 1 N ∑ i L i + 1 2 λ ∑ k ∑ l W k , l 2

    公式后半部分为正则化损失,比如某个点的特征为[1, 1],而此时有两组不同的权重向量 w1 w 1 =[1, 0], w2 w 2 =[0.5, 0.5],与两组不同的权重分别做内积的结果相等,都为1。可是加上正则化损失项后,很明显 0.50.5+0.50.5<11 0.5 ∗ 0.5 + 0.5 ∗ 0.5 < 1 ∗ 1 ,所以选择 w2 w 2 作为权重整体的损失更小。起作用在于增强泛化能力,去除权重的不确定性。


    由之前得到的分数矩阵score,可以计算得到每个样本对应各个类别的概率值。这里就用到了之前所说的softmax,把三个数,通过softmax函数映射为归一化的三个概率,softmax公式如下:

    softmax(score(i))=escore(i)jescore(j) s o f t m a x ( s c o r e ( i ) ) = e s c o r e ( i ) ∑ j e s c o r e ( j )

    例如:某个样本 i 对应各个类别的分值分别为(3, 3, 8),则该样本对应各个类别的概率值为 (e3e3+e3+e8,e3e3+e3+e8,e8e3+e3+e8) ( e 3 e 3 + e 3 + e 8 , e 3 e 3 + e 3 + e 8 , e 8 e 3 + e 3 + e 8 )

    实现代码如下:

    num_examples = X.shape[0]
    # get unnormalized probabilities
    exp_scores = np.exp(scores)
    # normalize them for each example
    probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)

    现在我们有了一个300行3列的概率矩阵,由于已经进行了归一化处理,所以每一行的三个概率值相加和为1。接下来将每个样本的正确类别的概率提取出来,并做 log − l o g 映射。例如:第一个样本对应各个类别的概率为[0.2, 0.3, 0.5],而第一个样本的类别标签为1,则取出第1列的概率值0.3进行 log − l o g 映射。

    代码如下:

    corect_logprobs = -np.log(probs[range(num_examples),y])

    得到了一个包含300个元素的一维数组,每个元素都是相应样本的正确类别的概率值。

    之后根据上文所述公式计算完整的损失,代码如下:

    # compute the loss: average cross-entropy loss and regularization
    data_loss = np.sum(corect_logprobs)/num_examples
    reg_loss = 0.5 * reg * np.sum(W * W)
    loss = data_loss + reg_loss

    当然了这里的 reg 即公式中的 λ λ 在实际运行代码的时候是需要赋值的。先随意将其赋值为1.5,打印loss,可以得到此时的loss值为:

    1.099367068027489

    即使改变reg值,loss值变化也不大,这是因为我们给权重的初始值非常小,还记得下图是我们随机生成的权重矩阵和偏置向量吧。

    这里写图片描述

    某样本的两个特征,无论是和权重矩阵的第一列内积,还是和第二列内积,还是和第三列,所得的结果都差不了多少。所以最后算得的该样本属于各个类别的概率值应该都是三分之一左右。

    这显然很不理想,我们希望能提升正确类别的概率值,即降低loss的值。


    那么如何降低损失值,必然又要用到梯度下降。要想找到 w w b取什么值的时候,最终的loss值能最小。就得对它们分别求导,用梯度下降找到导数为0的点,即为极小值点。

    先计算 L=1NiLi+12λklW2k,l L = 1 N ∑ i L i + 1 2 λ ∑ k ∑ l W k , l 2 加号之前部分的导数。

    首先让损失loss对分数score求导,得到 =. ∂ 损 失 ∂ 分 数 = ∂ 损 失 ∂ 概 率 . ∂ 概 率 ∂ 分 数 ,这一点由高数知识就可得到。

    这里损失loss由正确类别的概率值决定,而正确类别的概率值由各个类别分数共同决定,所以求得应分别是对三个分数的导数,为了不偏离主题,求导过程略掉,总之最后损失loss对各个分数的导数为

    Pk1(k=yi) P k − 1 ( k = y i )

    简单举例来说就是:某一个样本对应各个类别的概率为[0.2, 0.3, 0.5],而该样本的类别标签为1,即0.3是正确类别的概率,于是该样本的损失值loss对于分数score的导数为[0.2, -0.7, 0.5],即正确类别的概率值减1,其他类别的概率值不变,而从直觉上来想,也确实应该是这样的。

    显然中间那列的导数值是负数,所以增加中间那列的score值,减少两边的score值,可以使得该样本的loss值降低。

    以下代码实现导数表达式:

    dscores = probs
    dscores[range(num_examples),y] -= 1
    dscores /= num_examples

    最后除以样本个数,因为之前计算用到的是样本的平均损失,所以这里也要做平均处理(个人这么理解/(ㄒoㄒ)/~~)。


    现在得到了 ∂ 损 失 ∂ 分 数 ,我们想要得到的是 ∂ 损 失 ∂ 权 重 ,易知 .= ∂ 损 失 ∂ 分 数 . ∂ 分 数 ∂ 权 重 = ∂ 损 失 ∂ 权 重 ,故需要求得 ∂ 分 数 ∂ 权 重 ,对任意一个样本来说,[特征1, 特征2]与权重向量各列分别做内积得到三个分数score。因此三个分数各自对影响自己的权重求导,得到的就是[特征1,特征2],而考虑到所有样本的话,三个分数对权重求导结果就是样本矩阵X。故将样本矩阵X与之前所得的dscores矩阵相乘。

    而每个分数对偏置的求导自然是1了,考虑到300个样本,就是由300个1为元素的向量与dscores矩阵相乘。

    故代码如下:

    dW = np.dot(X.T, dscores)
    db = np.sum(dscores, axis=0, keepdims=True)
    dW += reg*W # don't forget the regularization gradient

    完整的损失对权重的求导还要加上正则项对权重的求导结果。这里的reg应设置为与之前相同的值。

    最后对权值和偏置进行更新

    # perform a parameter update
    W += -step_size * dW
    b += -step_size * db

    当然了,只更新一次肯定是不够了,所以将上面的代码都放在一个循环中,迭代200次。代码如下:

    #Train a Linear Classifier
    
    # initialize parameters randomly
    W = 0.01 * np.random.randn(D,K)
    b = np.zeros((1,K))
    
    # some hyperparameters
    step_size = 1e-0
    reg = 1e-3 # regularization strength
    
    # gradient descent loop
    num_examples = X.shape[0]
    for i in range(200):
    
        # evaluate class scores, [N x K]
        scores = np.dot(X, W) + b 
    
        # compute the class probabilities
        exp_scores = np.exp(scores)
        probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True) # [N x K]
    
        # compute the loss: average cross-entropy loss and regularization
        corect_logprobs = -np.log(probs[range(num_examples),y])
        data_loss = np.sum(corect_logprobs)/num_examples
        reg_loss = 0.5 * reg * np.sum(W * W)
        loss = data_loss + reg_loss
        if i % 10 == 0:
            print ("iteration %d: loss %f" % (i, loss))
    
        # compute the gradient on scores
        dscores = probs
        dscores[range(num_examples),y] -= 1
        dscores /= num_examples
    
        # backpropate the gradient to the parameters (W,b)
        dW = np.dot(X.T, dscores)
        db = np.sum(dscores, axis=0, keepdims=True)
    
        dW += reg*W # regularization gradient
    
        # perform a parameter update
        W += -step_size * dW
        b += -step_size * db

    迭代200次,将10的被数次的损失函数值打印出来,结果如下:

    这里写图片描述


    最后计算一下用更新后的权值和偏置预测出来的结果的精度,代码如下:

    # evaluate training set accuracy
    scores = np.dot(X, W) + b
    predicted_class = np.argmax(scores, axis=1)
    print('training accuracy: %.2f' % (np.mean(predicted_class == y))) 

    得到的精度结果为:0.50

    心累,这不就是随机瞎蒙吗,这就是用线性分类器给线性不可分的数据进行分类的后果……


    三、BP神经网络

    显然,对这个数据集来说,线性分类器是不够的,那么我们就需要使用神经网络来进行分类了。


    首先整理一下思路,先通过一张图来表达一下softmax线性分类器的工作原理。

    这里写图片描述

    由图可以看出,把每个样本的特征作为输入,每个样本的特征都加上权值和偏置进行运算之后得到输出,这个输出是三个分数,把这个三个分数再通过激活函数即softmax函数映射为三个概率,这样就得到了预测结果,把预测结果和真实情况作为输入,通过损失函数算出预测结果和真实情况相差多少。把300样本都这么算一下,看看平均损失是多少。然后想办法尽快降低这个损失。于是就得通过修改权值和偏置来使这个损失降低,

    那么神经网络和这个softmax线性分类器有什么不同呢,不同就是多了一层隐藏层。也就是每个样本的特征加上权值和偏置进行运算之后得到的输出,再加上一次权值和偏置进行运算,然后得到的结果,再通过激活函数进行运算。如下图所示:


    首先初始化参数,增加了一个有一百个神经元的隐藏层,所以需要初始化的权重和偏置的数量肯定是增多了。这里初始化了两套权重和偏置 W,b W , b ,分别为隐藏层的权重和偏置,以及输出层的权重和偏置 W2,b2 W 2 , b 2 ,代码如下:

    # initialize parameters randomly
    h = 100 # size of hidden layer
    W = 0.01 * np.random.randn(D,h)
    b = np.zeros((1,h))
    W2 = 0.01 * np.random.randn(h,K)
    b2 = np.zeros((1,K))

    初始化2行100列的权重和1行100列的偏置,用来与300个样本的特征做计算,得到300行100列的结果。再初始化100行3列的权重和1行3列的偏置,用来与之前所得的300行100列的结果再做运算,并得到300行3列的分数矩阵。


    接下来编写由特征矩阵得到分数矩阵的代码,首先定义每个隐藏层神经元的激活函数,在这里使用ReLu函数作为隐藏层神经元的激活函数,ReLu函数的图像如下图所示:

    这里写图片描述

    函数表达式为 ReLu(x)=max{0,x} R e L u ( x ) = m a x { 0 , x } ,即取0和自变量之间的最大值。

    # evaluate class scores with a 2-layer Neural Network
    hidden_layer = np.maximum(0, np.dot(X, W) + b) # note, ReLU activation
    scores = np.dot(hidden_layer, W2) + b2

    之后的操作和softmax线性分类器没什么区别,将分数矩阵通过softmax映射为概率矩阵,然后计算平均损失和正则损失,再将二者相加。

    num_examples = X.shape[0]
    # get unnormalized probabilities
    exp_scores = np.exp(scores)
    # normalize them for each example
    probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)
    corect_logprobs = -np.log(probs[range(num_examples),y])
    # compute the loss: average cross-entropy loss and regularization
    data_loss = np.sum(corect_logprobs)/num_examples
    reg_loss = 0.5 * 2 * np.sum(W * W)
    loss = data_loss + reg_loss

    然后还是和softmax线性分类器一样,要想计算 ∂ 分 数 ∂ 输 出 层 的 权 重 以及 ∂ 分 数 ∂ 输 出 层 的 偏 置 ,就需要先计算损失对分数的导数 ∂ 损 失 ∂ 分 数

    dscores = probs
    dscores[range(num_examples),y] -= 1
    dscores /= num_examples

    而接下来,与softmax线性分类器不同,softmax线性分类器的分数是由特征和权重进行运算得到的,而该神经网络的分数是由隐藏层的输出结果和输出层的权重、偏置进行运算得到的。所以这里 ∂ 分 数 ∂ 输 出 层 的 权 重 应该为隐藏层的输出矩阵。而 ∂ 分 数 ∂ 输 出 层 的 偏 置 仍然为全是1的向量。所以损失对输出层的权重、输出层的偏置求导代码如下:

    # backpropate the gradient to the parameters
    # first backprop into parameters W2 and b2
    dW2 = np.dot(hidden_layer.T, dscores)
    db2 = np.sum(dscores, axis=0, keepdims=True)

    =. ∂ 损 失 ∂ 隐 藏 层 的 权 重 = ∂ 损 失 ∂ 隐 藏 层 的 输 出 . ∂ 隐 藏 层 的 输 出 ∂ 隐 藏 层 的 权 重 ,于是就需要先求得 ∂ 损 失 ∂ 隐 藏 层 的 输 出 ,而 =. ∂ 损 失 ∂ 隐 藏 层 的 输 出 = ∂ 损 失 ∂ 分 数 . ∂ 分 数 ∂ 隐 藏 层 的 输 出

    而由于分数是由隐藏层的输出和输出层的权重加上偏置进行运算得到的,所以 ∂ 分 数 ∂ 隐 藏 层 的 输 出 应该为输出层的权重矩阵。故 ∂ 损 失 ∂ 隐 藏 层 的 输 出 代码如下:

    dhidden = np.dot(dscores, W2.T)

    =ReLu.ReLu ∂ 隐 藏 层 的 输 出 ∂ 隐 藏 层 的 权 重 = ∂ 隐 藏 层 的 输 出 ∂ R e L u 函 数 输 入 值 . ∂ R e L u 函 数 输 入 值 ∂ 隐 藏 层 权 重 ,而 ReLu ∂ 隐 藏 层 的 输 出 ∂ R e L u 函 数 输 入 值 很显然,隐藏层的输出大于0的,对函数输入值的导数是其本身,隐藏层的输出小于等于0的,对函数输入值的导数是0。故 RelU ∂ 隐 藏 层 的 输 出 ∂ R e l U 函 数 输 入 值 的代码应该如下:

    # backprop the ReLU non-linearity
    dhidden[hidden_layer <= 0] = 0
    

    所以 ∂ 隐 藏 层 的 输 出 ∂ 隐 藏 层 的 权 重 以及 ∂ 隐 藏 层 的 输 出 ∂ 隐 藏 层 的 偏 置 的代码如下:

    # finally into W,b
    dW = np.dot(X.T, dhidden)
    db = np.sum(dhidden, axis=0, keepdims=True)

    现在有了损失对各层权重、偏置的导数,即 dW,db,dW2,db2 d W , d b , d W 2 , d b 2 ,就可以通过循环迭代来更新各层的权重和偏置了。

    这次将涉及神经网络的所有代码都整理到一起,代码如下:

    # initialize parameters randomly
    h = 100 # size of hidden layer
    W = 0.01 * np.random.randn(D,h)
    b = np.zeros((1,h))
    W2 = 0.01 * np.random.randn(h,K)
    b2 = np.zeros((1,K))
    
    # some hyperparameters
    step_size = 1e-0
    reg = 1e-3 # regularization strength
    
    # gradient descent loop
    num_examples = X.shape[0]
    for i in range(10000):
    
      # evaluate class scores, [N x K]
        hidden_layer = np.maximum(0, np.dot(X, W) + b) # note, ReLU activation
        scores = np.dot(hidden_layer, W2) + b2
    
        # compute the class probabilities
        exp_scores = np.exp(scores)
        probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True) # [N x K]
    
        # compute the loss: average cross-entropy loss and regularization
        corect_logprobs = -np.log(probs[range(num_examples),y])
        data_loss = np.sum(corect_logprobs)/num_examples
        reg_loss = 0.5 * reg * np.sum(W * W) + 0.5 * reg * np.sum(W2 * W2)
        loss = data_loss + reg_loss
        if i % 1000 == 0:
            print("iteration %d: loss %f" % (i, loss))
    
        # compute the gradient on scores
        dscores = probs
        dscores[range(num_examples),y] -= 1
        dscores /= num_examples
    
        # backpropate the gradient to the parameters
        # first backprop into parameters W2 and b2
        dW2 = np.dot(hidden_layer.T, dscores)
        db2 = np.sum(dscores, axis=0, keepdims=True)
        # next backprop into hidden layer
        dhidden = np.dot(dscores, W2.T)
        # backprop the ReLU non-linearity
        dhidden[hidden_layer <= 0] = 0
        # finally into W,b
        dW = np.dot(X.T, dhidden)
        db = np.sum(dhidden, axis=0, keepdims=True)
    
        # add regularization gradient contribution
        dW2 += reg * W2
        dW += reg * W
    
        # perform a parameter update
        W += -step_size * dW
        b += -step_size * db
        W2 += -step_size * dW2
        b2 += -step_size * db2

    运行代码结果如下:

    这里写图片描述

    迭代了10000次,最后的损失降低为0.241312。
    再来打印一下精度:

    # evaluate training set accuracy
    hidden_layer = np.maximum(0, np.dot(X, W) + b)
    scores = np.dot(hidden_layer, W2) + b2
    predicted_class = np.argmax(scores, axis=1)
    print('training accuracy: %.2f' % (np.mean(predicted_class == y)))

    可以得到最后的精度为:0.98


    可以说最终得到了比较理想的精确度,事实证明BP神经网络在某些情况下比单纯的线性分类器的效果要好的多。上文通过了一张图直观的了解到softmax线性分类器的工作原理。那就再通过下面这张图,直观、形象的了解一下全连接的前馈反向传播传播神经网络的工作原理吧。

    这里写图片描述

    多了一层隐藏层,其他的没啥不同,这么看感觉BP神经网络还算比较好理解的哈。

    展开全文
  • python3_实现BP神经网络 + BP神经网络应用实例

    万次阅读 多人点赞 2018-07-29 22:10:28
    1.BP神经网络简介 BP神经网络是1986年由Rumelhart和McClelland为首的科学家提出的概念,是一种按照逆向传播算法训练的多层前馈神经网络,是目前应用最广泛的神经网络。 优点:具有任意复杂的模式分类能力和优良的...

    0.目录

    1.BP神经网络简介

    2.前期理论准备

    2.算法数学原理

    (一)符号说明

    (二)公式推导

    3.python实现(python3编程实现)

    (一)sigmoid函数

    (二)BP主函数实现

    4.数据格式

    1.BP神经网络简介

    BP神经网络是1986年由Rumelhart和McClelland为首的科学家提出的概念,是一种按照逆向传播算法训练的多层前馈神经网络,是目前应用最广泛的神经网络。

    目录

    0.目录

    1.BP神经网络简介

    2.前期理论准备

    2.算法数学原理

    (一)符号说明

    (二)公式推导

    3.python实现(python3编程实现)

    (一)sigmoid函数

    (二)BP主函数实现

    4.数据格式


    优点

    • 1.具有任意复杂的模式分类能力和优良的多维函数映射能力,解决了简单感知器不能解决的异或问题的问题(参考博客:https://www.jianshu.com/p/a25788130897 或 https://www.cnblogs.com/xym4869/p/11282469.html
    • 2.从结构上讲,BP神经网络具有输入层、隐含层和输出层
    • 3.从本质上讲,BP算法就是以网络误差平方目标函数、采用梯度下降法来计算目标函数的最小值。基本BP算法包括信号的前向传播误差的反向传播两个过程。

    缺点

    • 1.学习速度慢,即使是一个简单的过程,也需要几百次甚至上千次的学习才能收敛。
    • 2.容易陷入局部极小值
    • 3.网络层数、神经元个数的选择没有相应的理论指导
    • 4.网络推广能力有限。

    应用

    • 1.函数逼近
    • 2.模式识别
    • 3.分类
    • 4.数据压缩

    2.前期理论准备

    网络训练的目标:找到合适的权值和阈值,使得误差E最小。

    sigmoid函数:在信息科学当中,由于其单增以及其反函数单增等性质,sigmoid函数常被用作神经网络的阈值函数,将变量映射当0和1之间。(该函数的对x的求导也应该理解)

    2.算法数学原理

    (一)符号说明

    Xi: 输入信号。

    Xd: 隐层的阈值(是从求和函数中-θ中分离出的-1)。

    Vih: 第h个隐层神经元所对应输入信号Xi的权值。

    αh: 第h个隐层神经元的输入。

    -γh=--1*γh:隐层神经元的阈值。

    bh: 第h个隐层神经元的输入。

    ωhj: 第j个输出层神经元所对应的隐层神经元输出bh的权值。

    -θj=-1*θj:  输出层神经元的阈值(bq)

    :第j个输出层神经元的输出(预测输出值,yj为真实值)

    (二)公式推导

    通过公式变换可得输出层权值与阈值的变化量:

    同理可得隐层权值和阈值的变化量:

    3.python实现(python3编程实现)

    (一)sigmoid函数

    def sigmoid(x):
        """
        隐含层和输出层对应的函数法则
        """
        return 1/(1+np.exp(-x))
    

    (二)BP主函数实现

    def BP(data_tr, data_te, maxiter=600):
    
        # --pandas是基于numpy设计的,效率略低
        # 为提高处理效率,转换为数组
        data_tr, data_te = np.array(data_tr), np.array(data_te)
    
        # --隐层输入
        # -1: 代表的是隐层的阈值
        net_in = np.array([0.0, 0, -1])
        w_mid = np.random.rand(3, 4)          # 隐层权值阈值(-1x其中一个值:阈值)
    
        # 输出层输入
        # -1:代表输出层阈值
        out_in = np.array([0.0, 0, 0, 0, -1])
        w_out = np.random.rand(5)             # 输出层权值阈值(-1x其中一个值:阈值)
        delta_w_out = np.zeros([5])           # 存放输出层权值阈值的逆向计算误差
        delta_w_mid = np.zeros([3, 4])        # 存放因此能权值阈值的逆向计算误差
        yita = 1.75                           # η: 学习速率
        Err = np.zeros([maxiter])             # 记录总体样本每迭代一次的错误率
    
        # 1.样本总体训练的次数
        for it in range(maxiter):
    
            # 衡量每一个样本的误差
            err = np.zeros([len(data_tr)])
    
            # 2.训练集训练一遍
            for j in range(len(data_tr)):
                net_in[:2] = data_tr[j, :2]                       # 存储当前对象前两个属性值
                real = data_tr[j, 2]
    
                # 3.当前对象进行训练
                for i in range(4):
                    out_in[i] = sigmoid(sum(net_in*w_mid[:, i]))  # 计算输出层输入
                res = sigmoid(sum(out_in * w_out))                # 获得训练结果
    
                err[j] = abs(real - res)
    
                # --先调节输出层的权值与阈值
                delta_w_out = yita*res*(1-res)*(real-res)*out_in  # 权值调整
                delta_w_out[4] = -yita*res*(1-res)*(real-res)     # 阈值调整
                w_out = w_out + delta_w_out
    
                # --隐层权值和阈值的调节
                for i in range(4):
                    # 权值调整
                    delta_w_mid[:, i] = yita * out_in[i] * (1 - out_in[i]) * w_out[i] * res * (1 - res) * (real - res) * net_in
                    # 阈值调整
                    delta_w_mid[2, i] = -yita * out_in[i] * (1 - out_in[i]) * w_out[i] * res * (1 - res) * (real - res)
                w_mid = w_mid + delta_w_mid
            Err[it] = err.mean()
        plt.plot(Err)
        plt.show()
    
        # 存储预测误差
        err_te = np.zeros([100])
    
        # 预测样本100个
        for j in range(100):
            net_in[:2] = data_te[j, :2]                         # 存储数据
            real = data_te[j, 2]                                # 真实结果
    
            # net_in和w_mid的相乘过程
            for i in range(4):
                # 输入层到隐层的传输过程
                out_in[i] = sigmoid(sum(net_in*w_mid[:, i]))
            res = sigmoid(sum(out_in*w_out))                    # 网络预测结果输出
            err_te[j] = abs(real-res)                           # 预测误差
            print('res:', res, ' real:', real)
        
        plt.plot(err_te)
        plt.show()
    
    
    
    
    if "__main__" == __name__:
    
        # 1.读取样本
        data_tr = pd.read_csv("5.2 data_tr.txt")
        data_te = pd.read_csv("5.2 data_te.txt")
        BP(data_tr, data_te, maxiter=600)

    4.数据格式

    训练集、测试集下载链接见置顶评论:

    https://download.csdn.net/download/admin_maxin/19844122

    展开全文
  • 十分简单的单隐层BP神经网络python实现,运用了冲量项加快收敛,除此之外没有任何框架和复杂的函数,帮助初学者快速理解反向误差传播的含义
  • 压缩包中包含代码和所需数据,此代码实现了TE数据故障1测试集的正确分类,正确率99.9%。开发环境为jupyter lab。
  • BP神经网络原理推导及python实现摘要(一)BP神经网络简介1、神经网络权值调整的一般形式为:2、BP神经网络中关于学习信号的求取方法:(二)BP神经网络原理推导1、变量说明2、BP算法推导(三)BP神经网络python实现...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,071
精华内容 3,628
关键字:

bp神经网络分类python

python 订阅