全栈工程师开发手册 (作者:栾鹏)

python教程全解

FC全连接神经网络的理论教程参考
http://blog.csdn.net/luanpeng825485697/article/details/79009223

加载样本数据集

首先我们要有手写体的数据集文件

t10k-images.idx3-ubyte

t10k-labels.idx1-ubyte

train-images.idx3-ubyte

train-labels.idx1-ubyte

我们实现一个MNIST.py文件,专门用来读取手写体文件中的数据。

# -*- coding: UTF-8 -*-# 获取手写数据。
# 28*28的图片对象。每个图片对象根据需求是否转化为长度为784的横向量
# 每个对象的标签为0-9的数字,one-hot编码成10维的向量
import numpy as np# 数据加载器基类。派生出图片加载器和标签加载器
class Loader(object):# 初始化加载器。path: 数据文件路径。count: 文件中的样本个数def __init__(self, path, count):self.path = pathself.count = count# 读取文件内容def get_file_content(self):print(self.path)f = open(self.path, 'rb')content = f.read()  # 读取字节流f.close()return content  # 字节数组# 将unsigned byte字符转换为整数。python3中bytes的每个分量读取就会变成int# def to_int(self, byte):#     return struct.unpack('B', byte)[0]# 图像数据加载器
class ImageLoader(Loader):# 内部函数,从文件字节数组中获取第index个图像数据。文件中包含所有样本图片的数据。def get_picture(self, content, index):start = index * 28 * 28 + 16  # 文件头16字节,后面每28*28个字节为一个图片数据picture = []for i in range(28):picture.append([])  # 图片添加一行像素for j in range(28):byte1 = content[start + i * 28 + j]picture[i].append(byte1)  # python3中本来就是int# picture[i].append(self.to_int(byte1))  # 添加一行的每一个像素return picture   # 图片为[[x,x,x..][x,x,x...][x,x,x...][x,x,x...]]的列表# 将图像数据转化为784的行向量形式def get_one_sample(self, picture):sample = []for i in range(28):for j in range(28):sample.append(picture[i][j])return sample# 加载数据文件,获得全部样本的输入向量。onerow表示是否将每张图片转化为行向量def load(self,onerow=False):content = self.get_file_content()  # 获取文件字节数组data_set = []for index in range(self.count):  #遍历每一个样本onepic =self.get_picture(content, index)  # 从样本数据集中获取第index个样本的图片数据,返回的是二维数组if onerow: onepic = self.get_one_sample(onepic)  # 将图像转化为一维向量形式data_set.append(onepic)return data_set# 标签数据加载器
class LabelLoader(Loader):# 加载数据文件,获得全部样本的标签向量def load(self):content = self.get_file_content()   # 获取文件字节数组labels = []for index in range(self.count):  #遍历每一个样本onelabel = content[index + 8]   # 文件头有8个字节onelabelvec = self.norm(onelabel) #one-hot编码labels.append(onelabelvec)return labels# 内部函数,one-hot编码。将一个值转换为10维标签向量def norm(self, label):label_vec = []# label_value = self.to_int(label)label_value = label  # python3中直接就是intfor i in range(10):if i == label_value:label_vec.append(0.9)else:label_vec.append(0.1)return label_vec# 获得训练数据集。onerow表示是否将每张图片转化为行向量
def get_training_data_set(num,onerow=False):image_loader = ImageLoader('train-images.idx3-ubyte', num)  # 参数为文件路径和加载的样本数量label_loader = LabelLoader('train-labels.idx1-ubyte', num)  # 参数为文件路径和加载的样本数量return image_loader.load(onerow), label_loader.load()# 获得测试数据集。onerow表示是否将每张图片转化为行向量
def get_test_data_set(num,onerow=False):image_loader = ImageLoader('t10k-images.idx3-ubyte', num)  # 参数为文件路径和加载的样本数量label_loader = LabelLoader('t10k-labels.idx1-ubyte', num)  # 参数为文件路径和加载的样本数量return image_loader.load(onerow), label_loader.load()# 将一行784的行向量,打印成图形的样式
def printimg(onepic):onepic=onepic.reshape(28,28)for i in range(28):for j in range(28):if onepic[i,j]==0: print('  ',end='')else: print('* ',end='')print('')if __name__=="__main__":train_data_set, train_labels = get_training_data_set(100)  # 加载训练样本数据集,和one-hot编码后的样本标签数据集train_data_set = np.array(train_data_set)train_labels = np.array(train_labels)onepic = train_data_set[12]  # 取一个样本printimg(onepic)  # 打印出来这一行所显示的图片print(train_labels[12].argmax())  # 打印样本标签

