在前面两篇文章介绍了深度学习的一些基本概念,本文则使用Python实现一个简单的深度神经网络,并使用MNIST数据库进行测试。
神经网络的实现,包括以下内容:

  • 神经网络权值的初始化
  • 正向传播
  • 误差评估
  • 反向传播
  • 更新权值

主要是根据反向传播的4个基本方程,利用Python实现神经网络的反向传播。

初始化

首先定义代表神经网络的类NeuralNetwork,

class NeuralNetwork:def __init__(self,layers,alpha=0.1):self.W = []self.layers = layersself.alpha = alpha

有三个属性,

  • W存储各个层之间的权值矩阵,也是神经网络要更新学习的
  • layers 神经网络的结构,例如: [2,2,1]表示输入层有2个神经元,隐藏层2个神经元,输出层只有1个神经元。
  • alpha 学习速率

接下来初始化各个层之间的权值矩阵

for i in np.arange(0,len(layers) - 2):w = np.random.randn(layers[i] + 1,layers[i + 1] + 1)self.W.append(w / np.sqrt(layers[i]))

注意上面生成权值矩阵的大小layers[i] + 1,layers[i + 1] + 1,都加了1。 这是将神经元的偏置和权值统一的放到了权值矩阵里面。
\[ \left[ \begin{array}{c}w_{11} & w_{12} \\ w_{21} & w_{22}\end{array} \right] \cdot \left[\begin{array}{c}x_1 \\ x_2\end{array}\right] + \left[\begin{array}{c}b_1 \\ b_2\end{array}\right] = \left[\begin{array}{c}w_{11}x_1 + w{12}x_2 + b_1 \\ w_{21}x_1 + w_{22}x_2 + b_2 \end{array}\right] \]

可以将上式写成齐次的形式
\[ \left[ \begin{array}{c}w_{11} & w_{12} & b_1 \\ w_{21} & w_{22} &b_2 \end{array} \right] \cdot \left[\begin{array}{c}x_1 \\ x_2 \\ 1\end{array}\right] \]

使用统一的矩阵运算,在正向反向传播的时候更方便。

在输出层的神经元并没有偏置,所以要单独初始化输出层的权值矩阵

        w = np.random.randn(layers[-2] + 1,layers[-1])self.W.append(w / np.sqrt(layers[-2]))

下面实现Python的magic function __repr__输出神经网络结构

    def __repr__(self):return "NeuralNetWork:{}".format("-".join(str(l) for l in self.layers))

激活函数

在神经网络中使用sigmoid作为激活函数,实现sigmoid及其导数

    def sigmoid(self,x):return 1.0 / (1 + np.exp(-x))def sigmoid_deriv(self,x):return x * (1 - x)

正向反向传播

这一部分是神经的网络的核心了。下面实现fit方法,在方法中完成神经网络权值更新(训练)的过程。

    def fit(self,X,y,epochs=1000,displayUpdate=100):X = np.c_[X,np.ones((X.shape[0]))]for epoch in np.arange(0,epochs):for(x,target) in zip(X,y):self.fit_partial(x,target)# check to see if we should display a training updateif epoch == 0 or (epoch + 1) % displayUpdate == 0:loss = self.calculate_loss(X,y)print("[INFO] epoch={},loss={:.7f}".format(epoch + 1,loss))

该函数有4个参数:

  • X是输入的样本数据
  • y是样本的真是值
  • epochs训练的轮数
  • displayUpdate 输出训练的loss值。

X = np.c_[X,np.ones((X.shape[0]))]将输入训练的样本表示为齐次向量(也就是在末尾添1)。fit_partial是对输入的每个样本进行训练,包括正向传播,反向传播以及权值的更新。

    def fit_partial(self,x,y):A = [np.atleast_2d(x)]# 正向传播# 层层之间的数据传递for layer in np.arange(0,len(self.W)):# 输入经过加权以及偏置后的值net = A[layer].dot(self.W[layer])# 神经元的输出out = self.sigmoid(net)# 保存下来,反向传播的时候使用A.append(out)

