(2编写网络)自己动手,编写神经网络程序,解决Mnist问题,并网络化部署

简介: 基于《神经网络和深度学习》这本绝好的教材提供的相关资料和代码,我们自己动手编写“随机取样的梯度下降神经网络”。为了更好地说明问题,我们先从简单的开始:1、sigmod函数,基本上就是基于定义的;#########helper函数#########计算sigmoid,这个函数来自定义def sigmoid(z): return 1.
基于《神经网络和深度学习》这本绝好的教材提供的相关资料和代码,我们自己动手编写“随机取样的梯度下降神经网络”。为了更好地说明问题,我们先从简单的开始:
1、sigmod函数,基本上就是基于定义的;

#########helper函数########
#计算sigmoid,这个函数来自定义
def sigmoid( z):
return 1.0/( 1.0+np.exp(-z))
#计算sigmoid的导数,这个函数可以被证明
def sigmoid_prime( z):
return sigmoid(z)*( 1 - sigmoid(z))

2、构造函数
###########Main函数########
#使用例子 net = GoNetwork([2, 3, 1])
class GoNetwork( object):

def __init__( self, sizes): #构造函数
self.num_layers = len(sizes) #层数
self.sizes = sizes #每层size
#随机生成子节点
self.biases= [np.random.randn(y, 1) for y in sizes[ 1:]]
# net.weights[1] 是一个存储着连接第二层和第三层神经元权重的 Numpy 矩阵。
self.weights = [np.random.randn(y, x)
for x, y in zip(sizes[:- 1], sizes[ 1:])]
这个地方有以下几个地方,一个是在Python中类和类的构造函数是这样定义的;二个是Python如何体现出其强大的数据处理能力的。
这里,如果
sizes = [2,  3,  1]
则sizes [1:] = [3,1]

numpy.random.randn(d0, d1, ..., dn)

这个函数的作用就是从标准正态分布中返回一个或多个样本值,比如

bbb = [np.random.randn( 3, 2)]
表示的是生成3X2的随机序列,可以这样来使用,就是加上偏置了
2.5 * np.random.randn(2, 4) + 3

返回:

array([[ 4.128****53,  1.764****44 ,  2.732****92,  2.90839231],
      [ 0.174****86,  4.92026887,  1.574****66, -0.4305991 ]])
aaa =[ np.random.randn(y, 1) for y in sizes[ 1:]]
这是一种Python的连写方法,这里就是对[3,1]分别生成随机序列。这个随机是用来干什么的?就是随机的权值。
描述 zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表
这里
zip(sizes[:-1], sizes[1:])
表示的是将第1、2层之间,2、3层之间的全连接生成随机权值。

3、前向网络,主要用于测试当前网络
def feedforward( self, a):
for b,w in zip( self.biases, self.weights):
a = sigmoid(np.dot(w,a)+b)
return a

非常直接的按照定义,进行上一层到下一层的前向 计算,注意这里得到的a也是x行1列的一个矩阵

4、评价函数,基本上也是按照定义进行设定的
def evaluate( self, test_data):
test_results = [(np.argmax( self.feedforward(x)), y) #这里需要注意feedforward的参数x,实际上它是一个in/out参数。
for (x, y) in test_data]
return sum( int(x == y) for (x, y) in test_results) #做出了正确的预测
这个地方调用了feedforward(x),并且和y进行比较,得到准确比对有哪些。应该说代码非常精简。

5、代价函数
#cost代价函数
def cost_derivative( self, output_activations, y):
return (output_activations-y)

以上几项都是非常好理解的,基本上你看到的立刻就能够理解,需要补充的知识并不是很多。结合上一课的相关知识,我们这里提出的所谓随机,就是提取很小的一块数据,而后进行计算梯度下降参数,更新网络的权重和偏置
def update_mini_batch( self, mini_batch, eta):
nabla_b = [np.zeros(b.shape) for b in self.biases] #生成b和w形状的以0填充的矩阵
nabla_w = [np.zeros(w.shape) for w in self.weights]
for x, y in mini_batch:
delta_nabla_b, delta_nabla_w = self.backprop(x, y) #理解反向传播就是一种快速计算梯度的方法
nabla_b = [nb+dnb for nb, dnb in zip(nabla_b, delta_nabla_b)]
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)]
其中
   nabla_b = [np.zeros(b.shape) for b in self.biases]
   nabla_w = [np.zeros(w.shape) for w in self.weights]
生成b和w形状的以0填充的矩阵,这里就是用来填充原始数据的。
在这个小循环里面,我们可以以“黑箱”的形式来理解backprop函数,就是一种用来计算最快下降梯度的方法。
 for x, y in mini_batch:
            delta_nabla_b, delta_nabla_w = self.backprop(x, y)
            nabla_b = [nb+dnb for nb, dnb in zip(nabla_b, delta_nabla_b)]
            nabla_w = [nw+dnw for nw, dnw in zip(nabla_w, delta_nabla_w)]
