最近花了半个多月把Mchiael Nielsen所写的Neural Networks and Deep Learning这本书看了一遍,受益匪浅。

该书英文原版地址地址:http://neuralnetworksanddeeplearning.com/

回顾一下这本书主要讲的内容

1.使用神经网络识别手写数字

作者从感知器模型引申到S型神经元。然后再到神经网络的结构。并用一个三层神经网络结构来进行手写数字识别,

作者详细介绍了神经网络学习所使用到梯度下降法,由于当训练输入数量过大时,学习过程将变的时分缓慢,就引

入了随机梯度下降的算法用来加速学习。

选取二次代价函数

神经网络的权重偏置更新法则如下:

其中m是随机选取的m个训练样本,我们把这些随机训练样本标记为X1,X2,X3,..,Xm.。并把它们称为一个小批量数据。

2.反向传播算法如何工作

这一章作者主要介绍了反向传播的四个公式。并给出了反向传播算法的计算流程:

以MNIST数据集为例,包含50000幅用于训练的手写图片,10000幅用于校验的手写图片,10000幅用于测试的手写图片。

MNIST数据集下载地址:https://github.com/mnielsen/neural-networks-and-deep-learning

1.输入训练集样本的集合

2.初始化迭代期次数(epochs),开始循环 for i in range(epochs):

2.1 打算输入训练集样本,按mini_batch_size(小批量大小)划分成许多组

2.2 针对每一小批量数据应用随机梯度下降法,并更新权重和偏置(程序中update_mini_batch(self,mini_batch,eta)函数)

2.3 一轮训练结束,用测试数据集检验准确率

3.神经网络学习结束

其中2.2步骤,尤为重要,针对小批量数据(mini_batch),如何应用随机梯度下降法,更新网络参数(update_mini_batch)

1.输入小批量数据的集合 mini_batch

2遍历每一个实例 (x,y),开始循环 for x,y in mini_batch:

2.1计算每一个实例的梯度 (backprop(self,x,y)函数)

2.1.1 对每层l = 2,3,...,L(输入层记做l=1,输出层l=L),计算每一层带全权输入zl = wlal-1+bl,激活输出al = σ(zl)

2.1.2 计算输出层误差 δL=∂C/∂aLσ‘(zL),计算∂Cx/∂ωLL(aL-1)T,∂Cx/∂bLL。(注意当选择不同的代价函数时δL值是不一样,

当选择二次代价函数时,δL=(aL-y)σ‘(zL),当选择交叉熵代价函数时,δL=(aL-y))

2.1.3 反向传播误差,对每个l = L-1,L-2,...,2 计算δl = ((ωl+1)Tδl+1)σ‘(zl),计算∂Cx/∂ωll(al-1)T,∂Cx/∂bll

2.1.4 ∂Cx/∂ω = [∂Cx/∂ω2,∂Cx/∂ω3,...,∂Cx/∂ωL], ∂Cx/∂b = [∂Cx/∂b2,∂Cx/∂b3,...,∂Cx/∂bL]

2.2计算梯度的累积和,Σ∂Cx/∂ω,Σ∂Cx/∂b

注意:步骤2中a,b,z,y,δl均是列向量

  为了提高计算的速度,步骤2我们可以采用向量化的计算方式。提示矩阵al可以写成al = [实例1al  实例2al   ....  实例mal ]

3.应用随机梯度下降法权重偏置更新法则更新权重和偏置 ω = ω-η/mΣ∂Cx/∂ω,b = b-η/mΣ∂Cx/∂b

选用三层神经网络,激活函数选取S型神经元,代价函数选取二次代价函数,实现程序如下:

Network1.py:非向量化方式

