当前位置: 首页 > news >正文

对神经网络基础的理解

目录

一、《python神经网络编程》

二、一些粗浅的认识

1) 神经网络也是一种拟合

2)神经网络不是真的大脑

3)网络构建需要反复迭代

三、数字图像识别的实现思路

1)建立一个神经网络类

 2)权重更新的具体实现

3)网络测试

四、总结


一、《python神经网络编程》

最近学习了一本书《python神经网络编程》,该书通过对一个数字识别案例的深入详细讲解,可以让读者对神经网络的思想有更加清晰的理解,明白计算机神经网络是如何工作的。在没有真正接触神经网络之前,总以为这是非常深奥的理论,也不明白神经网络是如何模拟人的大脑进行学习和判断的,难以理解计算机能够模拟人的大脑。《python神经网络编程》确实是一本很好的入门教材,它让读者能够真正踏入人工智能的门槛,奠定深入研究的基础。

二、一些粗浅的认识

1) 神经网络也是一种拟合

在数学中有很多拟合方法,比如线性拟合、多项式拟合等等。在这些拟合中,我们同样需要有确定的已知数据,然后通过这些拟合方法我们可以得到一个确定的数学解析表达式,并通过这个表达式来预测未知的结果。而神经网络的核心思想,我想也是一样的,只是这个实现过程相对复杂。我们最终能得到的是一个预测网络,也称模型,而不是一个精确的数学方程表达式。我们使用已知输入和输出的大量数据来训练神经网络,就是在让这个网络的输出结果逐渐逼近已知的输出结果。这个网络在训练的过程中,最终建立起了输入与输出之间的对应关系。但是这个对应关系我们无法用一个清晰的数学表达式来描述,可是我们可以使用这个网络来进行预测。正如对于图片中的数字而言,我们人看到图片中的数字就可以知道图中的数字是多少,因为在我们认识数字之前经过了学习,很多次有人告诉我们这个图形对应的数字就是这个数字。就像神经网络不能用一个准确的数学公式来描述输入与输出之间的关系一样,我们人类其实至今也还是不知道我们大脑学习的本质是什么。所以神经网络得到的拟合结果是一个黑盒子,我们针对特定的问题建立了一个黑盒子,然后训练了这个黑盒子,我们只知道给这个黑盒子一个输入,他能给出一个可信的结果。

2)神经网络不是真的大脑

神经网络只是借用了人类大脑神经元的形式。计算机神经网络是否真的能实现动物大脑的能力,我想还是难以断定。我们以前总是认为计算机的工作都是确定的,给它一个输入,我们必然能够准确预测它的输出结果。其实现在的神经网络也是一样的,虽然它是个黑盒子,但是给它相同的输入,它必然能够得到相同的结果,即使我们不知道它具体的计算逻辑,因为在这个网络中所有的参数经过训练后已经确定,计算机计算的每一步都是确定的。但计算机神经网络这种模糊拟合的实现,让我们认识到,当大量简单计算累计到一定数量时,在庞大的信息传递中是否就存在不可预测性。我们不理解自己为什么会思考,或许在不久的将来我们也无法确信庞大计算机系统的运行的真是我们人类设计的程序。

3)网络构建需要反复迭代

在构建神经网络过程中,输入与输出的节点数量需要根据实际问题进行分析。我们需要根据解决的实际问题,分析如何将问题的输入数字化,并设计相应的输入节点。而对于输出也是一样,我们需要分析如何用输出的数字信息来表达我们想要的结果形式,并设计相应的输出节点。我们常见的简单的神经网络通常是3层,包括输入、输出和中间的隐藏层,而隐藏层的层数以及每层的节点数该如何设计,这需要通过不断的尝试。较少的层数和节点数能够获得较高的计算效率,但是性能较低,误差较大,较多的层数和节点数能够获得较高的精度,但是计算效率低。因此,针对具体的问题需要综合考虑,反复迭代后确定网络构建形式。