我们尝试运行一下。读取第13个样本的内容。

可以看到打印输出样式如下。

建立全连接网络模块

我们使用以下代码实现全连接网络模型,存储为DNN.py

# 实现神经网络反向传播算法,以此来训练网络
# 所谓向量化编程,就是使用矩阵运算。import random
import numpy as np
import datetime# 1. 当为array的时候,默认d*f就是对应元素的乘积,multiply也是对应元素的乘积,dot(d,f)会转化为矩阵的乘积, dot点乘意味着相加,而multiply只是对应元素相乘,不相加
# 2. 当为mat的时候,默认d*f就是矩阵的乘积,multiply转化为对应元素的乘积,dot(d,f)为矩阵的乘积# Sigmoid激活函数类
class SigmoidActivator(object):def forward(self, weighted_input): #前向传播计算输出return 1.0 / (1.0 + np.exp(-weighted_input))def backward(self, output):  #后向传播计算导数return np.multiply(output,(1 - output))   # 对应元素相乘# 全连接每层的实现类。输入对象x、神经层输出a、输出y均为列向量
class FullConnectedLayer(object):# 构造函数。input_size: 本层输入向量的维度。output_size: 本层输出向量的维度。activator: 激活函数def __init__(self, input_size, output_size,activator):self.input_size = input_sizeself.output_size = output_sizeself.activator = activator# 权重数组Wself.W = np.random.uniform(-0.1, 0.1,(output_size, input_size))  #初始化为-0.1~0.1之间的数。权重的大小。行数=输出个数,列数=输入个数。a=w*x,a和x都是列向量# 偏置项bself.b = np.zeros((output_size, 1))  # 全0列向量偏重项# 输出向量self.output = np.zeros((output_size, 1)) #初始化为全0列向量# 前向计算,预测输出。input_array: 输入向量,维度必须等于input_sizedef forward(self, input_array):   # 式2self.input = input_arrayself.output = self.activator.forward(np.dot(self.W, input_array) + self.b)# 反向计算W和b的梯度。delta_array: 从上一层传递过来的误差项。列向量def backward(self, delta_array):# 式8self.delta = np.multiply(self.activator.backward(self.input),np.dot(self.W.T, delta_array))   #计算当前层的误差,已被上一层使用self.W_grad = np.dot(delta_array, self.input.T)   # 计算w的梯度。梯度=误差.*输入self.b_grad = delta_array  #计算b的梯度# 使用梯度下降算法更新权重def update(self, learning_rate):self.W += learning_rate * self.W_gradself.b += learning_rate * self.b_grad# 神经网络类
class Network(object):# 初始化一个全连接神经网络。layers:数组,描述神经网络每层节点数。包含输入层节点个数、隐藏层节点个数、输出层节点个数def __init__(self, layers):self.layers = []for i in range(len(layers) - 1):self.layers.append(FullConnectedLayer(layers[i], layers[i+1],SigmoidActivator()))   # 创建全连接层,并添加到layers中# 训练函数。labels: 样本标签矩阵。data_set: 输入样本矩阵。rate: 学习速率。epoch: 训练轮数def train(self, labels, data_set, rate, epoch):for i in range(epoch):for d in range(len(data_set)):# print(i,'次迭代,',d,'个样本')oneobject = np.array(data_set[d]).reshape(-1,1)   #将输入对象和输出标签转化为列向量onelabel = np.array(labels[d]).reshape(-1,1)self.train_one_sample(onelabel,oneobject, rate)# 内部函数,用一个样本训练网络def train_one_sample(self, label, sample, rate):# print('样本:\n',sample)self.predict(sample)  # 根据样本对象预测值self.calc_gradient(label) # 计算梯度self.update_weight(rate) # 更新权重# 使用神经网络实现预测。sample: 输入样本def predict(self, sample):sample = sample.reshape(-1,1)   #将样本转换为列向量output = sample  # 输入样本作为输入层的输出for layer in self.layers:# print('权值:',layer.W,layer.b)layer.forward(output)  # 逐层向后计算预测值。因为每层都是线性回归output = layer.output# print('预测输出:', output)return output# 计算每个节点的误差。label为一个样本的输出向量,也就对应了最后一个所有输出节点输出的值def calc_gradient(self, label):# print('计算梯度:',self.layers[-1].activator.backward(self.layers[-1].output).shape)delta = np.multiply(self.layers[-1].activator.backward(self.layers[-1].output),(label - self.layers[-1].output))  #计算输出误差# print('输出误差:', delta.shape)for layer in self.layers[::-1]:layer.backward(delta)   # 逐层向前计算误差。计算神经网络层和输入层误差delta = layer.delta# print('当前层误差:', delta.shape)return delta# 更新每个连接权重def update_weight(self, rate):for layer in self.layers:  # 逐层更新权重layer.update(rate)# ====================================以上为网络的类构建=================================
# ====================================以下为网络的应用=================================# 根据返回结果计算所属类型
def valye2type(vec):return vec.argmax(axis=0)   # 获取概率最大的分类,由于vec是列向量,所以这里按列取最大的位置# 使用错误率来对网络进行评估
def evaluate(network, test_data_set, test_labels):error = 0total = test_data_set.shape[0]for i in range(total):label = valye2type(test_labels[i])predict = valye2type(network.predict(test_data_set[i]))if label != predict:error += 1return float(error) / float(total)# 由于使用了逻辑回归函数,所以只能进行分类识别。识别ont-hot编码的结果
if __name__ == '__main__':# 使用神经网络实现and运算data_set = np.array([[0,0],[0,1],[1,0],[1,1]])labels = np.array([[1,0],[1,0],[1,0],[0,1]])# print(data_set)# print(labels)net = Network([2,1,2])  # 输入节点2个(偏量b会自动加上),神经元1个,输出节点2个。net.train(labels, data_set, 2, 100)for layer in net.layers:  # 网络层总不包含输出层print('W:',layer.W)print('b:',layer.b)# 对结果进行预测sample = np.array([[1,1]])result = net.predict(sample)type = valye2type(result)print('分类:',type)

