2.神经网络的实现

创建神经网络类

import numpy
# scipy.special包含S函数expit(x)
import scipy.special
# 打包模块
import pickle# 激活函数
def activation_func(x):return scipy.special.expit(x)# 用于创建、 训练和查询3层神经网络
class neuralNetwork:# 初始化神经网络def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):# 设置 输入层, 隐藏层, 输出层 结点个数self.inodes = inputnodesself.hnodes = hiddennodesself.onodes = outputnodes# 两个链接权重矩阵 wih, who# w11 w21# w12 w22 etcself.wih = numpy.random.normal(0.0, pow(self.hnodes, -0.5), (self.hnodes, self.inodes))self.who = numpy.random.normal(0.0, pow(self.onodes, -0.5), (self.onodes, self.hnodes))# 学习率self.lr = learningrate# 激活函数是S函数,使用lambda定义函数# self.activation_function = lambda x: scipy.special.expit(x)# 使用lambda定义函数时无法打包保存神经网络对象self.activation_function = activation_funcpass# 训练神经网络def train(self, inputs_list, targets_list):# 使用完全相同的方式从输入层前馈信号到最终输出层,因此代码几乎与query()相同inputs = numpy.array(inputs_list, ndmin=2).T# 使用包含期望值训练样本来训练网络targets = numpy.array(targets_list, ndmin=2).Thidden_inputs = numpy.dot(self.wih, inputs)hidden_outputs = self.activation_function(hidden_inputs)final_inputs = numpy.dot(self.who, hidden_outputs)# 此处的final_outputs和上面的hidden_outputs都经过了激活函数,后面更新权重时不需要再代入了final_outputs = self.activation_function(final_inputs)# 期望矩阵和输出矩阵相减获得误差矩阵output_errors = targets - final_outputs# 根据所连接的权重分割误差,为每个隐藏层结点重组这些误差hidden_errors = numpy.dot(self.who.T, output_errors)# 应用更新权重的矩阵形式表达式# 学习率*误差Ek*sigmoid(输出Ok)*(1-sigmoid(Ok))·前一层输出OjTself.who += self.lr * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)), numpy.transpose(hidden_outputs))self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), numpy.transpose(inputs))pass# 查询神经网络,接受输入,返回输出def query(self, inputs_list):# 将输入列表转换成二维列表,保证计算类型正确inputs = numpy.array(inputs_list, ndmin=2).T# 输入层-隐藏层权重矩阵 点乘 输入矩阵 = 隐藏层输入hidden_inputs = numpy.dot(self.wih, inputs)# 隐藏层输入应用激活函数hidden_outputs = self.activation_function(hidden_inputs)# 隐藏层-输出层权重矩阵 点乘 输隐藏层输出矩阵 = 输出层输入final_inputs = numpy.dot(self.who, hidden_outputs)# 输出层输入应用激活函数final_outputs = self.activation_function(final_inputs)return final_outputs

数据集采用在人工智能领域流行的手写数字的MNIST数据库,MNIST数据库的格式不容易使用, 因此其他人已经创建了相对简单的数据文件格式——CSV文件,其纯文本中的每一个值都是由逗号分
隔的。

训练集是用来训练神经网络的60 000个标记样本集。标记是指输入与期望的输出匹配,也就是答案应该是多少。
可以使用较小的只有10 000个样本的测试集来测试我们的想法或算法工作的好坏程度。 由于这也包含了正确的标记, 因此可以观察神经网络是否得到正确的答案。

在文本中, 这些记录或这些行的内容很容易理解:
第一个值是标签, 即书写者实际希望表示的数字, 如“7”或“9”。 这是我们希望神经网络学习得到的正确答案。随后的值,由逗号分隔,是手写体数字的像素值。像素数组的尺寸是28乘以28,因此在标签后有784个值。

# 读取并显示数据集数据表示的含义
import numpy
import matplotlib.pyplot as plt
# %matplotlib inlinedata_file = open(".../mnist_train_100.csv", 'r')
data_list = data_file.readlines()
data_file.close()
print(len(data_list))# 显示第一个
all_values = data_list[0].split(',')
# 将文本字符串转换成实数, .reshape((28,28))可以确保数字列表每28个元素折返一次,形成28乘28的方形矩阵
image_array = numpy.asfarray(all_values[1:]).reshape((28, 28))
# 对图像做处理
plt.imshow(image_array, cmap='Greys', interpolation='None')
# 显示图像
plt.show()