三、数字图像识别的实现思路

1)建立一个神经网络类

《python神经网络编程》书中给出了一个实现数字识别的例子。在Python中首先定义一个3层神经网络类neuralNetwork。在类的初始化函数中确定网络的输入层节点数、隐藏层节点数、输出层节点数和学习率4个参数。并确定使用的激活函数。输入层与隐藏层、隐藏层和输出层之间的初始权重矩阵随机生成。

训练神经网络时,先根据训练数据的输入,正向逐层计算,最后得到网络的输出结果。然后计算网络输出结果与实际结果的误差值,然后再将误差进行反向传播,更新权重矩阵。这样,一组数据的训练就完成。

网络输出就是利用测试数据对网络进行一次正向输出的过程,最后根据输出数据给出网络的图像识别结果,具体实现后面再叙述。

class neuralNetwork:# 初始化函数def __int__(self, inputnodes, hiddennodes, outputnodes, learningrate):self.inodes = inputnodes  # 输入节点数self.hnodes = hiddennodes  # 隐藏节点数self.onodes = outputnodes  # 输出节点数self.wih = numpy.random.normal(0.0, pow(self.hnodes, -0.5), (self.hnodes, self.inodes))  # 随机生成初始的输入层到隐藏层的权重矩阵self.who = numpy.random.normal(0.0, pow(self.hnodes, -0.5), (self.onodes, self.hnodes))  # 随机生成初始的隐藏层到输出层的权重矩阵self.learn = learningrate   # 权重更新率self.active_function = lambda x: scipy.special.expit(x)  # 选择需要使用的激活函数pass# 定义训练函数def train(self, input_list, target_list):  # 提供已知的输入和输出结果inputs = numpy.array(input_list, ndmin=2).T  # 将输入转换为二维矩阵形式targets = numpy.array(target_list, ndmin=2).Thidden_inputs = numpy.dot(self.wih, inputs)  # 计算隐藏层的输入值,输入层到隐藏层的权重矩阵乘以输入hidden_outputs = self.active_function(hidden_inputs)  # 计算隐藏层的输出值,将隐藏层的输入值带入激活函数final_inputs = numpy.dot(self.who, hidden_outputs)  # 计算输出层的输入值,隐藏层到输出层的权重矩阵乘以隐藏层的输出值final_outputs = self.active_function(final_inputs)  # 计算输出层的输出结果,将输出层的输入值带入激活函数output_errors = targets - final_outputs  # 计算误差值,已知的输出结果-输出层的输出值hidden_errors = numpy.dot(self.who.T, output_errors)  # 传递误差# 更新权重矩阵self.who += self.learn * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)),numpy.transpose(hidden_outputs))self.wih += self.learn * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)),numpy.transpose(inputs))pass# 定义输出函数def query(self, input_list):inputs = numpy.array(input_list, ndmin=2).Thidden_inputs = numpy.dot(self.wih, inputs)hidden_outputs = self.active_function(hidden_inputs)final_inputs = numpy.dot(self.who, hidden_outputs)final_outputs = self.active_function(final_inputs)return final_outputs

 2)权重更新的具体实现

权重矩阵反复更新,就是神经网络不断学习,获得正确拟合结果的过程。权重更新根据严格的数学推导公式,程序实现过程不能直观反映具体的实现思想。它的核心就是利用每次训练的计算误差来修正权重矩阵。

(1)误差计算

在训练神经网络过程中计算误差时,程序中我们直接将实际结果与计算结果相减(output_errors = targets - final_outputs),得到一个误差向量。但是理论分析时,直接相减计算误差的方法并不合适,我们通常使用差的平方来表示,所有节点的总误差如下:

error=\sum_{n}^{} \left (t_{n} -o_{n}\right )^{2}

 (2)误差传递

