一读即懂的神经网络图解指南

简介: 以乐高积木为例,从零构建一个神经网络,以图片的形式展示,保证您能看懂。

按照如下步骤运行代码:
• git clone https://github.com/omar-florez/scratch_mlp/
• python scratch_mlp/scratch_mlp.py

神经网络是线性模型和非线性模型的巧妙组合。选择并连接这些模型,便能获得一个强大的工具来逼近任何一个数学函数,比如一个能够借助非线性决策边界进行分类的神经网络模型。

接下来我们将以乐高积木为例,从零构建一个神经网络,并探究其内部功能。

神经网络就像是由乐高积木搭建而成

overview.png

上图描述了训练一个神经网络常用的数学过程。一个神经网络就是很多模块以不同的目标堆叠而成。

  • 输入变量X会传递进神经网络,它被存储在一个矩阵中,矩阵的行是观测值,列是维度
  • 权重W_1将输入X映射到第一个隐藏层h_1,W_1相当于一个线性核
  • Sigmoid函数使隐藏中的函数落到[0,1]区间,产生一个神经激活的数组,h_1=Sigmoid(WX)

但以上运算仅仅组成了一个线性系统,无法进行非线性建模。通过叠加网络层数,增加网络深度,可以学到微妙的非线性交互,从而解决更加复杂的问题,这也是神经网络模型备受推崇的原因之一。

了解神经网络内部结构有什么用?

如果你对神经网络内部结构有所了解,就能在遇到问题的时候知道如何做出调整,并且能够定制相应的策略来完成对算法的测试。

调试机器学习模型是一项复杂的任务。模型在初期可能并不奏效,在新数据上有着较低的准确率,耗费长时间进行训练,占用过多内存,甚至得到为NAN的预测值……在某些情况下,了解算法的运行机制能够让我们更加轻松的解决任务:

  • 如果训练耗费了太多的时间,可以选择增加minibatch的大小,从而减小观测值的方差,有助于算法收敛
  • 如果得到了NAN值,可能是由于梯度过大导致内存溢出。此时可以考虑降低学习率,减少网络层数或者进行梯度裁剪。

举个例子:学习异或函数

神经网络就像一个黑盒子,现在让我们打开它。从零开始构建一个学习异或函数的神经网络。非线性函数的选择并不是随机的,没有反向传播机制的话很难学会用一条直线分类。

nonlinear_xor.png

网络拓扑很简单,如下:

  • 输入变量X是一个二维向量
  • 权重w_1是具有随机初始化数值的2×3矩阵
  • 隐藏层包含3个神经元,每个神经元接受观测值的加权和作为输入。也就是下图中高亮部分的内积:z_1 = x_1, x_2
  • 权重w_2是具有随机初始化值的3×2的矩阵
  • 输出层h_2包含两个神经元,因为函数的输出要么是0(y_1 = [0,1]),要么是1(y_2 = [1, 0])

直接上图:

overview2.png

接下来训练模型。在上述示例中,可训练的参数就是权重。但是应该了解的是,目前的研究正在探索更多可以被优化的参数模型。例如层与层之间的连接,正则化,残差,学习率等。

反向传播是指:在给定的一批具有标签的观察值上,朝着预先定义的损失函数最小化的方向(梯度)更新权重。

网络初始化
随机初始化网络权重

initialized_network.png

前向传播
其目的主要是把输入变量X向前传递到网络的每一层,直到计算输出层h_2的向量。

以权重w_1为线性核对输入数据X做线性变换:

z1.png

使用Sigmoid激活函数对加权和进行放缩,得到了第一个隐藏层h_1的值。此时,原始的2D向量被映射到了3D空间。

h1.png

得到h_2的过程与之类似。接下来计算第一个隐藏层的加权和z_2,h_1现在是输入数据。

z2.png

然后计算它们的Sigmoid激活函数。向量[0.37166596 0.45414264]代表的是网络对给定数据X计算出的对数概率或者预测向量。

计算整体损失

也就是计算实际值与预测值的差值。损失函数的目标是量化预测向量h_2与标签y,也就是真实值之间的距离,这个距离可以表示误差。

