对神经网络基础的理解

目录

一、《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).T
        hidden_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).T
        hidden_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 += 1
    if(i != 10):  # 可调整数字,逐张识别
        continue
        pass
    all_values = record.split(',')
    correct_label = int(all_values[0])
    inputs = (numpy.asarray(all_values[1:], numpy.float32) / 255.0 * 0.99) + 0.01
    image_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)
        pass

    pass

scorecard_array = numpy.asarray(scorecard)
print("performance = ", scorecard_array.sum() / scorecard_array.size)

四、总结

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SOME/IP--协议英文原文讲解1

前言 SOME/IP协议越来越多的用于汽车电子行业中,关于协议详细完全的中文资料却没有,所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块: 1. SOME/IP协议讲解 2. SOME/IP-SD协议讲解 3. python/C举例调试讲解 一、SOM…

移动光猫怎么自己改桥接模式?

环境: 型号H3-8s 问题描述: 家里宽带用的是H3-8s 光猫,想改桥接模式。 解决方案: 1.默认管理员账号和密码: 账号:CMCCAdmin 密码:aDm8H%MdAWEB页面我试了登陆不了,显示错误 …

2D 超声心动图视频到 3D 心脏形状重建的临床应用| 文献速递-医学影像人工智能进展

Title 题目 2D echocardiography video to 3D heart shape reconstruction for clinicalapplication 2D 超声心动图视频到 3D 心脏形状重建的临床应用 01 文献速递介绍 超声心动图是心血管医学中一种至关重要且广泛应用的影像学技术,利用超声波技术捕捉心脏及其…

web端ActiveMq测试工具

如何用vue3创建简单的web端ActiveMq测试工具? 1、复用vue3模板框架 创建main.js,引入APP文件,createApp创建文件,并加载element插件,然后挂载dom节点 2、配置vue.config.js脚本配置 mport { defineConfig } from "vite&qu…

STM32 GPIO配置 点亮LED灯

本次是基于STM32F407ZET6做一个GPIO配置,实现点灯实验。 新建文件 LED.c、LED.h文件,将其封装到Driver文件中。 双击Driver文件将LED.c添加进来 编写头文件,这里注意需要将Driver头文件声明一下。 在LED.c、main.c里面引入头文件LED.h LED初…

DroneXtract:一款针对无人机的网络安全数字取证工具

关于DroneXtract DroneXtract是一款使用 Golang 开发的适用于DJI无人机的综合数字取证套件,该工具可用于分析无人机传感器值和遥测数据、可视化无人机飞行地图、审计威胁活动以及提取多种文件格式中的相关数据。 功能介绍 DroneXtract 具有四个用于无人机取证和审…

用Python和PyQt5打造一个股票涨幅统计工具

在当今的金融市场中,股票数据的实时获取和分析是投资者和金融从业者的核心需求之一。无论是个人投资者还是专业机构,都需要一个高效的工具来帮助他们快速获取股票数据并进行分析。本文将带你一步步用Python和PyQt5打造一个股票涨幅统计工具,不…

大模型正确调用方式

1、ollama 安装 curl -fsSL https://ollama.com/install.sh | sh 如果是AutoDl服务器,可以开启学术加速。 source /etc/network_turbo 本次使用腾讯云Cloud Studio,所以已经安装好了 Ollama 2、启动 ollama run 模型的名字 ollama serve # 开启服务 olla…

计算机网络 (62)移动通信的展望

一、技术发展趋势 6G技术的崛起 内生智能:6G将强调自适应网络架构,通过AI驱动的智能算法提升通信能力。例如,基于生成式AI的6G内生智能架构将成为重要研究方向,实现低延迟、高效率的智能通信。信息编码与调制技术:新型…

KVM/ARM——基于ARM虚拟化扩展的VMM

1. 前言 ARM架构为了支持虚拟化做了些扩展,称为虚拟化扩展(Virtualization Extensions)。原先为VT-x创建的KVM(Linux-based Kernel Virtual Machine)适配了ARM体系结构,引入了KVM/ARM (the Linux ARM hypervisor)。KVM/ARM没有在hypervisor中引入复杂的…

python:taichi 模拟一维波场

在 Taichi 中模拟一维波场,通常是利用 Taichi 编程语言的特性来对一维空间中的波动现象进行数值模拟,以下是相关介绍: 原理基础 波动方程:一维波动方程的一般形式为 ,其中 u(x,t) 表示在位置x 和时间t 处的波的状态&…

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

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

视觉语言模型 (VLMs):跨模态智能的探索

文章目录 一. VLMs 的重要性与挑战:连接视觉与语言的桥梁 🌉二. VLMs 的核心训练范式:四种主流策略 🗺️1. 对比训练 (Contrastive Training):拉近正例,推远负例 ⚖️2. 掩码方法 (Masking):重构…

java8-日期时间Api

目录 LocalDate更新时间LocalTimeLocalDateTimeInstantPeriod Duration格式化、解析日期-时间对象时区 java.util.Date java.util.Calendar 不支持时区 线程不安全 月份从0起线程不安全,只有包裹在ThreadLocal中才安全 java.text.DateFormat java.text.SimpleDateFo…

深度学习 Pytorch 动态计算图与梯度下降入门

在上节末尾我们发现autograd.grad函数可以灵活进行函数某一点的导数和偏导数的运算,但微分运算只是AutoGrad模块中的一小部分功能,本节将继续讲解这个模块的其他常用功能,并在此基础上介绍另一个常用优化算法:梯度下降算法。 imp…

FreeRtos的使用教程

定义: RTOS实时操作系统, (Real Time Operating System), 指的是当外界事件发生时, 能够有够快的响应速度,调度一切可利用的资源, 控制实时任务协调一致的运行。 特点: 支持多任务管理, 处理多个事件, 实现更复杂的逻辑。 与计算…

大话特征工程:1.维数灾难与特征轮回

一、维度深渊 公元 2147 年,人类文明进入了数据驱动的超级智能时代。从金融到医疗,从教育到娱乐,所有决策都仰赖“全维计算网络”(高维特征空间)。这套系统将全球所有信息抽象成数以亿计的多维特征&#xff08…

从ai产品推荐到利用cursor快速掌握一个开源项目再到langchain手搓一个Text2Sql agent

目录 0. 经验分享:产品推荐 1. 经验分享:提示词优化 2. 经验分享:使用cursor 阅读一篇文章 3. 经验分享:使用cursor 阅读一个完全陌生的开源项目 4. 经验分享:手搓一个text2sql agent (使用langchain l…

《STL基础之hashtable》

【hashtable导读】STL为大家提供了丰富的容器,hashtable也是值得大家学习和掌握的基础容器,而且面试官经常会把它和hashmap混在一起,让同学们做下区分。因此关于hashtable的一些特性,比如:底层的数据结构、插入、查找元…

本地大模型编程实战(02)语义检索(2)

文章目录 准备按批次嵌入加载csv文件,分割文档并嵌入测试嵌入效果总结代码 上一篇文章: 本地大模型编程实战(02)语义检索(1) 详细介绍了如何使用 langchain 实现语义检索,为了演示方便,使用的是 langchain 提供的内存数据库。 在实…