前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深度学习笔记2-神经网络的基本内容

深度学习笔记2-神经网络的基本内容

作者头像
caoqi95
发布2019-03-27 17:26:33
5970
发布2019-03-27 17:26:33
举报

「学习内容总结自 coursera udacity 的深度学习课程,部分截图来自 udacity 的课件」

一.最简单的神经网络及其输出

如上图所示是最简单的神经网络模型,包含输入x,神经元(又称为感知器)和输出y。 对这个神经网络再具体一点就是下图所示,对输入的x给与权重(在其他较复杂的神经网络中,往往有很多个输入,一个较大的权重意味着神经网络认为这个输入比其它输入更重要,较小的权重意味着该数据不是那么重要)和偏置,并把中间的神经元细分为左右两部分,左半边为神经元的输入,右半边为神经元的输出。

神经元的输入为:z=wx+b,其中w表示为权重,b表示偏置;神经元的输出为a=g(z)=g(wx+b),其中g(z)表示激活函数。最终该神经网络的输出y=g(z)=g(wx+b)

二.多元(层)神经网络及其输出

拿上面这张图举个例子,x1,x2是输入层(layer0);中间的两层(layer1,layer2)称为隐藏层,隐藏层里的单元称为隐藏单元;y(layer3)是输出层。所以这个多元神经网络也称为3层神经网络。 接下来也像上面一样增加权重w和偏置b,并对神经元进行细分。

PS:[ ]内的数字表示层数,下标数字表示该层网络中的单元数

  • 对于layer1:

即有(Z,W,b都是矩阵):

  • 对于layer2:
  • 对于layer3:
  • 对于该3层网络的输出y:
  • 推广至L层网络:

三.神经网络的激活函数

参考:浅谈深度学习中的激活函数

1. 什么是激活函数

上面出现的g(z)就是激活函数(activation function),激活函数不是为了“激活”什么,只是在神经网络中添加一些非线性的学习和处理能力,解决线性模型所不能解决的复杂问题。

2. 为什么使用非线性的激活函数

在深层的神经网络中,如果隐藏层仍然使用线性的激活函数,经过网络层层传递,其计算结果仍然是线性的,这与没有添加隐藏层是一样的效果,这样做的话,“深度”反而是没有意义的,并不能帮助我们解决复杂性的问题。所以在构建深度神经网络的时候,要引入非线性的因素,赋予神经元自我学习和适应的能力,从而提高模型的学习能力,能够处理复杂的非线性的数据集问题。

3. 常见的激活函数

常见激活函数有对数几率(又称作 sigmoid),tanh函数 ,ReLU函数和ReLU的变形-leakyReLU函数。

  • sigmoid函数
代码语言:javascript
复制
import numpy as np
def sigmoid(x):
    return 1/(1+np.exp(-x))

sigmoid.png

  • tanh函数
代码语言:javascript
复制
import numpy as np
def tanh(x):
    return (np.exp(x)-np.exp(-x))/(np.exp(x)+np.exp(-x))

tanh.png

  • ReLU函数
代码语言:javascript
复制
import numpy as np
def relu(x):
    return np.maximum(0,x)

ReLU.png

  • ReLU的变形-leaky ReLU函数
代码语言:javascript
复制
import numpy as np
def leaky_relu(x):
    return np.maximum(0.01*x,x)

leaky_ReLU.png

四.用代码实现一个简单的神经网络

运用上面的知识,实现一个简单的神经网络,它有两个输入节点,一个输出节点,使用sigmoid函数。代码实现过程:

代码语言:javascript
复制
import numpy as np

def sigmoid(x):
    # 实施sigmoid函数
    return 1/(1+np.exp(-x))

inputs = np.array([0.7, -0.3]) #输入
weights = np.array([0.1, 0.8]) #权重
bias = -0.1 #偏置

# 计算神经网络的输出
output = sigmoid(np.dot(inputs,weights)+bias)

五.神经网络的梯度下降

PS: 此处为了简便,忽略了偏置 b

  • 误差函数 给神经网络输入x,我们需要其输出的预测值ŷ近似的等于期望值y。为了能够衡量,我们需要有一个指标来了解预测的好坏,也就是误差(error)。常用的指标有误差平方:
  • 梯度下降法 要使网络预测的误差尽可能小,我们所要做的就是尽可能的使这个指标要小,即要找出它的最小值。权重 w 是让我们能够实现这个目标的调节旋钮。我们的目的是寻找权重 w​ 使得误差平方 E 最小。通常来说神经网络通过梯度下降法来实现这一点。 所谓梯度下降法就是,沿着能够使误差最小化的方向一步步更新权重 w 来减小误差(error)。要找到误差最小化的方向,我们需要计算误差平方对于权重 w 的梯度(对单个输入变量来说是导数,梯度是多个输入变量的导数的泛化)。
  • 梯度下降的数学实现过程