上面完成了神经玩过的正向传播过程,下面根据反向传播的4个基本方程进行反向传播。
首先根据\(BP1\),
\[ \delta^L = \frac{\partial e}{\partial a^L} \odot \sigma'(z^L) \tag{BP1} \]
计算输出层的误差\(\delta^L\)

        error = A[-1] - y # 输出层的误差,均值方差作为损失函数D = [error * self.sigmoid_deriv(A[-1])]

得到输出层的误差D后,根据\(BP2\)计算各个层的误差
\[ \delta^{L-1} = (W^L)^T\delta^L \odot \sigma'(z^{L-1}) \tag{BP2} \]

        for layer in np.arange(len(A) - 2,0 ,-1):delta = D[-1].dot(self.W[layer].T)delta = delta * self.sigmoid_deriv(A[layer])D.append(delta)D = D[::-1]

D反转,和各个层的索引对应起来,下面根据\(BP3,BP4\)计算权值矩阵和偏置的导数
\[ \frac{\partial e}{b_j^l} = \delta_j^l \tag{BP3} \]
\[ \frac{\partial e}{w_{jk}^l} = \delta_j^l a_k^{l-1} \tag{BP4} \]

        for layer in np.arange(0,len(self.W)):self.W[layer] += -self.alpha * A[layer].T.dot(D[layer])

首先求得权值和偏置的导数(权值和偏置统一到同一个矩阵中)A[layer].T.dot(D[layer],然后将梯度乘以学习速率alpha 每次权值减小的步长。

上述就完成利用反向传播算法更新权值的过程。 关于反向传播四个基本方程的推导过程,可以参考文章深度学习与计算机视觉: 搞懂反向传播算法的四个基本方程

误差评估

上面代码已经实现了深度学习的训练过程,下面实现predict输出使用训练好的模型预测的结果,calculate_loss评估训练后模型的评估

    def predict(self,X,addBias=True):p = np.atleast_2d(X)if addBias:p = np.c_[p,np.ones((p.shape[0]))]for layer in np.arange(0,len(self.W)):p = self.sigmoid(np.dot(p,self.W[layer]))return p def calculate_loss(self,X,targets):targets = np.atleast_2d(targets)predictions = self.predict(X,addBias=False)loss = 0.5 * np.sum((predictions - targets) ** 2)return loss 

MNIST分类识别

使用上面实现的深度神经网络对MNIST手写体进行识别,首先导入必要的包

import NeuralNetwork
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn import datasets

需要使用sklearn包中的一些工具,进行数据的处理。

# load MNIST数据集,并使用min/max对数据进行归一化
digits = datasets.load_digits()
data = digits.data.astype("float")
data = (data - data.min()) / (data.max() - data.min())print("[INFO] samples: {}, dim: {}".format(data.shape[0], data.shape[1]))

将数据拆分为训练集和测试集,并对MNIST的类别进行编码

(trainX, testX, trainY, testY) = train_test_split(data, digits.target, test_size=0.25)# convert the labels from integers to vectors
trainY = LabelBinarizer().fit_transform(trainY)
testY = LabelBinarizer().fit_transform(testY)

下面构建神经网络结构,并使用训练集进行训练

nn = NeuralNetwork([data.shape[1], 32,16, 10])print ("[INFO] {}".format(nn))nn.fit(trainX, trainY, epochs=1000)

神经网络结构为:64-32-16-10,其中64为输入数据的大小,10输出类别的个数。

最后评估训练得到的模型

predictions = nn.predict(testX)print(classification_report(testY.argmax(axis=1), predictions.argmax(axis=1)))

最终的输出结果:

[INFO] loading MNIST (sample) dataset...
[INFO] samples: 1797, dim: 64
[INFO] training network...
[INFO] NeuralNetWork:64-32-16-10
[INFO] epoch=1,loss=607.1711647
[INFO] epoch=100,loss=7.1082795
[INFO] epoch=200,loss=4.0731690
[INFO] epoch=300,loss=3.1401868
[INFO] epoch=400,loss=2.8801101
[INFO] epoch=500,loss=1.8738122
[INFO] epoch=600,loss=1.7461474
[INFO] epoch=700,loss=1.6624043
[INFO] epoch=800,loss=1.1852884
[INFO] epoch=900,loss=0.6710255
[INFO] epoch=1000,loss=0.6336826
[INFO] evaluating network...precision    recall  f1-score   support0       1.00      0.95      0.97        391       0.84      1.00      0.92        382       1.00      0.98      0.99        413       0.93      0.98      0.95        524       0.91      0.97      0.94        405       0.98      0.98      0.98        416       1.00      0.96      0.98        517       1.00      0.98      0.99        488       0.98      0.89      0.93        559       0.98      0.93      0.95        45micro avg       0.96      0.96      0.96       450macro avg       0.96      0.96      0.96       450
weighted avg       0.96      0.96      0.96       450

如上测试结果,在测试集的上表现还算不错。

总结

本文使用Python简单的实现了一个神经网络。 主要是利用反向传播的4个基本方程,实现反向传播算法,更新各个神经元的权值。 最后使用该网络,对MNIST数据进行识别分类。

上面实现的神经网络只是“玩具”,用以加深对深度学习的训练过程以及反向传播算法的理解。后面将使用Keras和PyTorch来构建神经网络。

本文代码在git库 https://github.com/brookicv/machineLearningSample

深度学习与计算机视觉:基于Python的神经网络的实现相关推荐

  1. 【深度学习入门:基于Python的理论与实现】书本学习笔记 第三章 神经网络

    文章目录 1. 阶跃函数的实现 2. 函数图形 2.1 阶跃函数 2.2 sigmoid 函数 2.3 ReLU 函数 3. 多维数组的运算 3.1 矩阵乘法 3.2 神经网络的内积 4. 三层神经网 ...

  2. 深度学习与计算机视觉教程(11) | 循环神经网络及视觉应用(CV通关指南·完结)

    作者:韩信子@ShowMeAI 教程地址:https://www.showmeai.tech/tutorials/37 本文地址:https://www.showmeai.tech/article-d ...

  3. 学习《深度学习入门:基于Python的理论与实现》高清中文版PDF+源代码

    入门神经网络深度学习,推荐学习<深度学习入门:基于Python的理论与实现>,这本书不来虚的,一上来就是手把手教你一步步搭建出一个神经网络,还能把每一步的出处讲明白.理解神经网络,很容易就 ...

  4. 深度学习入门:基于Python的理论与实现①

    深度学习入门:基于Python的理论与实现① 机器学习的三大要素 第一章python入门 1.Numpy 1.1.numpy的N维数组 1.2.numpy广播 1.3访问元素 2.Matplotlib ...

  5. 读书笔记:《深度学习入门:基于python的理论与实现》

    基于python的深度学习入门 <Deep Learning from Scratch> 这是本人在关于深度学习领域所阅读的第一本书,即日本程序员斋藤康毅著,陆宇杰译作的<深度学习入 ...

  6. 深度学习与计算机视觉系列(8)_神经网络训练与注意点

    深度学习与计算机视觉系列(8)_神经网络训练与注意点 作者:寒小阳  时间:2016年1月.  出处:http://blog.csdn.net/han_xiaoyang/article/details ...

  7. 将MNIST手写数字数据集导入NumPy数组(《深度学习入门:基于Python的理论与实现》实践笔记)

    将MNIST手写数字数据集导入NumPy数组(<深度学习入门:基于Python的理论与实现>实践笔记) 一.下载MNIST数据集(使用urllib.request.urlretrieve( ...

  8. 《深度学习入门:基于Python的理论与实现》读书笔记:第8章 深度学习

    目录 8.1 加深网络 8.1.1 向更深的网络出发 8.1.2 进一步提高识别精度 8.1.3 加深层的动机 8.2 深度学习的小历史 8.2.1 ImageNet ​8.2.2 VGG 8.2.3 ...

  9. 深度学习入门:基于Python的理论与实现③

    第六章 与学习相关的技巧 本章将介绍神经网络的学习中的一些重要观点,主题涉及寻找最优权重参数的最优化方法.权重参数的初始值.超参数的设定方法等.此外,为了应对过拟合,本章还将介绍权值衰减.Dropou ...

  10. python2.7交通标志识别图_(四)深度学习初探:基于LeNet-5卷积神经网络的交通标志识别...

    1.项目任务 在常见深度学习模型的基础上(本文为LeNet-5),调整模型结构和参数,使用Tensorflow进行部署.利用公开的德国交通标志数据集进行训练,得到模型,并利用该模型对新的图片进行预测. ...

最新文章

  1. DevOps简单介绍
  2. leetcode-237-删除链表中的节点
  3. java mongodb 删除字段类型_Mongodb基本数据类型、常用命令之增加、更新、删除
  4. [转]C#网络编程(同步传输字符串) - Part.2
  5. PHP分组聊天室--fooking现实
  6. Android系统音量范围0-100,步进值5(十三)
  7. iar c语言单片机指针,51单片机IAR编程示例
  8. 《思考,快与慢》读书笔记
  9. iOS 友盟分享总结
  10. java基本数据类型范围
  11. 南邮历午计算机复试题,南京邮电大学2011年考研计算机复试流程
  12. WIN10计算机不支持3D游戏怎么办,教你如何在win10系统中开启3D加速?
  13. c语言按一个按钮弹出窗口,实现点击按钮,弹出输入框的内容
  14. linux安装wine
  15. 京东客小程序功能模块源码V6.0.2
  16. 8个国外开放的硕博论文、期刊、数据库下载网站-转
  17. 光滑的圆环(glossy torus)
  18. 路由器工作原理及配置实验
  19. JAVA中下载文件名含有中文乱码一种少见的解决方案
  20. 冰河的高并发电子书开源啦(文末免费领取)!!

热门文章

  1. java io 文件复制_实例讲述Java IO文件复制
  2. MySQL设计一个图书馆数据库_请设计一个图书馆数据库
  3. 深度优先遍历_二叉树的深度优先遍历,理解框架真的能够套用题目吗?不了解执行过程可能很难。...
  4. java s0 s1_Java GC 变量含义(S0 S1 E O P YGC YGCT FGC FGCT GCT)详解
  5. 计算机话筒接口,电脑麦克风插口是哪个哪位知道?
  6. 划分微型计算机的标志是,划分微型计算机的标志为
  7. 申报成功后怎样修改_【小白教程】12月第3期《申报成功后,如何更正,快快收藏!》...
  8. 关于Nginx的使用
  9. 2021年第十六届全国大学生智能汽车竞赛赛道铺设规范
  10. SH-20403AXIS12双轴蓝牙移动框架