在将数据抛给神经网络之前需要准备数据

我们先前看到,如果输入数据和输出值, 形状正好适合, 这样它们就可以待在网络节点激活函数的舒适区域内,那么神经网络的工作会更出色。

我们需要做的第一件事情是将输入颜色值从较大的0到255的范围,缩放至较小的0.01 到 1.0的范围。 我们刻意选择0.01作为范围最低点,是为了避免先前观察到的0值输入最终会人为地造成权重更新失败。我们没有选择0.99作为输入的上限值, 是因为不需要避免输入1.0会造成这个问题。 我们只需要避免输出值为1.0。

将在0到255范围内的原始输入值除以255,就可以得到0到1范围的输入值。

然后,需要将所得到的输入乘以0.99,把它们的范围变成0.0 到0.99。接下来,加上0.01,将这些值整体偏移到所需的范围0.01到1.00。

scaled_input = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01

现在, 我们需要思考神经网络的输出。 先前, 我们看到输出值应该匹配激活函数可以输出值的范围。 我们使用的逻辑函数不能输出如 -2.0 或 255 这样的数字,能输出的范围为0.0到1.0,事实上不能达到0.0或1.0,这是逻辑函数的极限值,逻辑函数仅接近这两个极限,但不能真正到达那里。因此,看起来在训练时必须调整目标值。

我们要求神经网络对图像进行分类, 分配正确的标签。 这些标签是0到9共10个数字中的一个。 这意味着神经网络应该有10个输出层节点, 每个节点对应一个可能的答案或标签。 如果答案是“0”, 输出层第一个节点激发, 而其余的输出节点则保持抑制状态。

image-20230827200941222

依照这种方向,我们可以构建目标矩阵

onodes = 10
targets = numpy.zeros(onodes) + 0.01
targets[int(all_values[0])] = 0.99

# 训练网络
def train_network(network, output_nodes, train_path, epochs):# 加载MNIST训练数据集training_data_file = open(train_path, 'r')training_data_list = training_data_file.readlines()training_data_file.close()# 训练世代,即训练几次for e in range(epochs):# 遍历读取的训练集for record in training_data_list:all_values = record.split(',')# 将文本字符串转换成实数,并将输入颜色值从0~255缩小为0.01~1.0,保证输入inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01# 目标数组targets = numpy.zeros(output_nodes) + 0.01# 设置目标数字对应的数组内容为0.99targets[int(all_values[0])] = 0.99network.train(inputs, targets)passpass# 测试单个输入
def query_network_one_input(network, img_data):# 设置输入inputs = (numpy.asfarray(img_data[:]) / 255.0 * 0.99) + 0.01# 查询网络outputs = network.query(inputs)# 取出输出数组中的最高值对应的下标label = numpy.argmax(outputs)return label# 测试文件,文件中有多条数据
def query_network(network, test_path):# 读取测试数据test_data_file = open(test_path, 'r')test_data_list = test_data_file.readlines()test_data_file.close()# 评分表,回答正确添加一个1scorecard = []for record in test_data_list:all_values = record.split(',')# 取出目标数字correct_label = int(all_values[0])print("aim=", correct_label, end="")# 设置输入inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01# 查询网络outputs = network.query(inputs)# 取出输出数组中的最高值对应的下标label = numpy.argmax(outputs)print("ans=", label)# 设置评分表if (label == correct_label):scorecard.append(1)else:scorecard.append(0)passpass# 计算正确率scorecard_array = numpy.asarray(scorecard)print("performance = ", scorecard_array.sum() / scorecard_array.size)# 保存神经网络对象
def save_network(path, network):with open(path, 'wb') as f:pickle.dump(network, f)# 加载神经网络对象
def load_network(path):with open(path, 'rb') as f:network = pickle.load(f)return network

改进网络

调整学习率

学习率是影响梯度下降发生速度的重要参数。

image-20230827201853904

多次运行

通过提供更多爬下斜坡的机会, 有助于在梯度下降过程中进行权重更新

image-20230827201945500