训练手写体识别网络模型

# 使用全连接神经网络类,和手写数据加载器,实现验证码识别。import datetime
import numpy as np
import DNN   # 引入全连接神经网络
import MNIST  # 引入手写数据加载器# 最后实现我们的训练策略:每训练10轮,评估一次准确率,当准确率开始下降时终止训练
def train_and_evaluate():last_error_ratio = 1.0epoch = 0train_data_set, train_labels = MNIST.get_training_data_set(6000,True)   # 加载训练样本数据集,和one-hot编码后的样本标签数据集test_data_set, test_labels = MNIST.get_test_data_set(1000,True)   # 加载测试特征数据集,和one-hot编码后的测试标签数据集train_data_set=np.array(train_data_set)train_labels=np.array(train_labels)test_data_set=np.array(test_data_set)test_labels=np.array(test_labels)print('样本数据集的个数:%d' % len(train_data_set))print('测试数据集的个数:%d' % len(test_data_set))network = DNN.Network([784, 300, 10])  # 定义一个输入节点784+1,神经元300,输出10while True:  # 迭代至准确率开始下降epoch += 1 # 记录迭代次数network.train(train_labels, train_data_set, 0.3, 1)  # 使用训练集进行训练。0.3为学习速率,1为迭代次数print('%s epoch %d finished' % (datetime.datetime.now(), epoch))  # 打印时间和迭代次数if epoch % 10 == 0:  # 每训练10次,就计算一次准确率error_ratio = DNN.evaluate(network, test_data_set, test_labels)  # 计算准确率print('%s after epoch %d, error ratio is %f' % (datetime.datetime.now(), epoch, error_ratio))  # 打印输出错误率if error_ratio < 0.1:  # 如果错误率开始上升就不再训练了。breakelse:print('错误率:', last_error_ratio)last_error_ratio = error_ratio # 否则继续训练index=0for layer in network.layers:np.savetxt('MNIST—W'+str(index),layer.W)np.savetxt('MNIST—b' + str(index), layer.b)index+=1print(layer.W)print(layer.b)if __name__ == '__main__':train_and_evaluate()   # 使用样本数据集进行预测

由于样本数据集非常大,所以训练速度非常慢。尝试了以下,6000个样本训练一次需要14s。

