命名格式:按照课程网站中的课后作业要求


1. 根据Course02课程中对全连接神经网络的讲解,将缺失的全连接神经网络中代码块补全,并完成一次训练

需要填充的部分已经在第一部分的全连接神经网络代码中用红色的"""补全代码"""标示

2. 利用sklearn的指标评测函数得出模型在测试集上的性能

从sklearn官网上查找metrics子包中关于评价指标的计算函数,了解其用法,之后的课程中就用到。

【目录】

1. 手写数字识别数据集(MNIST)

2. 全连接神经网络


1. 手写数字识别数据集(MNIST)

## 引入python包,没有安装的请按照抛出的error通过conda来安装直至成功
import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline
import sklearn
from collections import defaultdict
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
import _pickle as cPickle
import gzip
import random
#  载入mnist数据
def load_data():"""Return the MNIST data as a tuple containing the training data,the validation data, and the test data.The ``training_data`` is returned as a tuple with two entries.The first entry contains the actual training images.  This is anumpy ndarray with 50,000 entries.  Each entry is, in turn, anumpy ndarray with 784 values, representing the 28 * 28 = 784pixels in a single MNIST image.The second entry in the ``training_data`` tuple is a numpy ndarraycontaining 50,000 entries.  Those entries are just the digitvalues (0...9) for the corresponding images contained in the firstentry of the tuple.The ``validation_data`` and ``test_data`` are similar, excepteach contains only 10,000 images.This is a nice data format, but for use in neural networks it'shelpful to modify the format of the ``training_data`` a little.That's done in the wrapper function ``load_data_wrapper()``, seebelow."""f = gzip.open('MNIST/mnist.pkl.gz', 'rb')#对压缩文件的读写操作training_data, validation_data, test_data = cPickle.load(f, encoding='bytes')#通过pickle读数据f.close()return (training_data, validation_data, test_data)def minist_loader():"""Return a tuple containing ``(training_data, validation_data,test_data)``. Based on ``load_data``, but the format is moreconvenient for use in our implementation of neural networks.In particular, ``training_data`` is a list containing 50,0002-tuples ``(x, y)``.  ``x`` is a 784-dimensional numpy.ndarraycontaining the input image.  ``y`` is a 10-dimensionalnumpy.ndarray representing the unit vector corresponding to thecorrect digit for ``x``.``validation_data`` and ``test_data`` are lists containing 10,0002-tuples ``(x, y)``.  In each case, ``x`` is a 784-dimensionalnumpy.ndarry containing the input image, and ``y`` is thecorresponding classification, i.e., the digit values (integers)corresponding to ``x``.Obviously, this means we're using slightly different formats forthe training data and the validation / test data.  These formatsturn out to be the most convenient for use in our neural networkcode."""tr_d, va_d, te_d = load_data()# cause the network's input is a vector 784X1, so we reshape the image so as to more convenient# 将二维图片748x1展平training_inputs = [np.reshape(x, (784, 1)) for x in tr_d[0]]training_results = [vectorized_result(y) for y in tr_d[1]]training_data = list(zip(training_inputs, training_results))# zip将两个list对应维度结成一个tuple,最后返回一个list,list元素为tuple# training_data为标签x和标签y一一对应的list,里面有50个元祖,每个元祖为(数组1,数组2),其中数组1为784x1validation_inputs = [np.reshape(x, (784, 1)) for x in va_d[0]]validation_data = list(zip(validation_inputs, va_d[1]))test_inputs = [np.reshape(x, (784, 1)) for x in te_d[0]]test_data = list(zip(test_inputs, te_d[1]))return (training_data, validation_data, test_data)def vectorized_result(j):"""Return a 10-dimensional unit vector with a 1.0 in the jthposition and zeroes elsewhere.  This is used to convert a digit(0...9) into a corresponding desired output from the neuralnetwork."""e = np.zeros((10, 1)) # 注意里面还有一个括号e[j] = 1.0return e
training_data, validation_data, test_data = minist_loader()
print(len(training_data[0][0]))
print(training_data[0][1])
print(len(training_data))
784
[[0.][0.][0.][0.][0.][0.][0.][0.][1.][0.]]
50000
print(training_data[1][1])
[[1.][0.][0.][0.][0.][0.][0.][0.][0.][0.]]
print(test_data[0][1])
7
fig, ax = plt.subplots(nrows=5, ncols=5, sharex='all', sharey='all')
# sharex,share可以选择"all""none""row""col"表示那些共享坐标
ax = ax.flatten()
# ax = ax.flatten()将ax由n*m的Axes组展平成1*nm的Axes组,后面可以使用ax[i]
for i in range(25):ax[i].set_title(int(test_data[i][1]))img = test_data[i][0].reshape(28, 28)ax[i].imshow(img, cmap='Greys', interpolation='nearest')# Axes包含了图形的大部分元素:轴,Tick、Line2D、Text、Polygon等,并设置坐标系。# interpolation设置插值
ax[0].set_xticks([])
# set_xtickes 设置标签
ax[0].set_yticks([])
plt.tight_layout()
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NEwNk8dx-1657905733115)(output_8_0.png)]

