Pytorch基础:神经网络

神经网络

神经网络是由具有适应性的简单单元组成的广泛并行互联的网络,他的组织能够模拟生物神经系统对真实世界物体做出的交互反应

在深度学习中也借鉴了这样的结构,每一个神经元接受输入x,通过带权重w的连接进行传递,将总输入的信号与神经元的阈值进行比较,最后通过激活函数处理确定是否激活,并将激活后的计算结果y输出;训练即训练权重w

神经网络表示

将神经元拼接,两层神经元,即输入层+输出层(M-P)构成感知机。而多层功能神经元相连构成神经网络,输入层与输出层之间的所有层神经元,称为感知层;

激活函数

神经网络中的激活函数就是用来判断我们所计算的信息是否达到了往后面传输的条件
在神经网络计算过程中,每层都相当于矩阵相乘,无论神经网络有多少层输入都是输入的线性组合,每一层矩阵相乘获得的信息差距不大,所以需要激活函数来引入非线性因素,是的神经网络可以任意逼近任何非线性函数,这样神经网络就可以应用到众多的非线性模型中,增加和神经网络模型的泛化特性

import torch
import torch.nn.functional as F
import matplotlib.pyplot as plt
import numpy as np
x = torch.linspace(-10, 10, 50)
sigmoid函数

a = 1 1 + e − z a = \cfrac{1}{1+e^-z} a=1+ez1 导数: a ′ = a ( 1 − a ) a'=a(1-a) a=a(1a)

在sigmoid函数中,其输入是在(0,1)区间,它能把输入的连续实值变换为0到1之间的输出,如果是非常大的负数,那么输出就是0;如果是非常大的正数输出就是1,起到了抑制的作用

ax = plt.gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data', 0))
plt.ylim((0, 1))
sigmoid = torch.sigmoid(x)
plt.plot(x.numpy(), sigmoid.numpy())
[<matplotlib.lines.Line2D at 0x1dda740f408>]

在这里插入图片描述

sigmoid由于需要指数训练,再加上函数输出不是以0为中心的(权重更新效率低),当输入远离坐标原点,函数的梯度就变得很小(几乎为0)。在神经网络反向传播的过程中不利于权重优化,这个问题叫梯度饱和,也叫梯度弥散。所以sigmoid基本上只在做二元分类(0,1)时的输出层才会使用

tanh函数

a = e z − e − z e z + e − z a=\cfrac{e^z - e^{-z}}{e^z+e^{-z}} a=ez+ezezez 导数: a ′ = 1 − a 2 a'=1-a^2 a=1a2

tanh是双曲线正切函数,输输出区间在(-1, 1)之间,函数以0为中心

ax = plt.gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data', 0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data', 0))
plt.ylim((-1, 1))
tanh = torch.tanh(x)
plt.plot(x.numpy(), tanh.numpy())
[<matplotlib.lines.Line2D at 0x1dda38bf2c8>]

在这里插入图片描述

与sigmoid函数类似,当输入稍微远离了坐标原点,梯度还是很小,但是tanh是以0为中心点,使用tanh作为激活函数,可以起到归一化(均值为0)效果

ReLU函数

ReLu(Rectified Linear Units)修正线性单元
a = m a x ( 0 , z ) a = max(0, z) a=max(0,z)导数大于0时1,小于0时0;即z>0时,梯度始终为1,从而提高了神经网络基于梯度算法的运算速度。当z<0时,梯度一直为0。ReLU函数只有线性关系(只需判断输入是否大于0)不管前向传播还是反向传播,都比sigmoid和tanh速度快

ax = plt.gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data', 0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data', 0))
plt.ylim(-4, 10)
relu = F.relu(x)
plt.plot(x.numpy(), relu.numpy())
[<matplotlib.lines.Line2D at 0x1ddaa52a948>]

在这里插入图片描述

当输入为负数的时候,ReLU函数完全不被激活的。这表明如果输入为负数,ReLU会死掉,但是到了反向传播的时候,输入负数,梯度会完全到0

Leaky ReLU函数

为了解决ReLu函数z<0的问题,出现了Leaky ReLU函数,保证在z<0的时候,梯度仍不为0,ReLu的前半段设为az而不是0,通常a=0.01 a = m a x ( a z , z ) a=max(az,z) a=max(az,z)

ax = plt.gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data', 0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data', 0))
plt.ylim(-4, 10)
lrelu = F.leaky_relu(x, 0.09)
plt.plot(x.numpy(), lrelu.numpy())
[<matplotlib.lines.Line2D at 0x1ddaaceb4c8>]

在这里插入图片描述

理论上讲,Leaky ReLu有ReLU的所有优点,但是没有完全证明Leaky ReLU总体好于ReLU
ReLU目前仍时常用的activation function,在隐藏层中优先尝试

前向传播和反向传播

前向传播

对于一个神经网络来说,把输入特征 a [ 0 ] a^{[0]} a[0]这个输入值就是输入的x,放入第一层并计算第一层的激活函数,用 a [ 1 ] a^{[1]} a[1]表示,本层中的训练结果用 W [ 1 ] W^{[1]} W[1] b [ 1 ] b^{[1]} b[1]表示,这两个及计算结果 Z [ 1 ] Z^{[1]} Z[1]值都需要进行缓存,往后依此类推,直到最后计算出 z [ L ] z^{[L]} z[L]值。这个第L层的输出值即为网络的预测值。正向传播其实就是输入x经过一系列计网络计算得到y的过程

反向传播

对于反向传播:就是对正向传播的一些列的反向迭代,通过反向计算梯度,来优化需要训练的W和b。 δ a [ l ] \delta a^{[l]} δa[l]值进行求导得到 δ a [ l − 1 ] \delta a^{[l-1]} δa[l1],以此类推直到得到 δ a [ 2 ] \delta a^{[2]} δa[2] δ a [ 1 ] \delta a^{[1]} δa[1]。反向春波步骤中也会输出 δ W [ l ] \delta W^{[l]} δW[l] δ b [ l ] \delta b{[l]} δb[l]。这一步已得到权重的变化量

W = W − α δ W W = W - \alpha \delta W W=WαδW

b = b − α δ b b = b - \alpha \delta b b=bαδb

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值