神经网络模型实现手写字分类求解思路

《实例》阐述算法,通俗易懂,助您对算法的理解达到一个新高度。包含但不限于:经典算法,机器学习,深度学习,LeetCode 题解,Kaggle 实战。期待您的到来!

01

回顾

昨天介绍了神经网络的基本模型结构,可分类为前向传播神经网络,循环神经网络(RNN);介绍了神经网络中,梯度下降的原理推导,以小球下坡作为实例阐述梯度下降;分析了神经网络模型解决机器学习问题,与传统的机器学习算法的异同;并初步介绍了手写字分类的背景知识,欢迎参考:

下面,通过经典的手写字数据集来进一步认识神经网络模型解决分类问题的思考方式,原理,代码实现,通过这篇您学到如下重要的知识,这些是入门深度学习必须要掌握的理论和工具:

拿到一个分类任务后,通过神经网络模型求解的思维方式

神经网络前向传播原理

SGD 的实现原理(包括代码)

反向传播的代码实现(接下来几天详细推送反向传播的原理)

评估分类结果精确度的方法

如何设定与某个问题相关的特定神经网络

02

神经网络模型求解手写字分类的核心代码

2.1 手写字分类问题解决步骤

手写字分类可以分解为2类子问题,第一,把图像分解为连续的按位分开的单个数字图像,例如,将图像

分解为如下的6个图像:

然后,接下来对每个小图像,建立神经网络模型学习,建立的NN模型如下,先初步解释下为什么是这样,因为每个小图像的像素为:28 by 28 = 784,共784个像素点,每个像素点看做一个特征,对应一个输入神经元,至于中间的隐含层的个数,为15个,至于如何构造隐含层,隐含层的意义是什么,会在接下来谈,输出层为10个神经元,是因为0~9共10个数字。

2.2 训练神经网络

训练神经网络的过程,就是求解所有神经元的权重参数,每层网络的偏置量,这样就可以进行手写字的分类预测了,输入小图像5后,经过这套网络,可以得出数字分类为5吗?

2.3 梯度下降求权重参数和偏置量

昨天推导了梯度下降求权重参数和偏置量的过程,接下来,看看神经网络模型,求解手写字分类的详细过程。

2.4 代码实现

模块实现SGD的前向神经网络的学习算法,主函数为 SGD,里面涉及到后向传播求梯度的技术,详细研究这些代码对于深刻理解神经网络模型做分类任务有重大帮助。

import random

import numpy as np

classNetwork(object):

def__init__(self, sizes):

"""

参数,sizes : 神经网络的结构尺寸,是tuple,比如(3,2,1),

输入层为3个神经元,

中间层为2个神经元,

输出层为1个神经元

类内全局:sizes

biases:隐含层,输出层的偏置量

weights:各个神经元的权重参数,[[15 by 784],[10 by 15]]

"""

self.num_layers = len(sizes)

self.sizes = sizes

for x, y in zip(sizes[:-1], sizes[1:])]

deffeedforward(self, a):

"""

前向传播

a 是输入

返回神经网络的输出: sigmoid(w*a + b)

"""

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

a = sigmoid(np.dot(w, a)+b)

return a

defSGD(self, training_data, epochs, mini_batch_size, eta,

test_data=None):

"""

采用 mini-batch SGD 训练神经网络

training_data : [(x,y)],x 代表训练的输入, y 代表输出

epochs:比如,迭代100次为一波

mini_batch_size:批梯度下降,一次迭代,采用的样本个数,比如为10个样本

eta : 学习率

"""

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 xrange(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))

defupdate_mini_batch(self, mini_batch, eta):

"""

更新神经网络的权重(类内全局参数weights)和偏置量(类内全局参数:biases),

使用后传播的梯度下降方法,这个方法的核心是后传播算法backprop

mini_batch:[(x,y)],x是输入,y是输出

"""

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:

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)]

defbackprop(self, x, y):

