BP神经网络

一、BP神经网络介绍

BP神经网络是一种按照误差逆向传播算法训练的多层前馈神经网络,是应用最广泛的神经网络模型之一,也是目前深度学习的理论基础。目前深度学习网络的参数优化是基于BP和梯度回归的。我们以一个简单的神经网络为例,简单地介绍一下BP神经网络的结构。

假设数据  $X={x_1,x_2,..x_n}$  , $Y={y_1,y_2,y_3,..y_n}$   。其中  $x_i$  为维度为𝑛的向量,$y_i={0,1}$    。如果我们使用一个简单的BP神经网络进行预测。那么我们的预测公式为:

y_i'=f(W_2g(W_1 x_i+b_1)+b_2)

以上是一个简单的BP神经网络公式,  $W_1$  和  $W_2$  是参数。其中  $W_1$  的维度是 $m\times n$,  $W_2$  的维度是1×𝑚的向量,𝑦′为预测值,𝑓,𝑔为激活函数(这里我们使用sigmoid函数)。为了让神经网络能够准确地进行预测,我们需要对参数  $W_1,W_2$  进行优化。

二、BP神经网络的公式推导

BP神经网络分为前向网络和后向网络,前向网络是计算目标值,后向网络用于梯度计算。

前向计算:

输入: $a_0=x$

第一层:$a_1=\sigma(W_1 a_0+b_1)$

第二层:$a_2=\sigma(w_2 a_1+b_2)$

输出: $y'=a_2$

反向传播:

令损失函数为:

L=y ln(y')+(1-y )ln(1-y')

第二层梯度计算:

e=y ln(y')+(1-y )ln(1-y')

z_2=W_2 a_1 +b_2