我们可以直接计算出输出层的误差,但是最终的误差是由前面的计算逐层、逐节点计算累计得到的,该如何将最终的误差反向分配到每个节点上呢?通常我们认为节点之间连接权重越大的链路,计算引入的误差也越大,因此,我们也同样通过权重来分配误差。针对本例而言,我们已经得到了输出层的误差,还需要计算隐藏层的误差。输入层不需要计算,因为默认输入层输入与输出是相同的,不需要使用激活函数。那么隐藏层的输出误差计算如下:

error_{hidden}=\bigl(\begin{smallmatrix} W_{1,1} & W_{1,2}& W_{1,3}\\ W_{2,1}& W_{2,2}& W_{2,3}\\ W_{3,1}& W_{2,3}& W_{3,3} \end{smallmatrix}\bigr)\bullet \begin{pmatrix} e_{1}\\ e_{2}\\ e_{3}\end{pmatrix}

此处需要注意的是,误差反向传播计算的矩阵正好是正向计算时隐藏层到输出层权重矩阵的转置,至于为什么是转置,我们手动简单计算一下就知道了。同时需要注意的是,通过上式计算得到的总误差并不是输出层的总误差(\sum e_{n}) 。因为,更新权重矩阵时,我们其实并不关心过程中的误差大小,而是更关心是哪个链路导致的误差更大,只要能体现出各链路误差的相对大小就可以。

(3)更新权重

在此例中使用跟新权重的方法是梯度下降法,这也是使用非常广泛的一种方法。我们需要建立起权重与误差之间的关系。我们以最后的输出层为例,输出层的输入是隐藏层的输出乘以隐藏层和输出层之间的权重矩阵:

In_{final}=W\bullet O_{hidden}

将此结果代入激活函数,则输出层的结果为:

O_{final}=sigmoid(In_{final})

sigmoid函数为激活函数,形式为:

s = \frac{1}{1+e^{-x}}

则每个节点的输出误差为:

error=\left ( t -o\right )^{2} 

将上述公式联合,然后对权重w求导,就可以得到误差相对于权重的导数(斜率):

\frac{\partial E}{\partial w}=-2\left ( t-o \right )\bullet o\bullet (1-o)\bullet o_{hidden}

权重更新公式为:

W_{new}=W_{old}-\alpha \frac{\partial E}{\partial w}

上述公式中,我们实际使用时并不关心常系数2,因此在代码实现时省略了。

3)网络测试

网络测试的具体实现可参见代码。

# 测试网络
scorecard = []
i = 0
for record in test_data_list:i += 1if(i != 10):  # 可调整数字,逐张识别continuepassall_values = record.split(',')correct_label = int(all_values[0])inputs = (numpy.asarray(all_values[1:], numpy.float32) / 255.0 * 0.99) + 0.01image_array = numpy.asarray(all_values[1:], numpy.int32).reshape((28, 28))fig = matplotlib.pyplot.figure(figsize=(5, 5))matplotlib.pyplot.imshow(image_array, cmap='Greys', interpolation='None')matplotlib.pyplot.show()outputs = n.query(inputs)  # 网络识别的结果label = numpy.argmax(outputs)  # 输出结果中的最大值print("输入数字:", all_values[0], "识别结果:", label)  # 打印出实际值if(label == correct_label):scorecard.append(1)else:scorecard.append(0)passpassscorecard_array = numpy.asarray(scorecard)
print("performance = ", scorecard_array.sum() / scorecard_array.size)

四、总结

《python神经网络编程》与书中的示例简明阐述了神经网络的核心思想和基本架构,任何复杂的神经网络均可基于此构建。我们可以通过使用不同的网络层数、节点数、激活函数以及链路连接方式等,构建不同的适用于各种应用的神经网络模型。或许正式因为神经网络内部的不可描述性,对网络结构的各种优化,为研究神经网络开辟了广阔空间。

相关文章:

对神经网络基础的理解

