深度学习---手写字体识别程序分析(python) - 小Dream

时间:2024-03-10 15:40:48

深度学习---手写字体识别程序分析(python)

我想大部分程序员的第一个程序应该都是“hello world”,在深度学习领域,这个“hello world”程序就是手写字体识别程序。

这次我们详细的分析下手写字体识别程序,从而可以对深度学习建立一个基本的概念。

1.初始化权重和偏置矩阵,构建神经网络的架构

import numpy as np

class network():

  def __init__(self, sizes):

    self.num_layers = len(sizes) 

    self.sizes = sizes

    self.biases = [ np.random.randn(y,1) for y in sizes[1:] ]

    self.weights = [ np.random.randn(y,x) for x,y in zip(sizes(:-1), sizes(1:)) ]

 

在实例化一个神经网络时,去初始化权重和偏置的矩阵,例如

  network0 = network([784, 30, 10])

可以初始化一个3层的神经网络, 各层神经元的个数分别为 784, 30 , 10

 

2. 如何去反向传播计算代价函数的梯度?

这个过程可以大概概括如下:

(1)正向传播,获得每个神经元的带权输出和激活因子(a)

(2)计算输出层的误差

(3)反向传播计算每一层的误差和梯度

用python实现的代码如下:

def backprop(self, x, y):

  delta_w = [ np.zeros(w.shape) for w in self.weights]

       delta_b = [ np.zeros(b.shape)  for b in self.biases ]

       

       #计算每个神经元的带权输入z及激活值

  zs = []

       activation = x

       activations = [x]

  for b,w in zip(self.biases, self.weights):

    z = np.dot(w, activation) + b

    zs.append(z)

    activation = sigmod(z)

    activations.append(activation)

      #计算输出层误差(这里采用的是二次代价函数)

  delta = (activations[-1] - y) * sigmod_prime(zs[-1])

  delta_w[-1] = np.dot(delta, activations[-2].transpose())

  delta_b[-1] = delta

 

  #反向传播

  for l in xrange(2, self.num_layers):

    delta = np.dot(delta_w[-l+1].transpose(),delta)*sigmod_prime(zs[-l])

    delta_w[-l] = np.dot(delta, activations[-l-1].transpose())

    delta_b[-l] = delta

  return delta_w, delta_b

 

3.如何梯度下降,更新权重和偏置?

通过反向传播获得了更新权重和偏置的增量,进一步进行更新,梯度下降。

def update_mini_batch(self, mini_batch, eta):

  delta_w = [ np.zeros(w.shape) for w in self.weights ]

  delta_b = [ np.zeros(b.shape) for b in self.biases ]

  for x,y in mini_batch:

    (这里针对一个小批量内所有样本,应用反向传播,积累权重和偏置的变化)

    delta_w_p, delta_b_p = self.backprop(x,y)

    delta_w = [ dt_w + dt_w_p for dt_w,dt_w_p in zip(delta_w, delta_w_p)]

    delta_b = [ dt_b + dt_b_p for dt_b,dt_b_p in zip(delta_b, delta_b_p)]

  self.weights = [ w-(eta/len(mini_batch)*nw) for w,nw in zip(self.weights, delta_w)]

  self.biases = [ b-(eta/len(mini_batch)*nb) for b,nb in zip(self.biases, delta_b)]

 

def SGD(self, epochs, training_data,  mini_batch_size,eta, test_data=None):

  if test_data:

    n_tests = len(tast_data)

  n_training_data = len(training_data)

  for i in xrange(0, epochs):

    random.shuffle(training_data)

    mini_batches = [  training_data[k:k+mini_batch_size]

            for k in xrange(0, n_training_data, mini_batch_size)

            ]

    for mini_batch in mini_batches:

      self.update_mini_batch(mini_batch, eta)