我们用这个公式来更新权重 w :

其中w表示权重更新步长,式子如下:

η 表示learning rate,有些地方也用α表示。 接下来运用链式法则求误差平方 E 对权重 w 的偏导数:

又因为

所以偏差公式化解为:

在这里定义一下误差项(error term) δ :

综上,权重 w 更新的公式为:

以上过程自己推导一边,写代码就会神清气爽:)

  • 梯度下降的代码实现过程 假设只有一个输出单元,用 sigmoid 来作为激活函数 f(h),代码实现的过程如下:
代码语言:javascript
复制
import numpy as np

def sigmoid(x):
    """
    计算sigmoid
    """
    return 1/(1+np.exp(-x))

def sigmoid_prime(x):
    """
    # sigmoid函数的导数,后面调用作为输出的梯度
    """
    return sigmoid(x) * (1 - sigmoid(x))

learnrate = 0.5
x = np.array([1, 2, 3, 4])
y = np.array(0.5)

# 初始化权重
w = np.array([0.5, -0.5, 0.3, 0.1])

# 计算节点的输入
h = np.dot(w,x)

# 计算神经网络的输出
nn_output = sigmoid(h)

# 计算神经网络的误差
error = y-nn_output 

# 计算误差项 sigmoid_prime(h)为输出的梯度
error_term = error*sigmoid_prime(h)

# w
del_w = learnrate*error_term*x

# 权重更新
w = w + del_w

六.神经网络的反向传播

  • 反向传播 前面我们已经学习了一个简单神经网络的输出层的误差项 δ ,并用它来更新权重 w 。但对于多层神经网络(以一个两层网络为例),前面的做法更新的只是隐藏层-输出层的权重,对于输入层-隐藏层的权重,我们该如何使用误差项 δ 来更新?这个误差项又该如何计算得出?

利用链式法则我们可以计算输入层-隐藏层间权重的误差项: 因为输出层的误差项是由隐藏层的权重决定的,把这个误差项当做输入反推回网络,就能像前面逐层正向的输出结果一样逐层地反向推导出误差项。这种类似正向传输的过程我们称之为反向传播

反向传播是训练神经网络的基本原理,因此对于构建深度学习模型,理解反向传播至关重要。- 引自udacity课件

  • 反向传播的实现 反向传播的实现包括正向和反向两个操作。正向操作是利用权重和输入,从输入层到输出层,计算出预测值ŷ;反向操作则是利用预测值ŷ,从输出层到输入层,求解出误差,误差项和w(权重更新步长),最后更新权重,完成一次迭代。 代码实现过程如下:
代码语言:javascript
复制
import numpy as np
from data_prep import features, targets, features_test, targets_test

np.random.seed(21)

def sigmoid(x):
    """
    Calculate sigmoid
    """
    return 1 / (1 + np.exp(-x))


# Hyperparameters
n_hidden = 2  # number of hidden units
epochs = 900
learnrate = 0.005

n_records, n_features = features.shape
last_loss = None
# Initialize weights
weights_input_hidden = np.random.normal(scale=1 / n_features ** .5,
                                        size=(n_features, n_hidden))
weights_hidden_output = np.random.normal(scale=1 / n_features ** .5,
                                         size=n_hidden)

for e in range(epochs):
    del_w_input_hidden = np.zeros(weights_input_hidden.shape)
    del_w_hidden_output = np.zeros(weights_hidden_output.shape)
    for x, y in zip(features.values, targets):
        ## 正向操作 ##
        # TODO: Calculate the output
        hidden_input = np.dot(x,weights_input_hidden)
        hidden_output = sigmoid(hidden_input)
        output = sigmoid(hidden_output)

        ## 反向操作##
        # TODO: Calculate the network's prediction error
        error = y-output

        # TODO: Calculate error term for the output unit
        output_error_term = error*output*(1-output)

        ## propagate errors to hidden layer

        # TODO: Calculate the hidden layer's contribution to the error
        hidden_error = weights_hidden_output*output_error_term
        
        # TODO: Calculate the error term for the hidden layer
        hidden_error_term = hidden_error*hidden_output*(1-hidden_output)
        
        # TODO: Update the change in weights
        del_w_hidden_output += output_error_term*hidden_output
        del_w_input_hidden += hidden_error_term*x[:,None]

    # TODO: Update weights
    weights_input_hidden += del_w_input_hidden*learnrate/n_records
    weights_hidden_output += del_w_hidden_output*learnrate/n_records
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.01.01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一.最简单的神经网络及其输出
  • 二.多元(层)神经网络及其输出
  • 三.神经网络的激活函数
    • 1. 什么是激活函数
      • 2. 为什么使用非线性的激活函数
        • 3. 常见的激活函数
        • 四.用代码实现一个简单的神经网络
        • 五.神经网络的梯度下降
        • 六.神经网络的反向传播
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档