目录 一、《python神经网络编程》 二、一些粗浅的认识 1) 神经网络也是一种拟合 2)神经网络不是真的大脑 3)网络构建需要反复迭代 三、数字图像识别的实现思路 1)建立一个神经网络类 2)权重更新的具体实现 3&am…...

存储基础 -- SCSI命令格式与使用场景

SCSI命令格式与使用场景 1. SCSI命令描述符块(CDB) 1.1 CDB基本概念 SCSI命令通过**命令描述符块(CDB, Command Descriptor Block)**表示。 CDB长度:SCSI命令根据使用场景有不同长度的CDB,常见的有6字节…...

从崩溃难题看 C 标准库与 Rust:线程安全问题引发的深度思考

在软件开发的世界里,每一次技术的变革和尝试都伴随着未知的挑战。EdgeDB 团队在将部分网络 I/O 代码从 Python 迁移到 Rust 的过程中,就遭遇了一场棘手的问题,这个问题不仅暴露了 C 标准库的线程安全隐患,也让我们对 Rust 的 “安…...

【CSS入门学习】Flex布局设置div水平、垂直分布与居中

水平平均分布 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><style>…...

9. 神经网络(一.神经元模型)

首先&#xff0c;先看一个简化的生物神经元结构&#xff1a; 生物神经元有多种类型&#xff0c;内部也有复杂的结构&#xff0c;但是可以把单个神经元简化为3部分组成&#xff1a; 树突&#xff1a;一个神经元往往有多个树突&#xff0c;用于接收传入的信息。轴突&#xff1a;…...

R 语言 | future 包,非阻塞的执行耗时脚本

目的&#xff1a;有一段代码&#xff0c;后面暂时用不到&#xff0c;但是又很耗时&#xff0c;占了当前R session&#xff0c;难道只能等半个小时&#xff0c;等到它结束才能画图&#xff1f; 可以使用R多线程&#xff0c;在支线进程中执行耗时任务&#xff0c;同时不阻塞当前…...

UE学习日志#12 Niagara特效大致了解(水文,主要是花时间读了读文档和文章)

1 核心组件&#xff08;官方文档阅读&#xff09; 一些介绍主要来自官方文档Niagara概述 1.1 Systems 官方文档中的描述&#xff1a; Niagara系统是一种容器&#xff0c;可以放入你要构建该效果的所有内容。在这个系统中&#xff0c;你可以搭建不同的构建块来实现总体效果。…...

【数据结构】_链表经典算法OJ:合并两个有序数组

目录 1. 题目描述及链接 2. 解题思路 3. 程序 3.1 第一版 3.2 第二版 1. 题目描述及链接 题目链接&#xff1a;21. 合并两个有序链表 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 将两个升序链表合并为一个新的 升序 链表并返回。 新链表是通过拼接给…...

Mongodb副本集群为什么选择3个节点不选择4个节点

一、容错能力的定义 在副本集中&#xff0c;容错能力是指系统能够容忍多少个节点故障而仍然能够保持服务可用性的能力。这通常与选举机制中的多数投票原则密切相关。 二、三节点副本集的容错能力 在三节点的副本集中&#xff0c;通常有一个主节点和两个从节点。当主节点故障…...

基于 WEB 开发的手机销售管理系统设计与实现内容

标题:基于 WEB 开发的手机销售管理系统设计与实现 内容:1.摘要 摘要&#xff1a;随着智能手机的普及和电子商务的快速发展&#xff0c;手机销售行业面临着越来越多的挑战和机遇。为了提高销售效率和管理水平&#xff0c;本文设计并实现了一个基于 WEB 的手机销售管理系统。该系…...

LeetCode - Google 大模型校招10题 第1天 Attention 汇总 (3题)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/145368666 GroupQueryAttention(分组查询注意力机制) 和 KVCache(键值缓存) 是大语言模型中的常见架构&#xff0c;GroupQueryAttention 是注意力…...