损失函数包括一个正则项,正则项的作用是对较大的权重进行惩罚。因为平方值较大的权重会增大损失函数,而我们的目标是要最小化损失函数。

loss.png

反向传播

反向传播的目标是沿最小化损失函数的方向更新神经网络的权重。这是一个递归过程,它可以重用之前计算出来的梯度,而且严重依赖微分函数。因为这些更新可以减小损失函数,所以神经网络能够通过这个步骤[学会]逼近具有已知类别的观测值的标签。

与前向传播不同的是,这个步骤是沿着反向的顺序进行的。它首先计算出输出层中损失函数对每个权重的偏导数(dLoss/dW2),然后计算隐藏层的偏导数(dLoss/dW1)。

dLoss/dW2:

链式法则表明,我们可以将一个神经网络的梯度计算分解成多个微分部分:

chain_w2.png

下表列出了上面用到的一些函数定义以及它们的一阶导数:

Function First derivative
Loss = (y-h2)^2 dLoss/dW2 = -(y-h2)
h2 = Sigmoid(z2) dh2/dz2 = h2(1-h2)
z2 = h1W2 dz2/dW2 = h1
z2 = h1W2 dz2/dh1 = W2

更直观地,我们在下图中沿着导数链计算三个偏导数,以更新权重w_2(图中蓝色部分)。

update_w2.png

将数值代入到这些偏导数中,就能够计算出w_2的偏导数,如下所示:

chain_w2_detailed.png

最终的结果是一个3×2的矩阵dLoss/dW2,它将会沿着最小化损失函数的方向更新w_2的数值。

chain_w2_numbers.png

dLoss/dW1:

计算用于更新第一个隐藏层w_1权重的链式规则就展现了重复使用已有计算结果的可能。

chain_w11.png

更直观地,从输出层到权重w_1的计算会用到在后面层中已经计算过的偏导数。

update_w2.png

例如,偏导数dLoss/dh_2和dh_2/dz_2在上一节中已经被计算为输出层dLoss/dw_2学习权值的依赖项。

chain_w1_numbers.png

将所有的导数放在一起,就能够再一次执行链式法则,从而更新隐藏层的权重w_1。

chain_w1_numbers_final.png

最后,给权重赋予新的数值,完成对神经网络的一步训练。

copy_values.png

实现

仅使用numpy就可以将上面的数学方程式转换为代码。神经网络在一个循环中进行训练,每次迭代过程会给神经网络传入标准的输入数据。在本例中,我们只考虑每次迭代中的整个数据集。前向传播、损失函数和反向传播的计算都有比较好的泛化。因为我们在每一次循环中都用它们对应的梯度(矩阵dL_dw1和dL_dw2)来更新参数。

代码保存在github中:https://github.com/omar-florez/scratch_mlp

code.png

代码运行

下面展示了一些进行了多次迭代训练得到的能够近似异或函数的神经网络。

左图:准确率;中间的图:学习到的决策边界;右图:损失函数

首先,我们来看一下隐藏层具有3个神经元的神经网络为何能力较弱。这个模型学会了用一个简单的决策边界来进行二分类,这个边界一开始是一条直线,但是后来逐渐表现出了非线性的行为。随着训练的持续,右图的损失函数也明显地减小。

untitled.png

隐藏层拥有50个神经元的神经网络模型学习复杂决策边界的能力明显增强了。这虽然能够得到更准确的结果,但也会使梯度发生爆炸,这是训练神经网络时的一个显著问题。当梯度非常大的时候,反向传播中的连乘会产生很大的更新权重。这就是最后几步训练时损失函数突然增大的原因(step>90)。损失函数的正则项计算出了已经变得很大的权重的平方值(sum(W²)/2N)。

untitled1.png

可以通过减小学习率来减轻上面的问题。通过实现一个能够随着时间减小学习率的策略来实现。或者通过强制执行一个更强的正则化来实现,可能是 L1 或者 L2。


本文由阿里云开发者社区组织翻译。

文章原标题《Explaining the Math of how neural networks learn》

作者:Omar U. Florez

译者:Elaine

文章为简译,更为详细的内容,请查看原文link