python神经网络案例——FC全连接神经网络实现mnist手写体识别相关推荐

  1. 深度学习——神经网络之DNN全连接神经网络、BP算法原理

    深度学习--神经网络之DNN全连接神经网络.BP算法原理 深度学习--神经网络之DNN全连接神经网络.BP算法原理 1.啥是人工神经网络 2.神经网络的应用 3.神经网络的组成 3.1.神经元 3.2 ...

  2. [转载] python bp神经网络 mnist_Python利用全连接神经网络求解MNIST问题详解

    参考链接: Python中的单个神经元神经网络 本文实例讲述了Python利用全连接神经网络求解MNIST问题.分享给大家供大家参考,具体如下: 1.单隐藏层神经网络 人类的神经元在树突接受刺激信息后 ...

  3. 2021年人工神经网络第四次作业 - 第二题MNIST手写体识别

    简 介: ※MNIST数据集合是深度学习基础训练数据集合.改数据集合可以使用稠密前馈神经网络训练,也可以使用CNN.本文采用了单隐层BP网络和LeNet网络对于MNIST数据集合进行测试.实验结果标明 ...

  4. [Python人工智能] 六.TensorFlow实现分类学习及MNIST手写体识别案例

    从本专栏开始,作者正式开始研究Python深度学习.神经网络及人工智能相关知识.前一篇文章讲解了Tensorboard可视化的基本用法,并绘制整个神经网络及训练.学习的参数变化情况:本篇文章将通过Te ...

  5. 【DL】基于pytorch搭建BP神经网络/人工神经网络/多层感知机/全连接神经网络的鸢尾花分类

    目录 1.介绍 2.数据 3.模型 4.完整代码 1.介绍 鸢尾(学名:Iris tectorum Maxim. )又名:蓝蝴蝶.紫蝴蝶.扁竹花等,属百合目.鸢尾科.鸢尾属多年生草本,根状茎粗壮,直径 ...

  6. 【FPGA】基于HLS的全连接神经网络手写体识别

    目录 一 系统分析 1.1 全连接神经网络简介 二 通过HLS 编写全连接神经网络传入权重参数和偏置参数文件 2.1  获得图片.权重以及偏置的参数 2.2 编写C语言的全连接算子 2.3 Slave ...

  7. 全连接神经网络_【模型解读】从“局部连接”回到“全连接”的Non-Local神经网络...

    文章首发于<有三AI> [模型解读]从"局部连接"回到"全连接"的神经网络​mp.weixin.qq.com 这是深度学习模型解读第9篇,本篇我们简 ...

  8. 第五章 全连接神经网络

    第五章 全连接神经网络 1.1 全连接神经网络 人工神经网络(Artificial Neural Network)可以对一组输入信号和一组输出信号之间的关系进行建模,是机器学习和认知科学中的一种模仿生 ...

  9. 几种主要的神经网络----全连接神经网络、前馈神经网络、卷积神经网络、循环神经网络

    几种主要的神经网络 一.全连接神经网络 二.前馈神经网络(Feedforward neural network,FNN) 三.卷积神经网络(Convolutional Neural Network,C ...

最新文章

  1. 虚拟机中的黑苹果系统经常卡死_程序员吐槽macOS 10.15系统:破坏SSH默认规则
  2. tkinter python 句柄_微云收藏 python tkinter.after
  3. #Java小案例 随机产生数
  4. python 字典和列表的遍历
  5. java day44【JQuery 基础:概念,快速入门,JQuery对象和JS对象区别与转换,选择器,DOM操作,案例】...
  6. 谁设计python_如果你有设计师朋友,请对TA好一些...
  7. 1156 Sexy Primes (20 point(s)) PAT 素数
  8. Fragment isAdded() returns false on an already added Fragment
  9. tcprewrite批量修改报文ip地址一
  10. SPSS教程——进行数据的纵向和横向合并
  11. 如何看待越来越多人报名参加软考?
  12. winform直接控制云台_手机云台选购指南丨拍短视频Vlog有必要买手机云台吗?什么样的手机云台值得推荐?...
  13. 华为magicbook2019锐龙 无线网卡驱动下载
  14. anaconda 安装tensorflow1.9
  15. arduino编程时加{}报错_Arduino 程序数学运算
  16. 2021鸿蒙系统什么时候上线 鸿蒙支持哪些手机使用
  17. 生活中接口Java_Java接口实现
  18. 流量卡之家:苹果下周发布新品 不支持5G的iphone11你会买吗?
  19. 【MySQL】数据库 -- 多表查询
  20. C++面向对象的三大特性

热门文章

  1. automake 框架_[]GNU_Automake_中文.pdf
  2. 从今天起开始进一步学习前端
  3. Node-Promise
  4. Hbuilder 屏幕放大缩小
  5. Koa中使用art-template模板引擎,以及如何接受post请求等
  6. vue3.0新特性及用法
  7. 动态规划经典问题:背包问题
  8. 用数组建立二叉树(LeetCode二叉树测试)
  9. 支持Linux系统恢复工具,12款Linux系统恢复工具
  10. 购物车ajax php json,Ajax+json实现购物车结算