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”, 输出层第一个节点激发, 而其余的输出节点则保持抑制状态。
依照这种方向,我们可以构建目标矩阵
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
改进网络
调整学习率
学习率是影响梯度下降发生速度的重要参数。
多次运行
通过提供更多爬下斜坡的机会, 有助于在梯度下降过程中进行权重更新
结果呈现出不可预测性。 在大约5或7个世代时, 有一个甜蜜点。 在此之后, 性能会下降, 这可能是过度拟合的效果。 性能在6个世代的情况下下降, 这可能是运行中出了问题, 导致网络在梯度下降过程中被卡在了一个局部的最小值中。 事实上, 由于没有对每个数据点进行多次实验, 无法减
小随机过程的影响,
直观上, 如果你打算使用更长的时间(多个世代) 探索梯度下降, 那么你可以承受采用较短的步长(学习率) , 并且在总体上可以找到更好的路径, 这是有道理的。 确实, 对于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
让我们来看看是否可以到神经网络内部一探究竟, 是否能够理解神经网络所学习到的知识, 将神经网络通过训练搜集到的知识可视化。
我们可以观察权重, 这毕竟是神经网络学习的内容。 但是, 权重不太可能告诉我们太多信息。 特别是, 神经网络的工作方式是将学习分布到不同的链接权重中。 这种方式使得神经网络对损坏具有了弹性, 这就像是生物大脑的运行方式。 删除一个节点甚至相当多的节点, 都不太可能彻底破坏神经网络良好的工作能力。
向后查询
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)
相关文章:

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__(se…...

合宙Air724UG LuatOS-Air LVGL API控件-键盘 (Keyboard)
键盘 (Keyboard) LVGL 可以添加触摸键盘,但是很明显,使用触摸键盘的话必须要使用触摸的输入方式,否则无法驱动键盘。 示例代码 function keyCb(obj, e)-- 默认处理事件lvgl.keyboard_def_event_cb(keyBoard, e)if(e lvgl.EVENT_CANCEL)the…...

pytorch深度学习实践
B站-刘二大人 参考-PyTorch 深度学习实践_错错莫的博客-CSDN博客 线性模型 import numpy as np import matplotlib.pyplot as pltx_data [1.0, 2.0, 3.0] y_data [2.0, 4.0, 6.0]def forward(x):return x * wdef loss(x, y):y_pred forward(x)return (y_pred - y) ** 2# …...

直方图反向投影(Histogram Backprojection)
直方图反向投影(Histogram Backprojection)是一种在计算机视觉中用于对象检测和图像分割的技术。它的原理基于图像的颜色分布,允许我们在一幅图像中找到与给定对象颜色分布相匹配的区域。这个技术常常用于图像中的目标跟踪、物体识别和图像分…...

day32 泛型 数据结构 List
一、泛型 概述 JDK1.5同时推出了两个和集合相关的特性:增强for循环,泛型 泛型可以修饰泛型类中的属性,方法返回值,方法参数, 构造函数的参数 Java提供的泛型类/接口 Collection, List, Set,Iterator 等 …...

DW-AHB Central DMAC
文章目录 AHB Central DMAC —— Design Ware AHB Central DMAC —— Design Ware AHB(Adavenced High-performace BUS) Central DMAC(Direct Memory Access Controller) : 一个高性能总线系统。 作用:在嵌入式系统种连接高速设备,如处理器内存&#x…...

JavaScript设计模式(四)——策略模式、代理模式、观察者模式
个人简介 👀个人主页: 前端杂货铺 🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步…...

JS画布的基本使用
直线 <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title></title> <style> #myname{ border: 1px solid red; /* background: linear-gradient(to righ…...

c++ set/multiset
set/multiset 集合,一个单个,一个多个(multi)。两个库都是"set"。 https://blog.csdn.net/fckbb/article/details/130917681 对象创建 set(const Pred& compPred(),const A& alA()):创建空集合。set(const set& x):…...

多线程与高并发——并发编程(4)
文章目录 四、阻塞队列1 基础概念1.1 生产者消费者概念1.2 JUC阻塞队列的存取方法2 ArrayBlockingQueue2.1 ArrayBlockingQueue的基本使用2.2 生产者方法实现原理2.2.1 ArrayBlockingQueue的常见属性2.2.2 add方法2.2.3 offer方法2.2.4 offer(time,unit)方法2.2.5 put方法2.3 消…...

设计模式之建造者模式
文章目录 盖房项目需求传统方式解决盖房需求传统方式的问题分析建造者模式概述是建造者模式的四个角色建造者模式原理类图建造者模式的注意事项和细节 盖房项目需求 需要建房子:这一过程为打桩、砌墙、封顶房子有各种各样的,比如普通房,高楼…...

源码编译安装opencv4.6.0,别的版本也行
1.下载opencv4.6.0 系统: ubuntu 1804 64位点我下载opencv 4.6.0 https://codeload.github.com/opencv/opencv/zip/refs/tags/4.6.0 指令下载 推荐: wget -O opencv.zip https://github.com/opencv/opencv/archive/4.6.0.zip wget -O opencv_contrib.zip https://github.com/…...

【MongoDB】Springboot中MongoDB简单使用
1. docker安装MongoDB 拉取镜像 docker pull mongo创建容器 docker run -di --name mongo-service --restartalways -p 27017:27017 -v ~/data/mongodata:/data mongo2. 导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactI…...

Python 面试:单元测试unit testing 使用pytest
1. 对于函数进行单元测试 calc.py def add(x, y):"""Add Function"""return x ydef subtract(x, y):"""Subtract Function"""return x - ydef multiply(x, y):"""Multiply Function""…...

螺旋矩阵、旋转矩阵、矩阵Z字打印
螺旋矩阵 #include <iostream> #include <vector> void display(std::vector<std::vector<int>>&nums){for(int i 0; i < nums.size(); i){for(int j 0; j < nums[0].size(); j){std::cout<<nums[i][j]<< ;}std::cout<<…...

Seaborn绘制热力图的子图
Seaborn绘制热力图的子图 提示:如何绘制三张子图 绘制的时候,会出现如下问题 (1)如何绘制1*3的子图 (2)三个显示条,如何只显示最后一个 提示:下面就展示详细步骤 Seaborn绘制热力…...

C++二级题目4
小白鼠再排队 不会 多余的数 #include<iostream> #include<string.h> #include<stdio.h> #include<iomanip> #include<cmath> #include<bits/stdc.h> int a[2000][2000]; int b[2000]; char c[2000]; long long n; using namespace std; i…...

Tomcat 部署时 war 和 war exploded区别
在 Tomcat 调试部署的时候,我们通常会看到有下面 2 个选项。 是选择war还是war exploded 这里首先看一下他们两个的区别: war 模式:将WEB工程以包的形式上传到服务器 ;war exploded 模式:将WEB工程以当前文件夹的位置…...

Delphi IdTcpServer IdTcpClient 传输简单文本
Delphi IdTcpServer IdTcpClient 传输简单文本 已经很久敲代码了,想找一段直接Delphi11 TCP简单文本传输,费劲!FStringStream 、FStrStream : FStringStream:TStringStream.Create(,TEncoding.UTF8); 已经很久敲代码了,…...

界面控件Telerik UI for WPF——Windows 11主题精简模式提升应用体验
Telerik UI for WPF拥有超过100个控件来创建美观、高性能的桌面应用程序,同时还能快速构建企业级办公WPF应用程序。Telerik UI for WPF支持MVVM、触摸等,创建的应用程序可靠且结构良好,非常容易维护,其直观的API将无缝地集成Visua…...

PoseC3D 基于人体姿态的动作识别新范式
摘要1. Introduction2. Related Work动作识别 3D-CNN基于骨架的动作识别 GCN基于骨骼的动作识别 2D-CNN3. Framework3.1. Good Practice for Pose Extraction3.2. From 2D Poses to 3D Heatmap Volumes3.3 基于骨骼的动作识别 3D-CNNPose-SlowOnlyRGBPose-SlowFast4. Experimen…...

html2canvas 截图空白 或出现toDataURL‘ on ‘HTMLCanvasElement或img标签没截下来 的所有解决办法
1.如果截图空白: 1.1以下的参数是必须要有的。 width: shareContent.offsetWidth, //设置canvas尺寸与所截图尺寸相同,防止白边height: shareContent.offsetHeight, //防止白边logging: true,useCORS: true,x:0,y:0,2,如果出现了报错 toData…...

Eclipse错误提示: Symbol ‘xxxx‘ could not be resolved
问题现象: 调试FPGA时,如果在qsys中增加新的内容,到nios中编译的时候就会提示找不到宏定义。 而这些宏定义都是在system.h这个头文件中的,原来的宏定义都能找到,就是新增的找不到,这个应该和头文件路径没有…...

基于Java的OA办公管理系统,Spring Boot框架,vue技术,mysql数据库,前台+后台,完美运行,有一万一千字论文。
基于Java的OA办公管理系统,Spring Boot框架,vue技术,mysql数据库,前台后台,完美运行,有一万一千字论文。 系统中的功能模块主要是实现管理员和员工的管理; 管理员:个人中心、普通员工…...

正则表达式(JAVA)
正则表达式(JAVA) 文章目录 正则表达式(JAVA)用法字符类(只匹配一个字符)预定义字符(只匹配一个字符)数量词贪婪爬取符号捕获分组规则捕获分组符号 非捕获分组案例忽略大小写 用法 正则表达式在用于校验信息是否满足某些规则的时候,非常的好用 在文本中查找满足要求的内容 字…...

264_BOOST中的Json库解析_BOOST_AUTO(itrpromodel, doc.FindMember(“productmodel“));
BOOST_AUTO(itrpromodel, doc.FindMember("productmodel"));if(itrpromodel != doc.MemberEnd()){BOOST_AUTO(iterd_url...

linux rpm 离线安装 nginx 自用,仅供参考
检查是否安装nginx ps -ef|grep nginx 检查rpm是否安装nginx rpm -qa|grep nginx 查看linux centos 发行版本 cat /etc/centos-release (查看其它发现版本 就把centos替换为别的 比如 红旗的 redflag ) 查看cpu信息 x86_64 lscpu 检查nginx所需依赖 …...

第十二章 YOLO的部署实战篇(上篇)
cuda教程目录 第一章 指针篇 第二章 CUDA原理篇 第三章 CUDA编译器环境配置篇 第四章 kernel函数基础篇 第五章 kernel索引(index)篇 第六章 kenel矩阵计算实战篇 第七章 kenel实战强化篇 第八章 CUDA内存应用与性能优化篇 第九章 CUDA原子(atomic)实战篇 第十章 CUDA流(strea…...

无涯教程-Android - List View函数
Android ListView 是垂直滚动列表中显示的视图,使用 Adapter 从列表(如数组或数据库)中获取内容的列表项会自动插入列表中。 适配器(Adapter)实际上是UI组件和将数据填充到UI组件中的数据源之间的桥梁,适配器保存数据并将数据发送到适配器视图࿰…...

stable diffusion实践操作-重绘
系列文章目录 本文专门开一节写局部重绘相关的内容,在看之前,可以同步关注: stable diffusion实践操作 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、局…...