Vue3 provide/inject用法总结

1. 基本概念 provide/inject 是 Vue3 中实现跨层级组件通信的方案&#xff0c;类似于 React 的 Context。它允许父组件向其所有子孙组件注入依赖&#xff0c;无论层级有多深。 1.1 基本语法 // 提供方&#xff08;父组件&#xff09; const value ref(hello) provide(key, …...

Linux——网络基础(1)

文章目录 目录 文章目录 前言 一、文件传输协议 应用层 传输层 网络层 数据链路层 数据接收与解封装 主机与网卡 数据传输过程示意 二、IP和MAC地址 定义与性质 地址格式 分配方式 作用范围 可见性与可获取性 生活例子 定义 用途 特点 联系 四、TCP和UDP协…...

【记录】日常|从零散记录到博客之星Top300的成长之路

文章目录 shandianchengzi 2024 年度盘点概述写作风格简介2024年的创作内容总结 shandianchengzi 2024 年度盘点 概述 2024年及2025年至今我创作了786即84篇文章&#xff0c;加上这篇就是85篇。 很荣幸这次居然能够入选博客之星Top300&#xff0c;这个排名在我之前的所有年份…...

【二分查找】力扣373. 查找和最小的 K 对数字

给定两个以 非递减顺序排列 的整数数组 nums1 和 nums2 , 以及一个整数 k 。 定义一对值 (u,v)&#xff0c;其中第一个元素来自 nums1&#xff0c;第二个元素来自 nums2 。 请找到和最小的 k 个数对 (u1,v1), (u2,v2) … (uk,vk) 。 示例 1: 输入: nums1 [1,7,11], nums2 …...

池化层Pooling Layer

1. 定义 池化是对特征图进行的一种压缩操作&#xff0c;通过在一个小的局部区域内进行汇总统计&#xff0c;用一个值来代表这个区域的特征信息&#xff0c;常用于卷积神经网络&#xff08;CNN&#xff09;中。 2. 作用 提取代表性信息的同时降低特征维度&#xff0c;具有平移…...

力扣算法题——11.盛最多水的容器

目录 &#x1f495;1.题目 &#x1f495;2.解析思路 本题思路总览 借助双指针探索规律 从规律到代码实现的转化 双指针的具体实现 代码整体流程 &#x1f495;3.代码实现 &#x1f495;4.完结 二十七步也能走完逆流河吗 &#x1f495;1.题目 &#x1f495;2.解析思路…...

自由学习记录(32)

文件里找到切换颜色空间 fgui中的 颜色空间是一种总体使用前的设定 颜色空间&#xff0c;和半透明混合产生的效果有差异&#xff0c;这种问题一般可以产生联系 动效就是在fgui里可以编辑好&#xff0c;然后在unity中也准备了对应的调用手段&#xff0c;可以详细的使用每一个具…...

VScode+Latex (Recipe terminated with fatal error: spawn xelatex ENOENT)

使用VSCode编辑出现Recipe terminated with fatal error: spawn xelatex ENOENT问题咋办&#xff1f; 很好解决&#xff0c;大概率的原因是因为latex没有添加到系统环境变量中&#xff0c;所有设置的编译工具没有办法找到才出现的这种情况。 解决方法&#xff1a; winR 然后输…...

「蓝桥杯题解」蜗牛(Java)

题目链接 这道题我感觉状态定义不太好想&#xff0c;需要一定的经验 import java.util.*; /*** 蜗牛* 状态定义&#xff1a;* dp[i][0]:到达(x[i],0)最小时间* dp[i][1]:到达 xi 上方的传送门最小时间*/public class Main {static Scanner in new Scanner(System.in);static f…...

PHP EOF (Heredoc) 详解

