2021-05-16

本文介绍了如何使用神经网络进行MNIST手写数字识别,并详细阐述了随机梯度下降(SGD)算法的实现过程,包括网络初始化、前向传播和反向传播(backpropagation)用于计算权重和偏置的梯度更新。通过mini-batch的方式进行训练,逐步优化模型性能。
摘要由CSDN通过智能技术生成

3.4~3.5 — 梯度下降算法的实现

mnist 手写数字识别

在这里插入图片描述

import numpy as np
class Network(object): #Network:神经网络类
  #初始化函数
  def __init__(self, sizes): #sizes: 网络的规模 例如: 上图的神经网络规模就是:[3, 4, 1]
    self.num_layers = len(sizes) #多少层神经网络 上图3层
    slef.sizes = sizes
    #下一句的解释:np.random.randn(y,1) 生成高斯分布的随机数,(y, 1): 其规模是y列表,生成1组。
    #[y for y in range] 快速列表生成器, 生成sizes[1:]规模的列表, 其中sizes[1:]是sizes除去第一个元素后面的元素。按上图就是[4,1]
    self.biases = [np.random.randn(y,1) for y in sizes[1:]]
    #其中zip():按照给的参数, 两两对应,组合生成新数据 x:[3,4], y:[4,1]
    self.weights = [np.random.randn(y,x) for x, y in zip(sizes[:-1], sizes[1:])]
    #a 是input向量, 返回下一个节点的值
  def feedforward(self, a):
    for b, w in zip(self.biases, self.weights):
      a = sigmoid(np.dot(w, a) + b) #np.dot()点积 w1.a1 + w2.a2 ...
    return a #输出, 下一个节点的值

  #随机梯度下降算法
  #              训练集, 训练多少轮,  一轮有多少实例,     学习率       
  def SGD(self, training_data, epochs, mini_batch_size, eta, test_data=None)
    """training_data is a list of tuples (x, y)"""
    
    if test_data: n_test = len(test_data);
    n = len(training_data)
    for j in xrange(epochs):
      random.shuffle(training_data) # shuffle:打乱洗牌,把training_data 打乱
      #xrange(0, n, mini_batch_size) 从0->n, 每次步进mini_batch_size大小
      mini_batches = [traning_data[k:k+mini_batch_size] for k in xrange(0, n, mini_batch_size)] 
      self.update_mini_batch(mini_batch, eta)
      if test_data:
        print "Epoch {0}: {1} / {2}".format(j, self.evaluate(test_data), n_test)
      else:
        print "Epoch {0} complete".format(j)
      

update_mini_batch() 函数中做的事情就是:
梯度下降更新:
在这里插入图片描述

随机梯度下降更新:(优选,下面的函数就是实现了该方程)
在这里插入图片描述

def update_mini_batch(self, mini_batch, eta):
  """在一轮mini_batch 训练中,使用backpropagation 的方法梯度下降更新 w, b"""
  #backpropagation:计算cost() 函数对于w, b 的偏导数的方法
  #初始化偏导叠加值(方程中最后面的那个)
  nabla_b = [np.zeros(b.shape) for b in self.biases]
  nabla_w = [np.zeros(w.shape) for w in self.weights]
  
  for x, y in mini_batch:
    # 求b, w 的 偏导数
    delta_nabla_b, delta_nabla_w = self.backprop(x, y)
    nabla_b = [nb + dnb for nb, dnb in zip(nabla_b, delta_nabla_b)] 将每个遍历(x,y)cost的关于b偏导叠加: sum(deltaC/deltaw)
    nabla_w = [nw + dnw for nw, dnw in zip(nabla_w, delta_nabla_w)] 
  self.weights = [w-(eta/len(mini_batch))*nw for w, nw in zip(self.weights, nabla_w)]
  self.biases = [b-(eta/len(mini_batch))*nb for b, nb in zip(self.biases, nabla_b)]
    
  #一轮mini_batch 遍历完成累加起来的变化量才更新到 w, b 中。
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值