结果呈现出不可预测性。 在大约5或7个世代时, 有一个甜蜜点。 在此之后, 性能会下降, 这可能是过度拟合的效果。 性能在6个世代的情况下下降, 这可能是运行中出了问题, 导致网络在梯度下降过程中被卡在了一个局部的最小值中。 事实上, 由于没有对每个数据点进行多次实验, 无法减
小随机过程的影响,

image-20230827202727930

直观上, 如果你打算使用更长的时间(多个世代) 探索梯度下降, 那么你可以承受采用较短的步长(学习率) , 并且在总体上可以找到更好的路径, 这是有道理的。 确实, 对于MNIST学习任务, 我们的神经网络的甜蜜点看起来是5个世代。 请再次记住, 我们在使用一种相当不科学的方式来进行实验。 要正确、 科学地做到这一点, 就必须为每个学习率和世代组合进行多次实验, 尽量减少在梯度下降过程中随机性的影响。


改变网络形状

随着增加隐藏层节点的数量, 结果有所改善, 但是不显著。 由于增加一个隐藏层节点意味着增加了到前后层的每个节点的新网络链接, 这一切都会产生额外较多的计算, 因此训练网络所用的时间也显著增加了! 因此, 必须在可容忍的运行时间内选择某个数目的隐藏层节点。


手写数字

import imageio.v2 as imageio
import neuralNetwork
import splitimg# 分割图片保存目录
test = ".../test/"# 分析含有多个数字的图片
def parse_img_numbers(img_path, network):result = 0number = splitimg.split_img(img_path, test)for i in range(0, number):img_array = imageio.imread(test + '%d.jpg' % i, pilmode='L')img_data = 255.0 - img_array.reshape(784)label = neuralNetwork.query_network_one_input(network, img_data)result += label * pow(10, number-1)number -= 1print(result)# 分析只有一个数字的图片
def parse_img(img_path, network):img_array = imageio.imread(img_path, pilmode='L')img_data = 255.0 - img_array.reshape(784)label = neuralNetwork.query_network_one_input(network, img_data)return label
# 按数字分割图片
import cv2
import numpy as npP_A = 10def split_img(source_path, temp_save_path):# 图像resizedsize = 28img = cv2.imread(source_path)data = np.array(img)height = data.shape[0]width = data.shape[1]# 设置最小的文字像素高度min_val = 10start_i = -1end_i = -1# 存放每行的起止坐标rowinfo = []# 行分割for i in range(height):# 行中有字相关信息if (not data[i].all()):end_i = iif (start_i < 0):start_i = ipass# 行中无字相关信息elif (data[i].all() and start_i >= 0):if (end_i - start_i >= min_val):rowinfo.append((start_i, end_i))passstart_i, end_i = -1, -1# 列分割start_j = -1end_j = -1# 最小文字像素宽度min_val_word = 5# 分割后保存编号number = 0for start, end in rowinfo:for j in range(width):# 列中有字相关信息if (not data[start: end, j].all()):end_j = jif (start_j < 0):start_j = jpass# 列中无字信息elif (data[start: end, j].all() and start_j >= 0):if (end_j - start_j >= min_val_word):img = data[start:end, start_j: end_j]im2save = cv2.resize(cv2.copyMakeBorder(img, P_A, P_A, P_A, P_A, cv2.BORDER_CONSTANT, value=(255, 255, 255)), (28, 28))  # 归一化处理cv2.imwrite(temp_save_path + '%d.jpg' % number, im2save)number += 1passstart_j, end_j = -1, -1return number

让我们来看看是否可以到神经网络内部一探究竟, 是否能够理解神经网络所学习到的知识, 将神经网络通过训练搜集到的知识可视化。

我们可以观察权重, 这毕竟是神经网络学习的内容。 但是, 权重不太可能告诉我们太多信息。 特别是, 神经网络的工作方式是将学习分布到不同的链接权重中。 这种方式使得神经网络对损坏具有了弹性, 这就像是生物大脑的运行方式。 删除一个节点甚至相当多的节点, 都不太可能彻底破坏神经网络良好的工作能力。

向后查询

image-20230827203530166

https://github.com/makeyourownneuralnetwork/makeyourownneuralnetwork/blob/master/part3_neural_network_mnist_backquery.ipynb

上面是反向查询神经网络的代码


为了学习多样的变化类型,我们可以通过旋转图像创建新的训练数据