PHP EOF (Heredoc) 详解 PHP 中的 EOF(End Of File)是一种非常有用的语法特性,允许开发者创建多行字符串。它特别适合于创建格式化文本,如配置文件、HTML 模板等。本文将详细讲解 PHP EOF 的用法、优势以及注意事项。 什么是 EOF? EOF 是一种特殊的字符串定义方式,它允…...

pyautogui操控Acrobat DC pro万能PDF转Word,不丢任何PDF格式样式

为了将PDF转换脚本改为多进程异步处理&#xff0c;我们需要确保每个进程独立操作不同的Acrobat窗口。以下是实现步骤&#xff1a; 实现代码 import os import pyautogui import time import subprocess import pygetwindow as gw from multiprocessing import Pooldef conver…...

Day32:字符串的复制

在 Python 中&#xff0c;字符串的复制是指创建一个新的字符串&#xff0c;它的内容与原字符串相同。字符串是不可变的对象&#xff0c;这意味着你不能直接修改字符串的内容&#xff0c;但是可以通过复制来创建新的字符串进行操作。字符串的复制在一些情况下非常有用&#xff0…...

基于Mybatis继承AbstractRoutingDataSource使用自定义注解实现动态数据源

一&#xff1a;实现 方式一&#xff1a;继承AbstractRoutingDataSource使用自定义注解实现 环境&#xff1a;springboot3 MyBatis3 mysql-connector8 DataSourceKeyEnum枚举类 有几个数据源就配置几个枚举类&#xff0c;和数据源数量一一对应 class DataSourceKeyEnum{D…...

ZooKeeper 数据模型

ZooKeeper 数据模型 ZooKeeper 拥有层次化的命名空间&#xff0c;类似分布式文件系统&#xff0c;但每个节点不仅能有子节点&#xff0c;还可关联数据。节点路径为规范的绝对路径&#xff0c;用斜杠分隔&#xff0c;无相对引用。路径命名有如下约束&#xff1a; 路径名不能包…...

【VUE】Vue2中Vue.extend方法

在 Vue.js 2.x 版本中&#xff0c;Vue.extend() 方法被用于创建一个新的 Vue 子类&#xff0c;可以在该子类上扩展一些属性、指令和组件选项等&#xff0c;然后进行实例化。 比如&#xff0c;可以在创建一些类似 loading 式的函数式插件时&#xff0c;使用&#xff1a; 在 Vue…...

MaskGAE论文阅读

What’s Behind the Mask: Understanding Masked Graph Modeling for Graph Autoencoders 碎碎念&#xff1a;一篇论文看四天&#xff0c;效率也没谁了(捂脸) 看一点忘一点&#xff0c;虽然在本子上有记录&#xff0c;但还是忘&#xff0c;下次看一点在博客上记一点启发 本来很…...

Mybatis-plus 更新 Null 的策略踩坑记

一个bug 在一个管理页面&#xff0c;有一个非必填字段被设置成空了并提交更新&#xff0c;再次打开的时候&#xff0c;发现字段还在&#xff0c;并没有被更新成功。 使用的数据库映射框架是 Mybatis-plus &#xff0c;对于Mybatis 在更新字段的时候会对空进行校验&#xff0c;…...

Oracle迁移DM数据库

Oracle迁移DM数据库 本文记录使用达梦官方数据迁移工具DTS&#xff0c;将Oracle数据库的数据迁移至达梦数据库。 1 数据准备 2 DTS工具操作步骤 2.1 创建工程 打开DTS迁移工具&#xff0c;点击新建工程&#xff0c;填写好工程信息&#xff0c;如图&#xff1a; 2.2 新建迁…...

HTML特殊符号的使用示例

目录 一、基本特殊符号的使用 1、空格符号&#xff1a; 2、小于号 和 大于号&#xff1a; 3、引号&#xff1a; 二、版权、注册商标符号的使用 1、版权符号&#xff1a;© 2、注册商标符号&#xff1a; 三、数学符号的使用 四、箭头符号的使用 五、货币符号的使用…...