\frac{\partial L}{\partial b_2}=\frac{\partial L}{\partial a_2}\frac{\partial a_2}{\partial z_2}\frac{\partial z_2}{\partial b_2}=(-\frac{y}{y'}+\frac{1-y}{1-y'})(y'(1-y'))=(y'-y)

\frac{\partial L}{\partial w_2}=\frac{\partial L}{\partial a_2}\frac{\partial a_2}{\partial z_2}\frac{\partial a_2}{\partial w_2}=(-\frac{y}{y'}+\frac{1-y}{1-y'})(y'(1-y'))a_1 =(y'-y)a_1

\delta _2=\frac{\partial L}{\partial z_2}=(y'-y)

第一层梯度计算:

\frac{\partial L}{\partial z_1}=\frac{\partial L}{\partial y'}\frac{\partial y'}{\partial a_2}\frac{\partial a_2}{\partial a_1}\frac{\partial a_1}{\partial z_1}=\frac{\partial L}{\partial b_2}w_2 \cdot \frac{\partial a_1}{\partial z_1}=\delta _2 w_2 \cdot \sigma '(z_1)

其中  $z_1=W_1 a_0+b1$  ,令$\delta _1 =\frac{\partial L}{\partial z_1}$

因为  $\frac{\partial a_2}{\partial b_2}=1$  , $\frac{\partial a_2}{\partial a_1}=w_2$   ,因此上式也很好推导得到。

由此:

$\frac{\partial L}{\partial b_1}= \delta _1$

$\frac{\partial L}{\partial W_1}= \delta _1 a_0$

至此,BP神经网络的推导全部完成。为了更加直观地感受,我们接下来对一步进行分解。

1、首先是前向步骤

import numpy as np
def sigmoid(x):
    return 1/(1+np.exp(-x))
x=np.array([[1,2],[2,3]])

lr=0.01

1:第一层网络

w_1=np.array([[0.3,0.4],[0.5,0.5]])
b_1=0.5
def forward1(x):
    a_0=x
    a_1=sigmoid(np.dot(w_1,x)+b_1)
    return a_1


a_1=forward1(x)
a_1

'''
array([[0.83201839, 0.90887704],
       [0.88079708, 0.95257413]])
'''

2:第二层网络

w_2=np.array([2,3])
b_2=0.5
def forward2(x):
    a1=x
    a_2=sigmoid(np.dot(w_2,x)+b_2)
    return a_2

t=forward2(a_1)
print(t)

'''
[0.99188931 0.99437826]
'''

3:计算loss

def cal_cross_loss(y, t):
    loss=np.sum(-y * np.log(t)- (1 - y) * np.log(1 - t))/t.shape[0]
    return loss

y=np.array([0,1])
loss=cal_cross_loss(y,t)
loss

'''
2.4101046854144412
'''

2、然后就是反向传播

1:输出层梯度计算

def cal_grad(y, t):
    grad = t - y
    return grad
delta_2=cal_grad(y,t)
delta_2

'''
array([ 0.99188931, -0.00562174])
'''

2:第二层梯度计算

z_1=np.dot(w_1,x)+b_1
def backward2():
    global w_2,b_2
    
    grad_w=delta_2*a_1
    grad_b=np.sum(delta_2)
    
    w_2=w_2-lr*grad_w
    b_2=b_2-lr*grad_b
    print(w_2,b_2)
    return np.dot(delta_2,w_2)*(1-z_1)*z_1
delta_1=backward2()
delta_1

'''
[[1.9917473  3.00005109]
 [1.99126347 3.00005355]] 0.49013732434551505
array([[ -1.88582254,  -8.8469707 ],
       [ -3.92879696, -17.75311845]])
'''

3:第一层梯度计算

def backward1():
    global w_1,b_1
    
    grad_w=delta_1*a_1
    grad_b=np.sum(delta_1)
    w_1=w_1-lr*grad_w
    b_1=b_1-lr*grad_b
    
    return 
backward1()
print(w_1,b_1)

'''
[[0.31569039 0.48040809]
 [0.53460473 0.66911161]] 0.8241470864784078
'''

三、BP神经网络完整代码

1:输出层

def cal_cross_loss(y, t):
    loss = np.sum(-y * np.log(t) - (1 - y) * np.log(1 - t)) / t.shape[0]
    return loss


def cal_grad(y, t):
    grad = -y / t + (1 - y) / (1 - t)
    return grad


class Loss:
    def forward(self, y, t):
        self.loss = cal_cross_loss(y, t)
        self.delta = cal_grad(y, t)
        return self.loss

    def backward(self):
        return self.delta

2:网络层

class FC:
    def init(self, in_num, out_num, lr=0.01):
        self._in_num = in_num
        self._out_num = out_num
        self.w = np.random.rand(in_num, out_num)  # 生成out行,in列矩阵

        self.b = np.zeros(out_num)
        self.lr = lr

    def _sigmoid(self, in_data):
        return 1 / (1 + np.exp(-in_data))

    def forward(self, in_data):
        self.z = np.dot(in_data, self.w, ) + self.b
        self.top_val = self._sigmoid(self.z)
        self.bottom_val = in_data
        return self.top_val

    def backward(self, loss):
        residual_z = loss * self.top_val * (1 - self.top_val)

        grad_w = np.dot(self.bottom_val.T, residual_z)
        grad_b = np.sum(residual_z)

        self.w -= self.lr * grad_w
        self.b -= self.lr * grad_b
        residual_x = np.dot(residual_z,self.w.T)
        return residual_x

3:模型训练

class Net:
    def __init__(self, input_num=2, hidden_num=4, out_num=1, lr=0.05):
        self.fc1 = FC()
        self.fc1.init(input_num, hidden_num, lr)
        self.fc2 = FC()
        self.fc2.init(hidden_num, out_num, lr)
        self.loss = Loss()

    def trian(self, x, y):
        for i in range(1000):
            layer1out = self.fc1.forward(x)

            layer2out = self.fc2.forward(layer1out)

            loss = self.loss.forward(y, layer2out)

            delta2 = self.loss.backward()

            delta1 = self.fc2.backward(delta2)

            saliency = self.fc1.backward(delta1)
        layer1out = self.fc1.forward(X)
        layer2out = self.fc2.forward(layer1out)
        print(X)
        print(y)
        print(layer2out)




import numpy as np
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y=np.array([[0],[0],[0],[1]])
net=Net()
net.__init__(2,4,1,0.1)
net.trian(X,y)

'''
[[0 0]
 [0 1]
 [1 0]
 [1 1]]
[[0]
 [0]
 [0]
 [1]]
[[0.00227556]
 [0.01547024]
 [0.01542629]
 [0.98041847]]
'''
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值