深度学习入门

神经网络

简介

  • 神经网络的特征就是可以从数据中学习
  • 深度学习也称为端到端的学习,从输入中获取输出
  • 训练数据和测试数据两部分
  • 追求模型的泛化能力,泛化能力是值处理未被观察过的数据的能力,终极目标
  • 只对某个数据集过度拟合的状态称为过拟合,避免过拟合

损失函数

  • 当前神经网络对监督数据在多大程度上不拟合
  • 均方误差:
def mean_squared_error(y, t):
    return 0.5 * np.sum((y-t)**2)
  • 交叉熵误差:
def cross_entropy_error(y, t):
    delta = 1e-7  #保护,防止出现log(0)
    return -np.sum(t * np.log(y + delta))

mini-batch 学习

  • 从训练数据中选出一批数据,然后对每个mini-batch进行学习
  • mini-batch版交叉熵误差:
# one-hot,t为0的元素可以忽略
def cross_entropy_error(y, t):
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)

    batch_size = y.shape[0]
    return -np.sum(t * np.log(y + 1e-7)) / batch_size

# 非one-hot
def cross_entropy_error(y, t):
    if y.ndim == 1:
        t = t.reshape(1, t.size) 
        y = y.reshape(1, y.size)

    batch_size = y.shape[0] 
    return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size
  • 寻找最优参数(权重和偏置)时,要寻找使损失函数尽可能小的参数。
  • 需要计算参数的梯度,然后以此为指引,逐步更新参数

数值微分

  • 利用微小的差分求导数的过程称为数值微分
  • 基于数学式的推导求导数的过程称为解析性求导,是不含误差的“真的导数”
  • 数值微分:
def numerical_diff(f, x):
  h = 1e-4 # 0.0001 
  return (f(x+h) - f(x-h)) / (2*h)
  • 全部变量的偏导数汇总而成的向量称为梯度:
def numerical_gradient(f, x):
    h = 1e-4 # 0.0001 
    grad = np.zeros_like(x) # 生成和x形状相同的数组

    for idx in range(x.size):
      tmp_val = x[idx] 
      # f(x+h)的计算 
      x[idx] = tmp_val + h 
      fxh1 = f(x)

      # f(x-h)的计算 
      x[idx] = tmp_val - h 
      fxh2 = f(x)

      grad[idx] = (fxh1 - fxh2) / (2*h) 
      x[idx] = tmp_val # 还原值

    return grad
  • 梯度指示的方向是各点处函数值减少最多的方向
  • 梯度法:不断沿梯度方向前进,逐渐减小函数值的过程
  • 主要是梯度下降法,即寻找最小值的梯度法
  • 学习率:多大程度上更新参数
  • 数学公式表示梯度下降:Ƞ即学习率
  • 梯度下降法:
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
  • 学习率过大或过小都不好
  • 学习率这样的参数是超参数,人工设定,需要多次尝试

误差反向传播

计算图

  • 节点用○表示,○中是计算的内容,计算结果写在箭头上方
  • 构建计算图,在计算图上从左往右进行计算,即正向传播
  • 计算图可以集中精力于局部计算
  • 计算图的优点是可以通过正向传播和反向传播高效地计算各个变量的导数值

反向传播

  • 加法的反向传播只是将上游的值传给下游,并不需要正向传播的输入信号
  • 乘法的反向传播需要正向传播的输入信号值,并翻转传给下游
  • 乘法层的实现
class MulLayer:
    def __init__(self):
        self.x = None
        self.y = None
    
    def forward(self, x, y):
        self.x = x
        self.y = y
        out = x * y
        
        return out
    
    def backward(self, dout):
        dx = dout * self.y
        dy = dout * self.x
        
        return dx, dy
  • 加法层的实现:
class Addlayer:
    def __init__(self):
        pass
    
    def forward(self, x, y):
        out = x + y
        
        return out
    
    def backward(self, dout):
        dx = dout * 1
        dy = dout * 1
        
        return dx, dy

你可能感兴趣的:(深度学习入门)