print("训练集个数:{} 验证集个数:{} 测试集个数:{}".format(len(training_data), len(validation_data), len(test_data)))
训练集个数:50000 验证集个数:10000 测试集个数:10000

2. 全连接神经网络(Full Connected Neural Network)

全连神经网络从前向后分为输入层 -> 隐藏层xM -> 输出层。如果网络共有N层的话,那么存在N-1个权重连接矩阵和N-1个对应的偏置向量,其维度分别为:

Wli∈Rli×li−1(1<li≤N)\large W^{l_i} \in R^{l_i \times l_{i-1}} \quad (1<l_i \leq N) Wli​∈Rli​×li−1​(1<li​≤N)

bli∈Rli(1<li≤N)\large b^{l_i} \in R^{l_i } \quad (1 < l_i \leq N) bli​∈Rli​(1<li​≤N)

全连接神经网络的构建分为前向传播和误差的反向传播,具体的过程如下图:


def sigmoid(z):"""Sigmoid激活函数定义"""return 1.0 / (1.0 + np.exp(-z))"""补全代码"""def sigmoid_prime(z):"""Sigmoid函数的导数,关于Sigmoid函数的求导可以自行搜索。"""return sigmoid(z) * (1 - sigmoid(z))"""补全代码"""
# Full Connected Network
class FCN(object):"""全连接网络的纯手工实现"""def __init__(self, sizes):""":param sizes: 是一个列表,其中包含了神经网络每一层的神经元的个数,列表的长度就是神经网络的层数。举个例子,假如列表为[784,30,10],那么意味着它是一个3层的神经网络,第一层包含784个神经元,第二层30个,最后一层10个。注意,神经网络的权重和偏置是随机生成的,使用一个均值为0,方差为1的高斯分布。注意第一层被认为是输入层,它是没有偏置向量b和权重向量w的。因为偏置只是用来计算第二层之后的输出"""self._num_layers = len(sizes) # 记录神经网络的层数# 为隐藏层和输出层生成偏置向量b,还是以[784,30,10]为例,那么一共会生成2个偏置向量b,分别属于隐藏层和输出层,大小分别为30x1,10x1。self._biases = [np.random.randn(y,1) for y in sizes[1:]]# 为隐藏层和输出层生成权重向量W, 以[784,30,10]为例,这里会生成2个权重向量w,分别属于隐藏层和输出层,大小分别是30x784, 10x30。self._weights = [np.random.randn(y,x) for x,y in zip(sizes[:-1],sizes[1:])]def feedforward(self, a):"""前向计算,返回神经网络的输出。公式如下:output = sigmoid(w*x+b)以[784,30,10]为例,权重向量大小分别为[30x784, 10x30],偏置向量大小分别为[30x1, 10x1]输入向量为 784x1.矩阵的计算过程为:30x784 * 784x1 = 30x130x1 + 30x1 = 30x110x30 * 30x1 = 10x110x1 + 10x1 = 10x1故最后的输出是10x1的向量,即代表了10个数字。:param a: 神经网络的输入"""for w, b in zip(self._weights, self._biases):"""补全代码"""z = np.dot(w,a) + ba = sigmoid(z)return adef train(self, training_data, epochs, mini_batch_size, eta, test_data=None):"""使用小批量随机梯度下降来训练网络:param training_data: training data 是一个元素为(x, y)元祖形式的列表,代表了训练数据的输入和输出。:param epochs: 训练轮次:param mini_batch_size: 小批量训练样本数据集大小:param eta: 学习率:param test_data: 如果test_data被指定,那么在每一轮迭代完成之后,都对测试数据集进行评估,计算有多少样本被正确识别了。但是这会拖慢训练速度。:return:"""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)# 如果test_data被指定,那么在每一轮迭代完成之后,都对测试数据集进行评估,计算有多少样本被正确识别了if test_data:print("Epoch %d: accuracy rate: %.2f%%" % (j, self.evaluate(test_data)/n_test*100))else:print("Epoch {0} complete".format(j))def update_mini_batch(self, mini_batch, eta):"""通过小批量随机梯度下降以及反向传播来更新神经网络的权重和偏置向量:param mini_batch: 随机选择的小批量:param eta: 学习率"""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:# 反向传播算法,运用链式法则求得对b和w的偏导"""补全代码"""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)) * nwfor w, nw in zip(self._weights, nabla_w)]self._biases = [b - (eta / len(mini_batch)) * nbfor b, nb in zip(self._biases, nabla_b)]def backprop(self, x, y):"""反向传播算法,计算损失对w和b的梯度:param x: 训练数据x:param y: 训练数据x对应的标签:return: Return a tuple ``(nabla_b, nabla_w)`` representing thegradient for the cost function C_x.  ``nabla_b`` and``nabla_w`` are layer-by-layer lists of numpy arrays, similarto ``self.biases`` and ``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# 一层一层存储全部激活值的列表activations = [x]# 一层一层存储全部的z向量,即带权输入zs = []for b, w in zip(self._biases, self._weights):# 利用 z = wt*x+b 依次计算网络的输出z = np.dot(w, activation) + bzs.append(z)# 将每个神经元的输出z通过激活函数sigmoidactivation = sigmoid(z)# 将激活值放入列表中暂存activations.append(activation)# 反向传播过程# 首先计算输出层的误差delta Ldelta = self.cost_derivative(activations[-1], y) * sigmoid_prime(zs[-1])# 反向存储 损失函数C对b的偏导数nabla_b[-1] = delta# 反向存储 损失函数C对w的偏导数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"""补全代码"""# len(delta)长度为上一层的元素个数,因此这里要对_weight转置delta = np.dot(self._weights[-l+1].transpose(),delta) * sp# 保存损失喊出C对b的偏导数,它就等于误差deltanabla_b[-l] = delta# 计算损失函数C对w的偏导数nabla_w[-l] = np.dot(delta, activations[-l - 1].transpose())# 返回每一层神经元的对b和w的偏导数return (nabla_b, nabla_w)def evaluate(self, test_data):"""返回神经网络对测试数据test_data的预测结果,并且计算其中识别正确的个数因为神经网络的输出是一个10x1的向量,我们需要知道哪一个神经元被激活的程度最大,因此使用了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)def cost_derivative(self, output_activations, y):"""返回损失函数对a的的偏导数,损失函数定义 C = 1/2*||y(x)-a||^2求导的结果为:C' = y(x) - a"""return (output_activations - y)
# 定义一个3层全连接网络,输入层有784个神经元,隐藏层30个神经元,输出层10个神经元
fc = FCN([784, 30,10])
# 设置迭代次数40次,mini-batch大小为10,学习率为3,并且设置测试集,即每一轮训练完成之后,都对模型进行一次评估。
# 这里的参数可以根据实际情况进行修改
fc.train(training_data, 5, 128, 5.0, test_data=test_data)
# training_data共50000数据,mini_batch_size为128为每次取出的训练数据
Epoch 0: accuracy rate: 72.73%
Epoch 1: accuracy rate: 86.06%
Epoch 2: accuracy rate: 88.20%
Epoch 3: accuracy rate: 89.27%
Epoch 4: accuracy rate: 90.30%