# -*- coding: utf- -*-
"""
Created on Mon Mar :: @author: Administrator
""" '''
书籍:神经网络与深度学习
第一章:利用梯度下降法训练神经网络算法 这里代价函数采用二次代价函数
''' import numpy as np
import random '''
定义S型函数
当输入z是一个向量或者numpy数组时,numpy自动地按元素应用sigmod函数,即以向量形式
'''
def sigmod(z):
return 1.0/(1.0+np.exp(-z)) '''
定义S型函数的导数
'''
def sigmod_prime(z):
return sigmod(z)*(-sigmod(z)) '''
定义一个Network类,用来表示一个神经网络
'''
class Network(object):
'''
sizes:各层神经元的个数
weights:权重,随机初始化,服从(,)高斯分布 weights[i]:是一个连接着第i层和第i+1层神经元权重的numpy矩阵 i=,...
biases:偏置,随机初始化,服从(,)高斯分布 biases[i]:是第i+1层神经元偏置向量 i=,....
'''
def __init__(self,sizes):
#计算神经网络的层数
self.num_layers = len(sizes)
#每一层的神经元个数
self.sizes = sizes
#随机初始化权重 第i层和i+1层之间的权重向量
self.weights = [np.random.randn(y,x) for x,y in zip(sizes[:-],sizes[:])]
#随机初始化偏置 第i层的偏置向量 i=...num_layers
self.biases = [np.random.randn(y,) for y in sizes[:]] '''
前向反馈函数,对于网络给定一个输入向量a,返回对应的输出
'''
def feedforward(self,a):
for b,w in zip(self.biases,self.weights):
#dot矩阵乘法 元素乘法使用*
a = sigmod(np.dot(w,a) + b)
return a '''
随机梯度下降算法:使用小批量训练样本来计算梯度(计算随机选取的小批量数据的梯度来估计整体的梯度)
training_data:元素为(x,y)元祖的列表 (x,y):表示训练输入以及对应的输出类别 这里的输出类别是二值化后的10*1维向量
epochs:迭代期数量 即迭代次数
mini_batch:小批量数据的大小
eta:学习率
test_data:测试数据 元素为(x,y)元祖的列表 (x,y):表示训练输入以及对应的输出类别 这里的输出就是对应的实际数字 没有二值化
'''
def SGD(self,training_data,epochs,mini_batch_size,eta,test_data=None):
if test_data:
#计算测试集样本个数
n_test = len(test_data)
#计算训练集样本个数
n = len(training_data)
#进行迭代
for j in range(epochs):
#将训练集数据打乱,然后将它分成多个适当大小的小批量数据
random.shuffle(training_data)
mini_batches = [training_data[k:k+mini_batch_size] for k in range(,n,mini_batch_size)]
#训练神经网络
for mini_batch in mini_batches:
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)) '''
mini_batch:小批量数据 元素为(x,y)元祖的列表 (x,y)
eta:学习率
对每一个mini_batch应用梯度下降,更新权重和偏置
'''
def update_mini_batch(self,mini_batch,eta):
#初始化为0
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:
#计算每一个样本代价函数的梯度(∂Cx/∂ω,∂Cx/∂b)
delta_nabla_b,delta_nabla_w = self.backprop(x,y)
#梯度分量求和 Σ∂Cx/∂ω
nabla_b = [nb + dnb for nb,dnb in zip(nabla_b,delta_nabla_b)]
#梯度分量求和 Σ∂Cx/∂b
nabla_w = [nw + dnw for nw,dnw in zip(nabla_w,delta_nabla_w)]
#更新权重 w = w - η/m*Σ∂Cx/∂ω
self.weights = [w - (eta/len(mini_batch))*nw for w,nw in zip(self.weights,nabla_w)]
#更新偏置 b = b - η/m*Σ∂Cx/∂b
self.biases = [b - (eta/len(mini_batch))*nb for b,nb in zip(self.biases,nabla_b)] '''
计算给定一个样本二次代价函数的梯度 单独训练样本x的二次代价函数 C = 0.5||y - aL||^ = 0.5∑(yj - ajL)^
返回一个元组(nabla_b,nabla_w) = (∂Cx/∂ω,∂Cx/∂b) :和权重weights,偏置biases维数相同的numpy数组
'''
def backprop(self,x,y):
#初始化与self.baises,self.weights维数一样的两个数组 用于存放每个训练样本偏导数的累积和
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights]
#前向反馈
activation = x
#保存除了输入层外所有层的σ(z)的值
activations = [x]
#保存除了输入层外所有层的z的值
zs = []
#计算除了输入层外每一层z和σ(z)的值
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 = self.cost_derivative(activations[-],y)*sigmod_prime(zs[-])
nabla_b[-] = delta
nabla_w[-] = np.dot(delta,activations[-].transpose())

