最近花了半个多月把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. python学习笔记(12)--程序设计方法学

    计算思维: 逻辑思维:推演和演绎 实证思维:实验和验证,引力波->实验 计算思维:设计和构造,计算机为代表,汉诺塔递归. 计算思维特征 抽象和自动化,抽象问题的计算过程,利用计算机自动化求解. ...

  2. linux命令logger使用

    先从别的地方抄过来全部的解释,如下: **options (选项):** -d, --udp 使用数据报(UDP)而不是使用默认的流连接(TCP) -i, --id 逐行记录每一次logger的进程I ...

  3. 移动APP用例设计中的关键点(转载)

    http://www.51testing.com/html/52/n-4421752.html 在测试工作中我们需要不断的总结和储备自己的知识和经验,譬如具备特定属性.环境以及场景,如:PC,手机,智 ...

  4. PHP超级全局变量、魔术变量和魔术函数

    PHP超级全局变量(9个) $GLOBALS 储存全局作用域中的变量 $_SERVER 获取服务器相关信息 $_REQUEST 获取POST和GET请求的参数 $_POST 获取表单的POST请求参数 ...

  5. 使用javaWeb的二大(Listener、Filter)组件实现分IP统计访问次数

    分析: 统计工作需要在所有资源之前都执行,那么就可以放到Filter中. 我们这个过滤器不打算做拦截操作!因为我们只是用来做统计 用什么东西来装载统计的数据.Map<String,Integer ...

  6. 5.cgroup资源控制

    控制组( CGroups)是 Linux 内核的一个特性,主要用来对共享资源进行隔离.限制.审计等. 只有将分配到容器的资源进行控制,才能避免多个容器同时运行时对宿主机系统的资源竞争.每个控制组是一组 ...

  7. Redux学习(3) ----- 结合React使用

    Redux 和React 进行结合, 就是用React 做UI, 因为Redux中定义了state,并且定义了改变或获取state的方法,完全可以用来进行状态管理,React中就不用保存状态了,它只要 ...

  8. codeforces722B

    Verse Pattern CodeForces - 722B You are given a text consisting of n lines. Each line contains some ...

  9. 大学jsp实验6session

    1.session对象的使用 (1)设计一个简单的在线问卷调查程序,共有3个页面,分别是one.jsp.two.jsp.three.jsp. 其中,shiyan6_1_one.jsp页面效果如下图所示 ...

  10. python查找读写文件

    import os ''' 跟据文件名称,后缀查找指定文件 path:传入的路径 filename:要查找的文件名 suffix:要查找的文件后缀 return :返回查找的文件路径 ''' file ...