相关文章
|
机器学习/深度学习 人工智能 自然语言处理
简述人工智能,及其三大学派:符号主义、连接主义、行为主义
简述人工智能,及其三大学派:符号主义、连接主义、行为主义
7647 0
简述人工智能,及其三大学派:符号主义、连接主义、行为主义
|
10月前
|
机器学习/深度学习 编解码 自然语言处理
SigLIP 2:多语言语义理解、定位和密集特征的视觉语言编码器
SigLIP 2 是一种改进的多语言视觉-语言编码器系列,通过字幕预训练、自监督学习和在线数据管理优化性能。它在零样本分类、图像-文本检索及视觉表示提取中表现卓越,支持多分辨率处理并保持图像纵横比。模型提供 ViT-B 至 g 四种规格,采用 WebLI 数据集训练,结合 Sigmoid 损失与自蒸馏等技术提升效果。实验表明,SigLIP 2 在密集预测、定位任务及多模态应用中显著优于前代和其他基线模型。
889 9
SigLIP 2:多语言语义理解、定位和密集特征的视觉语言编码器
|
10月前
|
文字识别 测试技术 语音技术
看听说写四维突破:Qwen2.5-Omni 端到端多模态模型开源!
今天,通义千问团队发布了 Qwen2.5-Omni,Qwen 模型家族中新一代端到端多模态旗舰模型。该模型专为全方位多模态感知设计,能够无缝处理文本、图像、音频和视频等多种输入形式,并通过实时流式响应同时生成文本与自然语音合成输出。
2217 6
看听说写四维突破:Qwen2.5-Omni 端到端多模态模型开源!
|
10月前
|
机器学习/深度学习 编解码 人工智能
Qwen2.5-VL Technical Report
Qwen2.5-VL是阿里云团队推出的Qwen系列最新旗舰模型,具备显著提升的基础能力和创新功能。它在视觉识别、对象定位、文档解析和长视频理解等方面实现突破,支持精准的边界框/点定位及复杂输入处理。通过技术创新如窗口注意力、动态帧率采样和绝对时间编码,该模型在多模态任务中表现出色,在多个基准测试中超越顶级闭源模型,适用于从边缘AI到高性能计算的广泛场景。
|
Java Spring 容器
深入理解Spring Boot中的容器与依赖注入
深入理解Spring Boot中的容器与依赖注入
|
数据处理 iOS开发 MacOS
Python 虚拟环境安装使用(Anaconda 实操完整版)
【10月更文挑战第4天】Anaconda 是一个开源的 Python 发行版,集成了常用科学计算与数据处理库,并提供了方便的包管理工具 `conda`。虚拟环境则允许在同一台机器上创建多个独立的 Python 运行环境,避免库版本冲突。通过下载 Anaconda、创建与激活虚拟环境、安装软件包及管理环境,可有效支持 Python 项目开发。
2109 8
|
消息中间件 存储 Java
吃透 RocketMQ 消息中间件,看这篇就够了!
本文详细介绍 RocketMQ 的五大要点、核心特性及应用场景,涵盖高并发业务场景下的消息中间件关键知识点。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
吃透 RocketMQ 消息中间件,看这篇就够了!
|
机器学习/深度学习 人工智能 算法
Python中实现简单神经网络
【9月更文挑战第2天】本文将通过Python编程语言,介绍如何从零开始构建一个简单的神经网络。我们将使用纯Python代码,不依赖任何外部库,来展示神经网络的核心概念和工作原理。文章将详细解释每个步骤,并最终实现一个能够进行基本模式识别的神经网络模型。通过这篇文章,读者可以对神经网络有一个直观的理解,并为进一步学习深度学习打下坚实的基础。
|
人工智能 JSON 文字识别
开源VLM新标杆 InternVL 2.0 怎么用?部署、微调尽在魔搭社区!
7月4日下午,世界人工智能大会科学前沿论坛,上海人工智能实验室OpenGVLab发布了InternVL 2.0 版本,中文名书生·万象。
|
机器学习/深度学习 存储 数据可视化
手把手教你绘制和解读实用R列线图(Nomogram):从入门到精通
手把手教你绘制和解读实用R列线图(Nomogram):从入门到精通
3355 1