#计算反向传播误差
for l in range(,self.num_layers):
z = zs[-l]
sp = sigmod_prime(z)
delta = np.dot(self.weights[-l+].transpose(),delta)*sp
nabla_b[-l] = delta
nabla_w[-l] = np.dot(delta,activations[-l-].transpose())
return (nabla_b,nabla_w) '''
对神经网络预测准确率进行评估
'''
def evaluate(self,test_data):
#np.argmax返回最大值所在的索引 这里获取预测数值和实际数值组成元组的列表
test_results = [(np.argmax(self.feedforward(x)),y) for x,y in test_data]
#计算预测值 == 实际值的总个数
return sum(int(x==y) for x,y in test_results) '''
计算损失函数的偏导数∂C/∂a a是实际输出
'''
def cost_derivative(self,output_activations,y):
return (output_activations - y) import mnist_loader
def  network_baseline():
    #遇到编码错误:参考链接http://blog.csdn.net/qq_41185868/article/details/79039604S
    #traning_data:[(784*1,10*1),...],50000个元素
    #validation_data[(784*1,1*1),....],10000个元素
    #test_data[(784*1,1*1),....],10000个元素
    training_data,validation_data,test_data = mnist_loader.load_data_wrapper()
    print('训练集数据长度',len(training_data))
    print(training_data[0][0].shape)      #训练集每一个样本的特征维数   (784,1)
    print(training_data[0][1].shape)      #训练集每一个样本对应的输出维数  (10,1)
    
    print('测试集数据长度',len(test_data))
    print(test_data[0][0].shape)         #测试机每一个样本的特征维数,1,1   (784,1)
    #print(test_data[0][1].shape)         #测试机每一个样本对应的输出维数   () 这里与训练集的输出略有不同,这里输出是一个数 并不是二指化后的10*1维向量
    print(test_data[0][1])               #7
       
    #测试
    net = Network([784,30,10])
    '''
    print(net.num_layers)      #3
    print(net.sizes)
    print(net.weights)
    print(net.biases)
    '''
    
    net.SGD(training_data,30,10,3.0,test_data=test_data) #运行程序
network_baseline()
    

向量化方式:

