深度学习入门——基于python的基本理论与实现

3.1神经网络

3.2激活函数

3.2.1 sigmoid函数

神经网络中经常使用的一个激活函数就是式表示的sigmoid函数
(sigmoid function)。
在这里插入图片描述

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

>>> x = np.array([-1.0, 1.0, 2.0])
>>> sigmoid(x)
array([ 0.26894142, 0.73105858, 0.88079708])

3.2.7 ReLU函数

sigmoid函数很早就开始被使用了,而最近则主要使用ReLU(Rectified Linear Unit)函数。
在这里插入图片描述

def relu(x):
 return np.maximum(0, x)

3.3 多维数组的运算在这里插入图片描述

在这里插入图片描述

>>> A = np.array([[1,2], [3, 4], [5,6]])
>>> A.shape
(3, 2)
>>> B = np.array([7,8])
>>> B.shape
(2,)
>>> np.dot(A, B)
array([23, 53, 83])

3.4 3层神经网络的实现

在这里插入图片描述

在这里插入图片描述
#3层神经网络的实现

import numpy as np

def sigmoid(x):#激活函数
 return 1 / (1 + np.exp(-x))
def identity_function(x):#最后一层的激活函数
 return x

def init_network():
 network = {}
 network['W1'] = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
 network['b1'] = np.array([0.1, 0.2, 0.3])
 network['W2'] = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])
 network['b2'] = np.array([0.1, 0.2])
 network['W3'] = np.array([[0.1, 0.3], [0.2, 0.4]])
 network['b3'] = np.array([0.1, 0.2])
 return network
def forward(network, x):
 W1, W2, W3 = network['W1'], network['W2'], network['W3']
 b1, b2, b3 = network['b1'], network['b2'], network['b3']
 a1 = np.dot(x, W1) + b1
 z1 = sigmoid(a1)
 a2 = np.dot(z1, W2) + b2
 z2 = sigmoid(a2)
 a3 = np.dot(z2, W3) + b3
 y = identity_function(a3)
 return y

network = init_network()
x = np.array([1.0, 0.5])
y = forward(network, x)
print(y) # [ 0.31682708 0.69627909]

3.5 输出层的设计

  • 一般而言,回归问题用恒等函数,分类问题用softmax函数
  • 分类问题中使用的softmax函数可以用下面的式子表示。
  • softmax函数的输出值的总和是1。输出总和为1是softmax函数的一个重要性质。正因为有了这个性质,我们才可以把softmax函数的输出解释为“概率”。

在这里插入图片描述

  • 在计算机的运算上有一定的缺陷。这个缺陷就是溢出问题。
  • 通过减去输入信号中的最大值(上例中的c),我们发现原本为nan(not a number,不确定)的地方,现在被正确计算了。
def softmax(a):
 c = np.max(a)
 exp_a = np.exp(a - c) # 溢出对策
 sum_exp_a = np.sum(exp_a)
 y = exp_a / sum_exp_a
 return y

神经网络的学习

4.2 损失函数

4.2.1 均方误差

在这里插入图片描述

def mean_squared_error(y, t):
    return 0.5 * np.sum((y-t)**2)
>>> # 设“2”为正确解
>>> t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
>>>
>>> # 例1:“2”的概率最高的情况(0.6)
>>> y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
>>> mean_squared_error(np.array(y), np.array(t))
0.097500000000000031
>>>
>>> # 例2:“7”的概率最高的情况(0.6)
>>> y = [0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0]
>>> mean_squared_error(np.array(y), np.array(t))
0.59750000000000003

4.2.2 交叉熵误差

在这里插入图片描述
函数内部在计算np.log时,加上了一个微小值delta。这是因为,当出现np.log(0)时,np.log(0)会变为负无限大的-inf,这样一来就会导致后续计算无法进行。

#代码实现交叉熵误差。
def cross_entropy_error(y, t):
 delta = 1e-7
 return -np.sum(t * np.log(y + delta))
>>> t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
>>> y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
>>> cross_entropy_error(np.array(y), np.array(t))
0.51082545709933802

4.2.3 mini-batch学习

假设数据有N个,tnk表示第n个数据的第k个元素的值(ynk是神经网络的输出,tnk是监督数据)
在这里插入图片描述
扩大到了N份数据,不过最后还要除以N进行正规化。
如果遇到大数据,数据量会有几百万、几千万之多,这种情况下以全部数据为对象计算损失函
数是不现实的。因此,我们从全部数据中选出一部分,作为全部数据的“近似”。