深度学习理论与实践第二章作业-FNN手写数字识别相关推荐

  1. 【机器学习/人工智能】 大作业:手写数字识别系统

    写在前面 参考的是https://zh.d2l.ai/index.html 一.大作业设计目的与要求 (1)利用所学习的聚类算法完成简单的图像分割系统. (2)编程并利用相关软件完成大作业测试,得到实 ...

  2. 深度学习笔记:01快速构建一个手写数字识别系统以及张量的概念

    深度学习笔记:01快速构建一个手写数字识别系统 神经网络代码最好运行在GPU中,但是对于初学者来说运行在GPU上成本太高了,所以先运行在CPU中,就是慢一些. 一.安装keras框架 使用管理员模式打 ...

  3. 深度学习入门项目:PyTorch实现MINST手写数字识别

    完整代码下载[github地址]:https://github.com/lmn-ning/MNIST_PyTorch.git 目录 一.MNIST数据集介绍及下载地址 二.代码结构 三.代码 data ...

  4. 深度学习之基于CNN实现汉字版手写数字识别(Chinese-Mnist)

    Mnist数据集是深度学习入门的数据集,昨天发现了Chinese-Mnist数据集,与Mnist数据集类似,只不过是汉字数字,例如'一'.'二'.'三'等,本次实验利用自己搭建的CNN网络实现Chin ...

  5. 深度学习案例之基于 CNN 的 MNIST 手写数字识别

    一.模型结构 本文只涉及利用Tensorflow实现CNN的手写数字识别,CNN的内容请参考:卷积神经网络(CNN) MNIST数据集的格式与数据预处理代码input_data.py的讲解请参考 :T ...

  6. 【项目实践】:KNN实现手写数字识别(附Python详细代码及注释)

    ↑ 点击上方[计算机视觉联盟]关注我们 本节使用KNN算法实现手写数字识别.KNN算法基本原理前边文章已经详细叙述,盟友们可以参考哦! 数据集介绍 有两个文件: (1)trainingDigits文件 ...

  7. 深度学习入门实例——基于keras的mnist手写数字识别

    本文介绍了利用keras做mnist数据集的手写数字识别. 参考网址 http://www.cnblogs.com/lc1217/p/7132364.html mnist数据集中的图片为28*28的单 ...

  8. 【FPGA教程案例100】深度学习1——基于CNN卷积神经网络的手写数字识别纯Verilog实现,使用mnist手写数字数据库

    FPGA教程目录 MATLAB教程目录 ---------------------------------------- 目录 1.软件版本 2.CNN卷积神经网络的原理 2.1 mnist手写数字数 ...

  9. 2.7mnist手写数字识别之训练调试与优化精讲(百度架构师手把手带你零基础实践深度学习原版笔记系列)

    2.7mnist手写数字识别之训练调试与优化精讲(百度架构师手把手带你零基础实践深度学习原版笔记系列) 目录 2.7mnist手写数字识别之训练调试与优化精讲(百度架构师手把手带你零基础实践深度学习原 ...

最新文章

  1. ua获取手机型号_取证人员为什么很难从移动设备上获取电子数据证据?
  2. IT项目管理总结:第一章 项目管理概述
  3. boost::hana::detail::any_of用法的测试程序
  4. html 适配 android,Android 版本适配 6~11
  5. 位运算在一类数组题中的用法 只出现一次的数字I
  6. 常见数据结构List之LinkedList
  7. WPFのclipToBounds与maskToBounds的区别
  8. mongodb的用法
  9. 启用windows功能NetFx3时出错的离线解决方案
  10. DjangoBook2.0 中文版:电子书
  11. linux命令du -sh,du命令_Linux du 命令用法详解:显示每个文件和目录的磁盘使用空间...
  12. 2021年什么邮箱最好用,这款电子邮箱让你的工作效率翻倍!
  13. Ubuntu16.04如何设置自动休眠时间
  14. $ is not a function
  15. px4在ubuntu中make px4fmu-v2_default upload上传失败
  16. 2022年全球市场机器视觉频闪仪总体规模、主要生产商、主要地区、产品和应用细分研究报告
  17. java+swagger+侵入,一种无侵入比swagger-ui兼容性更好更简单的API文档生成方案
  18. 学计算机需要记住的快捷键,这几个电脑快捷键必须会,快学!
  19. HTML样式表两个表格距离为零,css表格间距怎么调?
  20. c语言两位共阴数码管00,两位数码管动态显示C语言程序

热门文章

  1. java实现qq抢红包_java抢红包功能实现
  2. 如何将台式机的网络共享给另外一台台式机
  3. iphone型号表_苹果所有产品型号大全
  4. C#XML序列化特性全中文教程
  5. F280049C Crossbar X-BAR
  6. 提升个人效率减少焦虑——GTD法则
  7. html5的水墨画,PR怎么做水墨画效果
  8. Java程序设计——随机点名器
  9. 四川泡菜中的亚硝酸盐如何变化
  10. 计算机科学与技术研究生推荐读物,2017年中山大学0812计算机科学与技术考研参考书目推荐...