在这里,我们便历所有的mini_batch,注意在上面这行代码中,
而后,引入eta,以这个梯度作为 delta_nabla_b,  delta_nabla_w  的初始值都为空.
这样,我们按照定义进行了一次小数据的更新。其能够完成,是因为backprop为我们成功计算了代价函数的两个梯度。
6、后向传播函数,其目的是进行梯度下降计算,是最为复杂的部分
#反向传播就是一种快速计算代价函数梯度的方法,也就是计算delta的一种方法
def backprop( self, x, y):
#都以空矩阵来进行初始化
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights]
# feedforward
activation = x
activations = [x] # list to store all the activations, layer by layer
zs = [] # list to store all the z vectors, layer by layer
for b, w in zip( self.biases, self.weights):
z = np.dot(w, activation)+b #前向传播
zs.append(z)
activation = sigmoid(z)
activations.append(activation)
# backward pass
delta = self.cost_derivative(activations[- 1], y) * \
sigmoid_prime(zs[- 1])
nabla_b[- 1] = delta
nabla_w[- 1] = np.dot(delta, activations[- 2].transpose())
for l in range( 2, self.num_layers):
z = zs[-l]
sp = sigmoid_prime(z)
delta = np.dot( self.weights[-l+ 1].transpose(), delta) * sp
nabla_b[-l] = delta
nabla_w[-l] = np.dot(delta, activations[-l- 1].transpose())
return (nabla_b, nabla_w)

其中内容比较复杂,一条一条进行解释 
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights]
生成空矩阵
# feedforward
activation = x
activations = [x] # list to store all the activations, layer by layer
zs = [] # list to store all the z vectors, layer by layer
for b, w in zip( self.biases, self.weights):
z = np.dot(w, activation)+b #前向传播
zs.append(z)
activation = sigmoid(z)
activations.append(activation)

前向计算,保存所有b、w和 z。后面的几行代码,主要都是和4个公式严格对应的
delta = self.cost_derivative(activations[- 1], y) * sigmoid_prime(zs[- 1])

对应BP1

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

分别对应BP3和BP4,就是最后来计算具体的梯度值

delta = np.dot( self.weights[-l+ 1].transpose(), delta) * sp

对应BP2,反向计算。

7、 随机梯度下降算法,到了这里也就是将上面的合起来
#随机梯度下降算法
def SGD( self, training_data, epochs, mini_batch_size, eta, test_data= None):

training_data = list(training_data)
n = len(training_data)

if test_data:
test_data = list(test_data)
n_test = len(test_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 {} : {} / {} ".format(j, self.evaluate(test_data),n_test))
else:
print( "Epoch {} complete".format(j))
主要优化的地方,就是将原较大的数据集分成多个部分,而后遍历所有的部分,进行梯度下降运算,并且打印比较的结果。应该说再次体现了Python强大的集成编码能力。





目前方向:图像拼接融合、图像识别 联系方式:jsxyhelu@foxmail.com
目录
相关文章
用MASM32按Time Protocol(RFC868)协议编写网络对时程序中的一些有用的函数代码
用MASM32按Time Protocol(RFC868)协议编写网络对时程序中的一些有用的函数代码
|
3月前
|
Kubernetes Devops 持续交付
DevOps实践:使用Docker和Kubernetes实现持续集成和部署网络安全的守护盾:加密技术与安全意识的重要性
【8月更文挑战第27天】本文将引导读者理解并应用DevOps的核心理念,通过Docker和Kubernetes的实战案例,深入探讨如何在现代软件开发中实现自动化的持续集成和部署。文章不仅提供理论知识,还结合真实示例,旨在帮助开发者提升效率,优化工作流程。
|
1月前
|
安全 定位技术 数据安全/隐私保护
|
1月前
|
机器学习/深度学习 数据采集 算法
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
这篇博客文章介绍了如何使用包含多个网络和多种训练策略的框架来完成多目标分类任务,涵盖了从数据准备到训练、测试和部署的完整流程,并提供了相关代码和配置文件。
56 0
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
|
1月前
|
机器学习/深度学习 存储 自然语言处理
深度学习入门:循环神经网络------RNN概述,词嵌入层,循环网络层及案例实践!(万字详解!)
深度学习入门:循环神经网络------RNN概述,词嵌入层,循环网络层及案例实践!(万字详解!)
|
1月前
|
安全 网络协议 IDE
使用Python编写网络扫描程序
使用Python编写网络扫描程序
|
3月前
|
存储 网络协议 安全
|
3月前
|
机器学习/深度学习 人工智能 编解码
【神经网络】基于对抗神经网络的图像生成是如何实现的?
对抗神经网络,尤其是生成对抗网络(GAN),在图像生成领域扮演着重要角色。它们通过一个有趣的概念——对抗训练——来实现图像的生成。以下将深入探讨GAN是如何实现基于对抗神经网络的图像生成的
37 3
|
3月前
|
机器学习/深度学习 算法 文件存储
【博士每天一篇文献-算法】 PNN网络启发的神经网络结构搜索算法Progressive neural architecture search
本文提出了一种名为渐进式神经架构搜索(Progressive Neural Architecture Search, PNAS)的方法,它使用顺序模型优化策略和替代模型来逐步搜索并优化卷积神经网络结构,从而提高了搜索效率并减少了训练成本。
57 9
|
4月前
|
机器学习/深度学习 自然语言处理
像生物网络一样生长,具备结构可塑性的自组织神经网络来了
【7月更文挑战第24天】Sebastian Risi团队发布的arXiv论文探讨了一种模仿生物神经网络生长与适应特性的新型神经网络。LNDP利用结构可塑性和经验依赖学习,能根据活动与奖励动态调整连接,展现自我组织能力。通过基于图变换器的机制,LNDP支持突触动态增删,预先通过可学习随机过程驱动网络发育。实验在Cartpole等任务中验证了LNDP的有效性,尤其在需快速适应的场景下。然而,LNDP在复杂环境下的可扩展性及训练优化仍面临挑战,且其在大规模网络和图像分类等领域的应用尚待探索
91 20
下一篇
无影云桌面