前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >神经网络-BP神经网络

神经网络-BP神经网络

作者头像
三猫
发布2021-03-04 16:47:27
1.5K0
发布2021-03-04 16:47:27
举报
感知器作为初代神经网络,具有简单、计算量小等优点,但只能解决线性问题。BP神经网络在感知器的基础上,增加了隐藏层,通过任意复杂的模式分类能力和优良的多维函数映射能力,解决了异或等感知器不能解决的问题,并且BP神经网络也是CNN等复杂神经网络等思想根源。

1

基本概念

BP神经网络是一种通过误差反向传播算法进行误差校正的多层前馈神经网络,其最核心的特点就是:信号是前向传播,而误差是反向传播。前向传播过程中,输入信号经由输入层、隐藏层逐层处理,到输出层时,如果结果未到达期望要求,则进入反向传播过程,将误差信号原路返回,修改各层权重。

2

BP神经网络结构

BP神经网络包含输入层、隐藏层和输出层,其中,隐藏层可有多个,其中,输入层和输出层的节点个数是固定的(分别是输入样本的变量个数和输出标签个数),但隐藏层的节点个数不固定。以具有单隐藏层的BP神经网络为例,其网络结构如下图:

3

BP神经网络原理公式

以单隐藏层的BP神经网络为例,各阶段原理公式如下:

  • 前向传播。设输入层有n个节点,隐藏层有q个节点,输出层有m个节点,输入层与隐藏层间的权重为V,隐藏层与输出层的节点为W,输入变量为X,则隐藏层和输出层的输出分别为:
  • 误差函数。设有p个输入样本,则每个输入样本的误差函数为:
  • 根据误差调整权重。函数是沿梯度的方向变化最快,BP神经网络中也是通过梯度下降法更新权重。根据链式法则及上述关系,可以得到权重W和V的变化公式分别为:

4

python代码实现

这里,我们用手写数字图片建立一个仅有1层隐藏层的BP神经网络,并进行训练及预测。每张图片大小为8*8,因此有64个图片像素变量及1个偏置项,共65个输入层节点;训练目标是将手写图片判断为0-9,因此有10个输出层节点;隐藏层节点数这里设置为100。图片示例如下:

另外,这里两个激活函数我们都选用sigmoid函数,且这个函数都导数有一个特点,即f′(x)=f(x)(1−f(x))。

  • step 1:导入相应模块及定义sigmoid、dsigmoid函数
import numpy as np
from sklearn.datasets import load_digits
from sklearn.preprocessing import LabelBinarizer 
from sklearn.model_selection import train_test_split 

def sigmoid(x):
    return 1/(1+np.exp(-x))
def dsigmoid(x):
    return x*(1-x)
  • step 2:建立BP神经网络模型 初始过程中,给定两个权重V和W的初始值。训练过程中,首先给数据增加偏置项,然后每次训练时,随机选择一个样本,计算隐藏层和输出层的输出,并对W,V进行更新,同时每训练10000次计算一下预测准确率。
class NeuralNetwork:
    def __init__(self,layers):
        #权值等初始化,范围-1到1
        self.V = np.random.random((layers[0]+1,layers[1]+1))*2-1
        self.W = np.random.random((layers[1]+1,layers[2]))*2-1
        
    def train(self,X,y,lr=0.11,epochs=10000): # lr为学习率,X为训练集
        #添加偏置
        temp = np.ones([X.shape[0],X.shape[1]+1])#1为偏置
        temp[:,0:-1] = X
        X = temp
        
        for n in range(epochs+1):
            i = np.random.randint(X.shape[0]) #随机选取训练集中的一个数据
            x = [X[i]]
            x = np.atleast_2d(x)#转为二维数据
            
            L1 = sigmoid(np.dot(x,self.V)) #隐藏层输出
            L2 = sigmoid(np.dot(L1,self.W)) #输出层输出
            
            L2_delta = (y[i]-L2)*dsigmoid(L2)
            L1_delta = L2_delta.dot(self.W.T)
            
            self.W += lr*L1.T.dot(L2_delta)
            self.V += lr*x.T.dot(L1_delta)
            
            #每训练1000次预测一次准确率
            if n%1000==0:
                predictions = []
                for j in range(X_test.shape[0]):
                    o = self.predict(X_test[j])
                    predictions.append(np.argmax(o))#获取预测结果
                accuracy = np.mean(np.equal(predictions,y_test))
                print('epoch:',n,'accuracy:',accuracy)
                
    def predict(self,x):
        #添加偏置
        temp = np.ones(x.shape[0]+1)
        temp[0:-1] = x
        x = temp
        x = np.atleast_2d(x)#转为二维数据

        L1 = sigmoid(np.dot(x,self.V)) #隐藏层输出
        L2 = sigmoid(np.dot(L1,self.W)) #输出层输出
        return L2
  • step 3:结果计算 导入数据时,对输入数据进行归一化处理,不然sigmoid求导结果接近于0,权值的改变也将接近0,无法学习。
digits = load_digits()#载入数据
X = digits.data#数据
y = digits.target#标签
X -= X.min()
X /= X.max()

nm = NeuralNetwork([64,100,10])#创建网络
X_train,X_test,y_train,y_test = train_test_split(X,y) #默认3:1划分
labels_train = LabelBinarizer().fit_transform(y_train)#标签二值化
labels_test = LabelBinarizer().fit_transform(y_test)#标签二值化

print('start')
nm.train(X_train,labels_train,epochs=20000)
print('end')

输出结果如下,可以看到随着训练次数提升,模型准确率稳定在0.95、0.96。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-02-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 机器学习养成记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档