# -*- coding: utf-8 -*-
"""
Created on Mon Mar 5 20:24:32 2018 @author: Administrator
""" '''
书籍:神经网络与深度学习
第一章:利用梯度下降法训练神经网络算法 这里代价函数采用二次代价函数
这里采用向量化的方式,实现了正向传播和反向传播
''' import numpy as np
import random '''
定义S型函数
当输入z是一个向量或者numpy数组时,numpy自动地按元素应用sigmod函数,即以向量形式
'''
def sigmod(z):
return 1.0/(1.0+np.exp(-z)) '''
定义S型函数的导数
'''
def sigmod_prime(z):
return sigmod(z)*(1-sigmod(z)) '''
定义一个Network类,用来表示一个神经网络
'''
class Network(object):
'''
sizes:各层神经元的个数
weights:权重,随机初始化,服从(0,1)高斯分布 weights[i]:是一个连接着第i层和第i+1层神经元权重的numpy矩阵 i=0,1...
biases:偏置,随机初始化,服从(0,1)高斯分布 biases[i]:是第i+1层神经元偏置向量 i=0,1....
'''
def __init__(self,sizes):
#计算神经网络的层数
self.num_layers = len(sizes)
#每一层的神经元个数
self.sizes = sizes
#随机初始化权重 第i层和i+1层之间的权重向量
self.weights = [np.random.randn(y,x) for x,y in zip(sizes[:-1],sizes[1:])]
#随机初始化偏置 第i层的偏置向量 i=1...num_layers
self.biases = [np.random.randn(y,1) for y in sizes[1:]] '''
前向反馈函数,对于网络给定一个输入向量a,返回对应的输出
'''
def feedforward(self,a):
for b,w in zip(self.biases,self.weights):
#dot矩阵乘法 元素乘法使用*
a = sigmod(np.dot(w,a) + b)
return a '''
随机梯度下降算法:使用小批量训练样本来计算梯度(计算随机选取的小批量数据的梯度来估计整体的梯度)
training_data:元素为(x,y)元祖的列表 (x,y):表示训练输入以及对应的输出类别 这里的输出类别是二值化后的10*1维向量
epochs:迭代期数量 即迭代次数
mini_batch:小批量数据的大小
eta:学习率
test_data:测试数据 元素为(x,y)元祖的列表 (x,y):表示训练输入以及对应的输出类别 这里的输出就是对应的实际数字 没有二值化
'''
def SGD(self,training_data,epochs,mini_batch_size,eta,test_data=None):
if test_data:
#计算测试集样本个数
n_test = len(test_data)
#计算训练集样本个数
n = len(training_data)
#进行迭代
for j in range(epochs):
#将训练集数据打乱,然后将它分成多个适当大小的小批量数据
random.shuffle(training_data)
mini_batches = [training_data[k:k+mini_batch_size] for k in range(0,n,mini_batch_size)]
#训练神经网络
for mini_batch in mini_batches:
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)) '''
mini_batch:小批量数据 元素为(x,y)元祖的列表 (x,y)
eta:学习率
对每一个mini_batch应用梯度下降,更新权重和偏置 采用向量化方式计算
'''
def update_mini_batch(self,mini_batch,eta):
#初始化与self.baises,self.weights维数一样的两个数组 用于存放每个训练样本偏导数的累积和
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights] #实例数
m = len(mini_batch)
#print('小批量数目',m) #把输入样本形式转换为 [样本1列向量 样本2列向量 ... 样本m列向量]的形式
#[样本1类别列向量 样本2类别列向量 ... 样本m类别列向量]的形式
training_x = [x for x,y in mini_batch] #(10,(784,1))
training_y = [y for x,y in mini_batch] #(10,(10,1)) #注意这里需要转置
X = np.array(training_x).reshape(m,training_x[0].shape[0]).T
Y = np.array(training_y).reshape(m,training_y[0].shape[0]).T #print('X',X.shape) #(784,10)
#print('Y',Y.shape) #(10,10) #计算前向输出
activation = X
#保存除了输入层外所有层的σ(z)的值
activations = [X]
#保存除了输入层外所有层的z的值
zs = []
#计算除了输入层外每一层z和σ(z)的值
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 = self.cost_derivative(activations[-1],Y)*sigmod_prime(zs[-1])
nabla_w[-1] = np.dot(delta,activations[-2].transpose())
#按照行求和
nabla_b[-1] = np.sum(delta,axis = 1, keepdims = True) #计算反向传播误差
for l in range(2,self.num_layers):
delta = np.dot(self.weights[-l+1].transpose(),delta)*sigmod_prime(zs[-l])
nabla_w[-l] = np.dot(delta,activations[-l-1].transpose())
nabla_b[-l] = np.sum(delta,axis =1,keepdims=True) #更新权重 w = w - η/m*Σ∂Cx/∂ω
self.weights = [w - eta/m*nw for w,nw in zip(self.weights,nabla_w)]
#更新偏置 b = b - η/m*Σ∂Cx/∂b
self.biases = [b - eta/m*nb for b,nb in zip(self.biases,nabla_b)] '''
对神经网络预测准确率进行评估
'''
def evaluate(self,test_data):
#np.argmax返回最大值所在的索引 这里获取预测数值和实际数值组成元组的列表
test_results = [(np.argmax(self.feedforward(x)),y) for x,y in test_data]
#计算预测值 == 实际值的总个数
return sum(int(x==y) for x,y in test_results) '''
计算损失函数的偏导数∂C/∂a a是实际输出
'''
def cost_derivative(self,output_activations,y):
return (output_activations - y) import mnist_loader def network_baseline():
#遇到编码错误:参考链接http://blog.csdn.net/qq_41185868/article/details/79039604S
#traning_data:[(784*1,10*1),...],50000个元素
#validation_data[(784*1,1*1),....],10000个元素
#test_data[(784*1,1*1),....],10000个元素
training_data,validation_data,test_data = mnist_loader.load_data_wrapper()
print('训练集数据长度',len(training_data))
print(training_data[0][0].shape) #训练集每一个样本的特征维数 (784,1)
print(training_data[0][1].shape) #训练集每一个样本对应的输出维数 (10,1) print('测试集数据长度',len(test_data))
print(test_data[0][0].shape) #测试机每一个样本的特征维数,1,1 (784,1)
#print(test_data[0][1].shape) #测试机每一个样本对应的输出维数 () 这里与训练集的输出略有不同,这里输出是一个数 并不是二指化后的10*1维向量
print(test_data[0][1]) # #测试
net = Network([784,30,10])
'''
print(net.num_layers) #3
print(net.sizes)
print(net.weights)
print(net.biases)
''' net.SGD(training_data,30,10,3,test_data=test_data) network_baseline()

 参考文章

[1]深度神经网络(DNN)模型与前向传播算法

[2]深度神经网络(DNN)反向传播算法(BP)