# create rotated variations
# rotated anticlockwise by 10 degrees
inputs_plus10_img = scipy.ndimage.interpolation.rotate(scaled_input.reshape(28,28), 10,cval=0.01, reshape=False)
# rotated clockwise by 10 degrees
inputs_minus10_img=scipy.ndimage.interpolation.rotate(scaled_input.reshape(28,28), -10,cval=0.01, reshape=False)

image-20230827203949024

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/109161.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据分析】统计量

1. 均值、众数描述数据的集中趋势度量&#xff0c;四分位差、极差描述数据的离散程度。 2. 标准差、四分位差、异众比率度量离散程度&#xff0c;协方差是度量相关性。 期望值分别为E[X]与E[Y]的两个实随机变量X与Y之间的协方差Cov(X,Y)定义为&#xff1a; 从直观上来看&…

Vue2向Vue3过度核心技术自定义指令

目录 1 自定义指令1.指令介绍2.自定义指令3.自定义指令语法4.指令中的配置项介绍5.代码示例6.总结 2 自定义指令-指令的值1.需求2.语法3.代码示例 3 自定义指令-v-loading指令的封装1.场景2.需求3.分析4.实现5.准备代码 1 自定义指令 1.指令介绍 内置指令&#xff1a;v-html、v…

channel并发编程

不要通过共享内存通信&#xff0c;要通过通信共享内存。 channel是golang并发编程中一种重要的数据结构&#xff0c;用于多个goroutine之间进行通信。 我们通常可以把channel想象成一个传送带&#xff0c;将goroutine想象成传送带周边的人&#xff0c;一个传送带的上游放上物品…

四信重磅推出5G RedCap AIoT摄像机 RedCap轻量级5G终端新品首发!

6月6日&#xff0c;四信受邀出席移动物联网高质量发展论坛&#xff0c;并在移动物联网新产品发布环节隆重推出5G RedCap AIoT摄像机&#xff0c;再次抓紧需求先机&#xff0c;为行业用户创造无限可能&#xff01; 两大应用场景 助推RedCap走深向实 火遍全网络的RedCap应用场景可…

【JavaEE进阶】MyBatis表查询

文章目录 一. 使用MyBatis完成数据库的操作1. MyBatis程序中sql语句的即时执行和预编译1.1 即时执行&#xff08;${}&#xff09;1.2 预编译&#xff08;#{}&#xff09;1.3 即时执行和预编译的优缺点 2. 单表的增删改等操作2.1 增加操作2.2 修改操作2.3 删除操作2.4 like(模糊…

LeetCode538. 把二叉搜索树转换为累加树