"""

通过后向传播得出偏置量和权重参数的梯度方向,

返回值 ,biases:每层的偏置量的梯度

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

activations = [x]# 分层存储每层的激活节点

zs = []# 分层存储每层的 Z 向量

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

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

zs.append(z)

activation = sigmoid(z)

activations.append(activation)

# 后向传播

delta = self.cost_derivative(activations[-1], y) * \

sigmoid_prime(zs[-1])

nabla_b[-1] = delta

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

# L = 1 表示最后一层神经元, L = 2 倒数第二层神经元

for layer in range(2, self.num_layers):

z = zs[-layer]

sp = sigmoid_prime(z)

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

nabla_b[-layer] = delta

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

return (nabla_b, nabla_w)

defevaluate(self, test_data):

"""

输出层中,输出值最大的神经元对应的索引为分类,比如神经元5的激活值

最大,则认为输入的图像为5

"""

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)

defcost_derivative(self, output_activations, y):

"""

成本函数的导数

"""

return (output_activations-y)

defsigmoid(z):

"""The sigmoid 函数."""

return 1.0/(1.0+np.exp(-z))

defsigmoid_prime(z):

"""sigmoid 函数的导数"""

return sigmoid(z)*(1-sigmoid(z))

以上就是前向神经网络的后向传播梯度下降求解的完整代码。

03

深度学习的展望

手写字的数据集下载,请参考:

http://yann.lecun.com/exdb/mnist/

接下来,就是要加载数据集,然后调用02节中编写的SGD接口,进行手写字的三层神经网络的训练,那么,训练结果如何呢?

核心代码中后向传播算法的原理是怎么样的?

神经网络中的隐含层的意义是什么,当含有多层隐含层的神经网络时,这种网络的学习便是深度学习,预知,深度学习的隐含层如何一层一层的构建思路,接下来也会重点总结。

请记住:每天一小步,日积月累一大步!

《实例》阐述算法,通俗易懂,助您对算法的理解达到一个新高度。包含但不限于:经典算法,机器学习,深度学习,LeetCode 题解,Kaggle 实战。期待您的到来!

本文来自企鹅号 - 全球大搜罗媒体

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏wOw的Android小站

[深度学习]Charpter 9:卷积网络

卷积网络convolutional network,也叫做卷积神经网络convolutional neural network CNN 专门用来处理类似网格结构...

1301
来自专栏机器学习算法工程师

风格迁移原理及tensorflow实现-附代码

作者:刘威威 编辑:田 旭 前 言 本文将详细介绍 tf 实现风格迁移的小demo,看完这篇就可以去实现自己的风格迁移了,复现的算法来自论文 Percept...

1.9K8
来自专栏云时之间

深度学习与TensorFlow:理解卷积神经网络

1974
来自专栏机器人网

从零开始,了解元学习

传统的机器学习研究模式是:获取特定任务的大型数据集,然后用这个数据集从头开始训练模型。很明显,这和人类利用以往经验,仅仅通过少量样本就迅速完成学习的情况相差甚远...

1202
来自专栏磐创AI技术团队的专栏

支持向量机原理讲解(一)

1445
来自专栏企鹅号快讯

机器学习三人行-神奇的分类回归决策树

系列五我们一起学习并实战了支持向量机的分类和回归,见下面链接: 文末附代码关键字,回复即可下载。 今天,我们一起学习下决策树算法,该算法和SVM一样,既可以用来...

4925
来自专栏YoungGy

ML基石_10_LogisticRegression

logistic regression problem Y是概率的情况 相同数据不同目标函数 logis假设集 logistic regression erro...

2985
来自专栏杂文共赏

蚂蚁金服论文

通常,图表征学习的目标是学习一个函数:f(\mathcal{X},\mathcal{G}) ,利用\mathcal{G}空间中附加的图结构,而不是传统的只考虑f...

5637
来自专栏机器之心

入门 | 从零开始,了解元学习

3629
来自专栏ATYUN订阅号

在不同的任务中,我应该选择哪种机器学习算法?

当开始研究数据科学时,我经常面临一个问题,那就是为我的特定问题选择最合适的算法。在本文中,我将尝试解释一些基本概念,并在不同的任务中使用不同类型的机器学习算法。...

3313

扫码关注云+社区

领取腾讯云代金券