第四节,Neural Networks and Deep Learning 一书小节(上)的更多相关文章

  1. 第五节,Neural Networks and Deep Learning 一书小节(中)

    在这一节,我们对上一个程序(Network1.py)进行了优化 3.改进神经网络的学习方法 (1)交叉熵代价函数的引入 Network1程序采用了S型神经元,S型神经元存在一个问题,当输出层神经元的输 ...

  2. 第六节,Neural Networks and Deep Learning 一书小节(下)

    4.神经网络可以计算任何函数的可视化证明 神经网络拥有一定的普遍性,即包含一个隐藏层的神经网络可以被用来按照任意给定的精度来近似任何连续函数. 这一章使用一个实例来阐述神经网络是如何来近似一个一元函数 ...

  3. 【DeepLearning学习笔记】Coursera课程《Neural Networks and Deep Learning》——Week1 Introduction to deep learning课堂笔记

    Coursera课程<Neural Networks and Deep Learning> deeplearning.ai Week1 Introduction to deep learn ...

  4. 【DeepLearning学习笔记】Coursera课程《Neural Networks and Deep Learning》——Week2 Neural Networks Basics课堂笔记

    Coursera课程<Neural Networks and Deep Learning> deeplearning.ai Week2 Neural Networks Basics 2.1 ...

  5. Neural Networks and Deep Learning学习笔记ch1 - 神经网络

    近期開始看一些深度学习的资料.想学习一下深度学习的基础知识.找到了一个比較好的tutorial,Neural Networks and Deep Learning,认真看完了之后觉得收获还是非常多的. ...

  6. Neural Networks and Deep Learning

    Neural Networks and Deep Learning This is the first course of the deep learning specialization at Co ...

  7. [C3] Andrew Ng - Neural Networks and Deep Learning

    About this Course If you want to break into cutting-edge AI, this course will help you do so. Deep l ...

  8. 《Neural Networks and Deep Learning》课程笔记

    Lesson 1 Neural Network and Deep Learning 这篇文章其实是 Coursera 上吴恩达老师的深度学习专业课程的第一门课程的课程笔记. 参考了其他人的笔记继续归纳 ...

  9. [C1W1] Neural Networks and Deep Learning - Introduction to Deep Learning

    第一周:深度学习引言(Introduction to Deep Learning) 欢迎(Welcome) 深度学习改变了传统互联网业务,例如如网络搜索和广告.但是深度学习同时也使得许多新产品和企业以 ...

随机推荐

  1. Golang的Json encode/decode以及[]byte和string的转换

    使用了太长时间的python,对于强类型的Golang适应起来稍微有点费力,不过操作一次之后发现,只有这么严格的类型规定,才能让数据尽量减少在传输和解析过程中的错误.我尝试使用Golang创建了一个公 ...

  2. php1

    正则表达式 $p = '/name:(\w+\s?\w+)/'; $str = "name:steven jobs"; preg_match($p, $str, $match); ...

  3. 【python练习题】程序8

    #题目:输出 9*9 乘法口诀表. for i in range(1,10): k = '' for j in range(1,i+1): k += '%s * %s = %s '%(i,j,i*j) ...

  4. word公式大小

    下面给出MathType与Word对应的字体关系,大家可以根据自己的实际需求,调整自己的公式大小.  MathType与Word对应的字体关系示例 以上给大家详细介绍了调整MathType公式字体大小 ...

  5. Windows Server 2012 Hyper-V 快照

    快照 Hyper-V 可提供擷取執行中虛擬機器快照的能力,因此可輕易地回復至前一狀態,對於測試環境相當有幫助. 快照的功用雖然很不錯,不過每次建立快照時都是會消耗相當的硬碟資源,尤其目前的快照點和上一 ...

  6. Nginx 缓存针对打开的文件句柄与原文件信息

    L:108 open_file_cache syntax: open_file_cache off;   open_file_cache max=N[inactive=time](inactive表示 ...

  7. 在 ubuntu 中安装 python3.5、 tornado、 pymysql

    一.在 ubuntu 中安装 python3.5 1.首先,在系统中是自带python2.7的.不要卸载,因为一些系统的东西是需要这个的.python2.7和python3.5是可以共存的. 命令如下 ...

  8. 关于jQuery.when()用法

    1.该方法在jQuery1.5开始被引入. 2.用法测试 a. var url1 = "/resource/ar/hometab/index_tab_games.json", ur ...

  9. MyBatis实操进阶版(一)

    MyBatis实操进阶版(一) 目前而言,持久层框架中,在业务实现灵活性上,无可出MyBatis之右者.具体原因,后续将逐步展开 ResultMap元素的设置 配置文件中,ResultMap元素的作用 ...

  10. 【CF833E】Caramel Clouds(线段树)

    [CF833E]Caramel Clouds(线段树) 题面 CF 洛谷 题解 首先把区间一段一段分出来,那么只有四种情况. 要么没有被任何一朵云被覆盖,那么直接就会产生这一段的贡献. 要么被一朵云覆 ...