538. 把二叉搜索树转换为累加树 文章目录 [538. 把二叉搜索树转换为累加树](https://leetcode.cn/problems/convert-bst-to-greater-tree/)一、题目二、题解方法一&#xff1a;递归&#xff08;中序遍历与节点更新&#xff09;方法二&#xff1a;反向中序遍历与累加更新&#x…

JavaFX 加载 fxml 文件

JavaFX 加载 fxml 文件主要有两种方式&#xff0c;第一种方式通过 FXMLLoader 类直接加载 fxml 文件&#xff0c;简单直接&#xff0c;但是有些控件目前还不知道该如何获取&#xff0c;所以只能显示&#xff0c;目前无法处理。第二种方式较为复杂&#xff0c;但是可以使用与 fx…

初阶数据结构(六)队列的介绍与实现

&#x1f493;博主csdn个人主页&#xff1a;小小unicorn&#x1f493; ⏩专栏分类&#xff1a;C &#x1f69a;代码仓库&#xff1a;小小unicorn的学习足迹&#x1f69a; &#x1f339;&#x1f339;&#x1f339;关注我带你学习编程知识 栈 队列的介绍队列的概念&#xff1a;队…

GWO-LSTM交通流量预测(python代码)

使用 GWO 优化 LSTM 模型的参数&#xff0c;从而实现交通流量的预测方法 代码运行版本要求 1.项目文件夹 data是数据文件夹&#xff0c;data.py是数据归一化等数据预处理脚本 images文件夹装的是不同模型结构打印图 model文件夹 GWO-LSTM测试集效果 效果视频&#xff1a;GWO…

SNN论文总结

Is SNN a great work ? Is SNN a convolutional work ? ANN的量化在SNN中是怎么体现的&#xff0c;和threshold有关系吗&#xff0c;threshold可训练和这个有关吗&#xff08;应该无关&#xff09; 解决过发放不发放的问题。 Intuation SNN编码方式 Image to spike patter…

stm32之19.温湿度模块(待补充)

dth11.c文件① #include "dht11.h" #include "delay.h"// 1、温湿度模块初始化(PG9) void Dht11_Init(void) {// 0、GPIO外设信息结构体GPIO_InitTypeDef GPIO_InitStruct;// 1、使能硬件时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);//…

Pyqt5开发实战记录

入职以来第一个开发项目&#xff1a; 1、如何给Qlabel加边框&#xff1a;右键label对象&#xff0c;选择“改变样式表”输入一下代码&#xff1a; border: 1px solid black;2、如何让垂直布局中button大小不发生变化&#xff1a;其实很简单&#xff0c;只需要设置button的最大…

【seaweedfs】2、Finding a needle in Haystack: Facebook’s photo storage 分布式对象存储论文

文章目录 一、介绍二、背景、设计理念2.1 背景2.2 NFS-based Design2.3 Discussion 三、设计和实现3.1 概览3.2 Haystack Directory3.3 Haystack Cache3.4 Haystack Store3.4.1 Photo Read3.4.2 Photo Write3.4.3 Photo Delete3.4.4 The Index File3.4.5 Filesystem 3.5 Recove…

WebGL 缓冲区对象介绍,创建并使用缓冲区,使用缓冲区对象向顶点着色器传入多个顶点数据的所有步骤

目录 使用缓冲区对象 使用缓冲区对象向顶点着色器传入多个顶点的数据&#xff0c;需要遵循以下五个步骤。 创建缓冲区对象&#xff08;gl.createBuffer&#xff08;&#xff09;&#xff09; gl.createBuffer&#xff08;&#xff09;的函数规范 gl.deleteBuffer &#…

C# winform加载yolov8模型测试(附例程)

第一步&#xff1a;在NuGet中下载Yolov8.Net 第二步&#xff1a;引用 using Yolov8Net; 第三步&#xff1a;加载模型 private IPredictor yolov8 YoloV8Predictor.Create("D:\\0MyWork\\Learn\\vs2022\\yolov_onnx\\best.onnx", mylabel); 第四步&#xff1a;图…

【OpenCV • c++】图像对比度调整 | 图像亮度调整

&#x1f680; 个人简介&#xff1a;CSDN「博客新星」TOP 10 &#xff0c; C/C 领域新星创作者&#x1f49f; 作 者&#xff1a;锡兰_CC ❣️&#x1f4dd; 专 栏&#xff1a;【OpenCV • c】计算机视觉&#x1f308; 若有帮助&#xff0c;还请关注➕点赞➕收藏&#xff…

window系统中如何判断是物理机还是虚拟机及VMPROTECT无法检测云主机

为什么要判断物理机&#xff0c;因为授权不能对虚拟机安装后的软件进行授权。虚拟机可以复制可以克隆&#xff0c;无法作为一个不可复制ID来使用。 总结了如何判断物理机&#xff1a; 1. 用systeminfo的系统型号。&#xff08;注&#xff0c;有资料是看处理器和bios。但是我这…

一步一步实验,讲解python中模块和包的使用

背景 为什么要提出这个问题&#xff1f; 在一个项目中&#xff0c;每一个python文件打开后&#xff0c;都会看到依赖了其他的一些包、模块等&#xff1b;概念混乱&#xff0c;魔改目标不清晰 为什么要修改&#xff1f; 如果需要将某开源包进行自定义处理&#xff0c;不再使…

Python 包管理(pip、conda)基本使用指南

Python 包管理 概述 介绍 Python 有丰富的开源的第三方库和包&#xff0c;可以帮助完成各种任务&#xff0c;扩展 Python 的功能&#xff0c;例如 NumPy 用于科学计算&#xff0c;Pandas 用于数据处理&#xff0c;Matplotlib 用于绘图等。在开始编写 Pytlhon 程序之前&#…

数据隐私与安全在大数据时代的挑战与应对

文章目录 数据隐私的挑战数据安全的挑战应对策略和方法1. 合规和监管2. 加密技术3. 匿名化和脱敏4. 安全意识培训5. 隐私保护技术 结论 &#x1f388;个人主页&#xff1a;程序员 小侯 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 ✨收录专栏&…