4.2.4 mini-batch版交叉熵误差的实现

(非one-hot表示,而是像“2”“7”这样的标签)时,交叉熵误差可通过如下代码实现。

def cross_entropy_error(y, t):
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)
        
    # 监督数据是one-hot-vector的情况下,转换为正确解标签的索引
    if t.size == y.size:
        t = t.argmax(axis=1)
             
    batch_size = y.shape[0]
    return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size

4.2.5 为何要设定损失函数

如果导数的值为负,通过使该权重参数向正方向改变,可以减小损失函数的值;反过来,如果导数的值为正,则通过使该权重参数向负方向改变,可以减小损失函数的值。
导数
变为0,导致参数无法更新。sigmoid函数的导数在任何地方都不为0。这对神经网络的学习非常重要。

4.3 数值微分

4.3.1 导数

def numerical_diff(f, x):
 h = 1e-4 # 0.0001
 return (f(x+h) - f(x-h)) / (2*h)

梯度

#二元的   
#权重W的梯度
def numerical_gradient(f, x):
    h = 1e-4 # 0.0001
    grad = np.zeros_like(x)
    # 多维迭代
    it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])
    while not it.finished:
        idx = it.multi_index
        tmp_val = x[idx]
        x[idx] = float(tmp_val) + h
        fxh1 = f(x) # f(x+h)
        
        x[idx] = tmp_val - h 
        fxh2 = f(x) # f(x-h)
        grad[idx] = (fxh1 - fxh2) / (2*h)
        
        x[idx] = tmp_val # 还原值
        it.iternext()   
        
    return grad


>>> numerical_gradient(function_2, np.array([3.0, 0.0]))
array([ 6., 0.])

梯度法
在这里插入图片描述
init_x是初始值,lr是学习率learning rate,step_num是梯度法的重复次数。
numerical_gradient(f,x)会求函数的梯度,用该梯度乘以学习率得到的值进行更新操作,由step_num指定重复的次数。使用这个函数可以求函数的极小值,顺利的话,还可以求函数的最小值。

def gradient_descent(f, init_x, lr=0.01, step_num=100):
     x = init_x
    for i in range(step_num):
        grad = numerical_gradient(f, x)
        x -= lr * grad
    return x
# 学习率过大的例子:lr=10.0
>>> init_x = np.array([-3.0, 4.0])
>>> gradient_descent(function_2, init_x=init_x, lr=10.0, step_num=100)
array([ -2.58983747e+13, -1.29524862e+12])
# 学习率过小的例子:lr=1e-10
>>> init_x = np.array([-3.0, 4.0])
>>> gradient_descent(function_2, init_x=init_x, lr=1e-10, step_num=100)
array([-2.99999994, 3.99999992])

实验结果表明,学习率过大的话,会发散成一个很大的值;反过来,学习率过小的话,基本上没怎么更新就结束了。

  • 像学习率这样的参数称为超参数,学习率这样的超参数则是人工设定的。

4.4.2 神经网络的梯度

在这里插入图片描述

学习相关技巧

6.2 权重的初始值

偏向0和1的数据分布会造成反向传播中梯度的值不断变小,最后消失。这个问题称为梯度消失(gradient vanishing)。层次加深的深度学习中,梯度消失的问题可能会更加严重

各层的激活值的分布都要求有适当的广度。为什么呢?因为通过
在各层间传递多样性的数据,神经网络可以进行高效的学习。反
过来,如果传递的是有所偏向的数据,就会出现梯度消失或者“表
现力受限”的问题,导致学习可能无法顺利进行。

总结: 当激活函数使用ReLU时,权重初始值使用He初始值,当
激活函数为sigmoid或tanh等S型曲线函数时,初始值使用Xavier初始值。
这是目前的最佳实践。

6.3 Batch Normalization

7.卷积神经网络

7.4.2 基于 im2col的展开

NumPy中存在使用for语句后处理变慢的缺点(NumPy中,访问元素时最好不要用for语句)。这里,我们不使用for语句,而是使用im2col这个便利的函数进行简单的实现

im2col这个名称是“image to column”的缩写,翻译过来就是“从
图像到矩阵”的意思。Caffe、Chainer 等深度学习框架中有名为
im2col的函数,并且在卷积层的实现中,都使用了im2col。
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值