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

《深度学习入门:基于python的理论与实现》观后感

捞点干的

第一章:python入门

已经掌握了 Python、NumPy、 Matplotlib 等知识的读者,可以跳过本章
跳过了1.1python的介绍

1.2python 的安装

1.2.1 python的版本

自行下载 python3.x

1.2.2 使用的外部库

NumPyMatplotlib
NumPy 是用于数值计算的库,提供了很多高级的数学算法和便利的数 组(矩阵)操作方法。本书中将使用这些便利的方法来有效地促进深度学习 的实现。
Matplotlib 是用来画图的库。使用 Matplotlib 能将实验结果可视化,并 在视觉上确认深度学习运行期间的数据。

1.2.3 Anaconda发行版

下一个 Anaconda 会让你简单很多

1.3 python解释器

安装后,确实版本, 打开终端, 若是windows则打开命令行窗口, 输入python --version 会显示已经安装的python版本
在这里插入图片描述
这里就是正确安装了,接着输入 python 启动python解释器在这里插入图片描述python是对话模式, 你问一句, python回一句,例如:
在这里插入图片描述

1.3.1 算术计算

加减乘除
在这里插入图片描述

*表示乘法,/表示除法,表示乘方(32是3的2次方)。

1.3.2 数据类型

常见的查看类型的手段就是type()
在这里插入图片描述

1.3.3 变量

用x或y 等字母,单词来定义变量(variable)。 可以使用变量进行计算, 也可以赋值
在这里插入图片描述

Python 是属于“动态类型语言”的编程语言,所谓动态,是指变量的类 型是根据情况自动决定的。在上面的例子中,用户并没有明确指出“x 的类 型是 int(整型)”,是 Python 根据 x 被初始化为 10,从而判断出 x 的类型为 int 的。此外,我们也可以看到,整数和小数相乘的结果是小数(数据类型的 自动转换)。另外,“#”是注释的意思,它后面的文字会被 Python 忽略。

1.3.4 列表

元素的访问是通过 a[0] 这样的方式进行的。[] 中的数字称为索引(下标), 索引从 0 开始(索引 0 对应第一个元素)。此外,Python 的列表提供了切片 (slicing)这一便捷的标记法。使用切片不仅可以访问某个值,还可以访问列表的子列表(部分列表)。

进行列表的切片时,需要写成 a[0:2] 这样的形式。a[0:2] 用于取出从索 引为 0 的元素到索引为 2 的元素的前一个元素之间的元素。另外,索引 −1 对 应最后一个元素,−2 对应最后一个元素的前一个元素。

1.3.5 字典

列表根据索引,按照 0, 1, 2, . . . 的顺序存储值,而字典则以键值对的形式存储数据。字典就像《新华字典》那样,将单词和它的含义对应着存储起来。

1.3.6 布尔型

Python 中有 bool 型。bool 型取 True 或 False 中的一个值。针对 bool 型的 运算符包括 and、or 和 not(针对数值的运算符有 +、-、*、/ 等,根据不同的 数据类型使用不同的运算符)。

1.3.7 if语句

根据不同的条件选择不同的处理分支时可以使用 if/else 语句。
在这里插入图片描述

Python中的空白字符具有重要的意义。上面的if语句中,if hungry:下面 的语句开头有4个空白字符。它是缩进的意思,表示当前面的条件(if hungry) 成立时,此处的代码会被执行。这个缩进也可以用 tab 表示,Python 中推荐 使用空白字符。

1.3.8 for 语句

进行循环处理时可以使用 for 语句
在这里插入图片描述
这是输出列表[1,2,3]中的元素的例子。使用for … in … :语句结构,可以按顺序访问列表等数据集合中的各个元素。

1.3.9 函数

可以将一连串的处理定义成函数(function)

在这里插入图片描述

此外,函数可以取参数。
另外,字符串的拼接可以使用 +。

1.4 python 脚本文件

到目前为止,我们看到的都是基于 Python 解释器的例子。Python 解释 器能够以对话模式执行程序,非常便于进行简单的实验。但是,想进行一 连串的处理时,因为每次都需要输入程序,所以不太方便。这时,可以将 Python 程序保存为文件,然后(集中地)运行这个文件。下面,我们来看一 个 Python 脚本文件的例子。

1.4.1 保存文件

保存文件为1.py , 然后在命令行中执行 python 1.py。 就可以了

1.4.2 类

前面我们了解了int和str等数据类型(通过type()函数可以查看对象的 类型)。这些数据类型是“内置”的数据类型,是 Python 中一开始就有的数 据类型。现在,我们来定义新的类。如果用户自己定义类的话,就可以自己 创建数据类型。此外,也可以定义原创的方法(类的函数)和属性。
Python 中使用 class 关键字来定义类,类要遵循下述格式(模板)。
在这里插入图片描述
这里有一个特殊的 init 方法,这是进行初始化的方法,也称为构造 函数(constructor), 只在生成类的实例时被调用一次。此外,在方法的第一 个参数中明确地写入表示自身(自身的实例)的 self 是 Python 的一个特点(学 过其他编程语言的人可能会觉得这种写 self 的方式有一点奇怪)
简单创建一个类,跑一下
在这里插入图片描述

这里我们定义了一个新类 People。上面的例子中,类 People 生成了实例(对象)p
People 的 构 造 函 数(初 始 化 方 法)会 接 收 参 数 name , 然 后 用 这 个 参 数 初 始 化实例变量 self.name。实例变量是存储在各个实例中的变量。Python 中可 以像 self.name 这样,通过在 self 后面添加属性名来生成或访问实例变量

1.5 Numpy

在深度学习的实现中,经常出现数组和矩阵的计算。NumPy 的数组类 (numpy.array)中提供了很多便捷的方法,在实现深度学习时,我们将使用这些方法。本节我们来简单介绍一下后面会用到的 NumPy。

1.5.1 导入Numpy

NumPy 是外部库。这里所说的“外部”是指不包含在标准版 Python 中。 因此,我们首先要导入 NumPy 库。
在这里插入图片描述

Python中使用import语句来导入库。这里的import numpy as np,直 译的话就是“将 numpy 作为 np 导入”的意思。通过写成这样的形式,之后 NumPy 相关的方法均可通过 np 来调用。

1.5.2 生成numpy 数组

要生成 NumPy 数组,需要使用 np.array() 方法。np.array() 接收 Python列表作为参数,生成 NumPy 数组(numpy.ndarray)。
在这里插入图片描述

1.5.3 numpy的算术运算

直接举例
在这里插入图片描述

这里需要注意的是,数组 x 和数组 y 的元素个数是相同的(两者均是元素 个数为 3 的一维数组)。当 x 和 y 的元素个数相同时,可以对各个元素进行算 术运算。如果元素个数不同,程序就会报错,所以元素个数保持一致非常重要。 另外,“对应元素的”的英文是 element-wise,比如“对应元素的乘法”就是 element-wise product。
NumPy 数组不仅可以进行 element-wise 运算,也可以和单一的数值(标量)组合起来进行运算。此时,需要在 NumPy 数组的各个元素和标量之间进行运算。这个功能也被称为广播(详见后文)。

在这里插入图片描述

1.5.3 numpy 的N维数组

NumPy 不仅可以生成一维数组(排成一列的数组),也可以生成多维数组。比如,可以生成如下的二维数组(矩阵)。
在这里插入图片描述

这里生成了一个2*3 的矩阵, 矩阵的形状可以通过shape 查看, 类型可以通过 dtype 查看

以下是一些常见的dtype表示法:
i1: 带符号整数,占用1个字节(8位)
i2: 带符号整数,占用2个字节(16位)
i4: 带符号整数,占用4个字节(32位)
u1: 无符号整数,占用1个字节(8位)
u2: 无符号整数,占用2个字节(16位)
u4: 无符号整数,占用4个字节(32位)
f4: 浮点数,占用4个字节(32位)
f8: 浮点数,占用8个字节(64位)
b: 布尔值

在这里插入图片描述

计算最好还是用数字类型
和数组的算术运算一样,矩阵的算术运算也可以在相同形状的矩阵间以 对应元素的方式进行。并且,也可以通过标量(单一数值)对矩阵进行算术运算。 这也是基于广播的功能。
在这里插入图片描述

NumPy 数组(np.array)可以生成 N 维数组,即可以生成一维数组、 二维数组、三维数组等任意维数的数组。数学上将一维数组称为向量, 将二维数组称为矩阵。另外,可以将一般化之后的向量或矩阵等统 称为张量(tensor)。本书基本上将二维数组称为“矩阵”,将三维数 组及三维以上的数组称为“张量”或“多维数组”。

1.5.5 广播

NumPy 中,形状不同的数组之间也可以进行运算。之前的例子中,在 2×2 的矩阵 x 和标量 10 之间进行了乘法运算。在这个过程中,如图 1-1 所示, 标量 10 被扩展成了 2 × 2 的形状,然后再与矩阵 A 进行乘法运算。这个巧妙 的功能称为广播(broadcast)。
在这里插入图片描述
再来一个广播的例子
在这里插入图片描述
在这个运算中,如图 1-2 所示,一维数组 B 被“巧妙地”变成了和二位数 组 A 相同的形状,然后再以对应元素的方式进行运算。
在这里插入图片描述

综上,因为 NumPy 有广播功能,所以不同形状的数组之间也可以顺利 地进行运算。

1.5.6 访问元素

元素的索引从 0 开始。对各个元素的访问可按如下方式进行。
在这里插入图片描述
也可以用for 循环遍历
在这里插入图片描述
除了前面介绍的索引操作,NumPy 还可以使用数组访问各个元素。
在这里插入图片描述
运用这个标记法,可以获取满足一定条件的元素。例如,要从 X 中抽出 大于 10 的元素,可以写成如下形式。
在这里插入图片描述
对NumPy数组使用不等号运算符等(上例中是X > 10),结果会得到一个 布尔型的数组。上例中就是使用这个布尔型数组取出了数组的各个元素(取 出 True 对应的元素)。

Python 等动态类型语言一般比 C 和 C++ 等静态类型语言(编译型语言) 运算速度慢。实际上,如果是运算量大的处理对象,用 C/C++ 写程 序更好。为此,当 Python 中追求性能时,人们会用 C/C++ 来实现 处理的内容。Python 则承担“中间人”的角色,负责调用那些用 C/ C++ 写的程序。NumPy 中,主要的处理也都是通过 C 或 C++ 实现的。 因此,我们可以在不损失性能的情况下,使用 Python 便利的语法。

1.6 Matplotlib

在深度学习的实验中,图形的绘制和数据的可视化非常重要。Matplotlib 是用于绘制图形的库,使用 Matplotlib 可以轻松地绘制图形和实现数据的可 视化。这里,我们来介绍一下图形的绘制方法和图像的显示方法。

1.6.1 绘制简单图形

可以使用 matplotlib 的 pyplot 模块绘制图形。绘制 sin 函数曲线的例子。
在这里插入图片描述
这里使用NumPy的arange方法生成了[0, 0.1, 0.2, …, 5.8, 5.9]的 数据,将其设为 x。对 x 的各个元素,应用 NumPy 的 sin 函数 np.sin(),将 x、 y 的数据传给 plt.plot 方法,然后绘制图形。最后,通过 plt.show() 显示图形。 运行上述代码后,就会显示展示图。

1.6.2 pyplot的功能

在刚才的 sin 函数的图形中,我们尝试追加 cos 函数的图形,并尝试使用 pyplot 的添加标题和 x 轴标签名等其他功能
在这里插入图片描述
在这里插入图片描述

1.6.3 显示图像

pyplot中还提供了用于显示图像的方法imshow()。另外,可以使用 matplotlib.image 模块的 imread() 方法读入图像。下面我们来看一个例子
在这里插入图片描述
这里,我们假定图像 9.png 在当前目录下。根据自己的环境,需要变更文件名或文件路径。

1.7

本章重点介绍了实现深度学习(神经网络)所需的编程知识,以为学习 深度学习做好准备。从下一章开始,我们将通过使用 Python 实际运行代码, 逐步了解深度学习。
本章只介绍了关于 Python 的最低限度的知识,想进一步了解 Python 的 读者,可以参考下面这些图书。
首先推荐《Python语言及其应用》一书。 这是一本详细介绍从 Python 编程的基础到应用的实践性的入门书。
关于 NumPy,《利用 Python 进行数据分析》 一书中进行了简单易懂的总结。
此 外,Scipy Lecture Notes 这个网站上也有以科学计算为主题的 NumPy 和 Matplotlib 的详细介绍,有兴趣的读者可以参考。
下面,总结一下本章所学的内容,如下所示。
• Python是一种简单易记的编程语言。
• Python是开源的,可以自由使用。
• 本书中将使用Python 3.x实现深度学习。
• 本书中将使用NumPy和Matplotlib这两种外部库。
• Python有“解释器”和“脚本文件”两种运行模式。
• Python能够将一系列处理集成为函数或类等模块。
• NumPy中有很多用于操作多维数组的便捷方法。

第二章 感知机

感知机(perceptron)这一算法。感知机是由美国学者 Frank Rosenblatt 在 1957 年提出来的。为何我们现在还要学习这一很久以前就有 的算法呢?因为感知机也是作为神经网络(深度学习)的起源的算法。因此, 学习感知机的构造也就是学习通向神经网络和深度学习的一种重要思想。
本章我们将简单介绍一下感知机,并用感知机解决一些简单的问题。希望读者通过这个过程能熟悉感知机。

2.1感知机是什么

感知机接收多个输入信号, 输出 一个信号。这里说的信号 可以想象成电流或河流那样具备流动性的东西, 像电流穿过导线,向前方输送电子一样, 感知机的信号也会形成流, 像前方输送信息, 但是,和实际的电力不同的是, 感知机的信号只有流/不流(1/0)两种取值, 本书中 0代表不传递信号,1代表传递信号
在这里插入图片描述
上图是一个接收两个输入信号的感知机例子。x1 和 x2 是输入信号,y是输出信号,w1和w2 是权重(w 是weight 的首字母)。图中的O 称为“神经元“ 或者”节点“。输入信号被送往神经元时,会被分别乘以固定的权重(w1x1,w2x2)。神经元会计算传送过来的信号的总和, 只有当这个总和超过了某个界限值时,才会输出1,这也称为”神经元被激活“。这里讲这个界限称为阀值,用符号θ来表示
感知机的运行原理只有这些~吧上述内容用数学式来表示就是下图
在这里插入图片描述
感知机的多个输入信号都有各自固有的权重, 这些权重发挥着控制各个信号的重要性作用, 也就是说, 权重越大,对应该权重的信号的重要性就越高

权重相当于电流里所说的电阻, 电阻是决定电流流动难度的参数,电阻越低,通过的电流就越大。而感知机的权重则是值越大通过的信号就越大,不管是电阻还是权重,在控制信号流动难度(或者说流动容易度)这一点上的作用都是一样的

2.2 简单逻辑电路

2.2.1 与门

现在让我们考虑用感知机来解决简单的问题。这里首先以逻辑电路为题材来思考一下与门(AND gate)。与门是有2个输入和一个输出的门电路,下图是这种输入信号和输出信号的对应表称为真值表。如图所示,与门仅在两个输入均为1的时候输出1,其他时候输出 0
在这里插入图片描述
下面考虑用感知机来表示这个与门。 需要做的就是断定能满足上图的真值表的w1,w2,θ的值。那么, 设定什么样的值才能制作出满足条件的感知机呢?
实际上,满足条件的参数的选择方法有无数个,比如当(w1,w2,θ)=(0.5,0.5,0.7)时,可以满足(0.5,0.5,0.8)或者(1.0,1.0,1.0)时同样满足条件,设定这样的参数后,近当x1和x2同时为1时,信号的加权总和才会超过给定的阀值 θ

2.2.2 与非门和或门

接着,我们再来考虑下与非门(NAND gate) 。NAND是not AND的意思, 与非门就是颠倒了与门的输出。用真值便是的话如下图所示, 仅当x1和x2 同时为1时输出0,其他时候输出1,那么与非门的参数又可以时什么样的组合呢?
在这里插入图片描述
要表示与非门, 可以用 (w1,w2,θ)=(-0.5,-0.5,-0.7)这样的组合。实际上, 只要把实现与门的参数值的符号取反。就可以实现与非门。
接下来看一下下图所示的或门。或门是“只要有一个输入信号是1,输出就为1”的逻辑电路。那么我们来思考下,应该为这个或门设定什么样的参数呢
在这里插入图片描述
如上所示,我们已经知道使用感知机可以表示与门、与非门、或门的逻 辑电路。这里重要的一点是:与门、与非门、或门的感知机构造是一样的。 实 际 上 , 3 个 门 电 路 只 有 参 数 的 值(权 重 和 阈 值)不 同 。 也 就 是 说 , 相 同 构 造 的感知机,只需通过适当地调整参数的值,就可以像“变色龙演员”表演不 同的角色一样,变身为与门、与非门、或门。

这里决定感知机参数的并不是计算机,而是我们人。我们看着真值 表这种“训练数据”,人工考虑(想到)了参数的值。而机器学习的课 题就是将这个决定参数值的工作交由计算机自动进行。学习是确定 合适的参数的过程,而人要做的是思考感知机的构造(模型),并把 训练数据交给计算机。

2.3感知机的实现

2.3.1 简单的实现

现在, 我们用Python 来实现刚才的逻辑电路, 这里, 先定义一个接收参数x1x2AND 函数.
在这里插入图片描述
初始化参数 w1,w2,thera, 当输入的加权总和超过阀值时返回1 否则返回0。打印输出下结果

在这里插入图片描述
和预想一样, 这样我们就实现了与门, 我们自然可以实现与非门和或门,

2.3.2导入权重和偏执

刚才的与门的实现比较直接, 容易理解,但是考虑到后面的事情,我们将其修改为另外一种的实现形式, 在此之前, 首先先把, θ换成-b, 于是我们就可以用数学式来表示感知机的行为
在这里插入图片描述
此处 b 称为偏置, w1和w2称为权重, 感知机会计算输入信号和权重的乘积,然后加上偏置,如果值大于0则输出1 反之输出0, 下面我门使用numpy ,来上面的方式来实现感知机, 我们用python解释器逐步确认结果
在这里插入图片描述
如图所示,在numpy数组的乘法运算中, 当两个数组的元素个数相同时,各个元素分别相乘,因此w*x的结果就是他们的各个元素分别相乘([0,1]*[0.5,0.5]=>[0,0.5])。之后,np.sum(w*x)再计算想趁狗的各个元素的总和,最后再把偏置加到这个总和上, 就完成了 ,上述式子的运算。

2.3.3 使用权重和偏置的实现

使用权重和偏置,可以像下面这样实现与门
在这里插入图片描述
这里把 − θ 命名为偏置 b,但是请注意,偏置和权重 w1、w2 的作用是不 一样的。具体地说,w1w2 是控制输入信号的重要性的参数,而偏置是调 整神经元被激活的容易程度(输出信号为 1 的程度)的参数。比如,若 b−0.1,则只要输入信号的加权总和超过 0.1,神经元就会被激活。但是如果 b−20.0,则输入信号的加权总和必须超过 20.0,神经元才会被激活。像这样, 偏置的值决定了神经元被激活的容易程度。另外,这里我们将 w1 和 w2 称为权重, 将 b 称为偏置,但是根据上下文,有时也会将 b、w1、w2 这些参数统称为权重。

偏置这个术语,有“穿木屐” 的效果,即在没有任何输入时(输入为 0 时 ), 给 输 出 穿 上 多 高 的 木 屐 ( 加 上 多 大 的 值 ) 的 意 思 。 实 际 上 , 在 式(2.2) 的b+w1x1 +w2x2的计算中,当输入x1和x2为0时,只输出 偏置的值。

接着,我们继续实现与非门和或门。
在这里插入图片描述
在这里插入图片描述
我们在 2.2 节介绍过,与门、与非门、或门是具有相同构造的感知机, 区别只在于权重参数的值。因此,在与非门和或门的实现中,仅设置权重和 偏置的值这一点和与门的实现不同。

2.4 感知机的局限性

到这里我们已经知道,使用感知机可以实现与门、与非门、或门三种逻辑电路, 现在我们来考虑下异或门(XOR gate)

2.4.1 异或门

异或门也被称为逻辑异或电路, 如下图所示, 仅当x1或x2中的一方为1时, 才会输出1(“异或”是拒绝其他的意思)。那么,要用感知机实现这个疑惑门的话,应该设定什么样的权重参数呢?
在这里插入图片描述
实际上,用前面介绍的感知机是无法实现这个异或门的。为什么用感知 机可以实现与门、或门,却无法实现异或门呢?下面我们尝试通过画图来思 考其中的原因。
首先,我们试着将或门的动作形象化。或门的情况下,当权重参数 (b, w1, w2) = (−0.5, 1.0, 1.0) 时,可满足真值表条件。此时,感知机 可用下面的式表示
在这里插入图片描述
表示的感知机会生成由直线−0.5+x1 +x2 =0分割开的两个空间。其中一个空间输出 1,另一个空间输出 0,如下图 所示。
在这里插入图片描述

或门在 (x1, x2) = (0, 0) 时输出 0,在 (x1, x2) 为 (0, 1)、(1, 0)、(1, 1) 时输 出 1。上图中,○表示 0,△表示 1。如果想制作或门,需要用直线将上图中的○和△分开, 实际上, 刚才那条支线就将这4个点正确的分开了
那么,换成异或门的话会如何呢?能否像或门那样,用一条直线作出分割下图中的○和△的空间呢?
在这里插入图片描述
想要用一条直线将上图 中的○和△分开,无论如何都做不到。事实上,用一条直线是无法将○和△分开的。

2.4.2 线性和非线性

上图中○和△无法用一条直线分开, 但是如果将直线这个限制条件去掉, 就可以实现了, 比如,我们可以像下图那样, 用一条曲线分开在这里插入图片描述
感知机的局限性就在于它只能表示由一条直线分割的空间, 像上图这样的弯曲的曲线无法用感知机表示, 另外像这种曲线分割而成发空间称为非线性空间,由直线分割而成的空间称之为线性空间.线性、非线性这两个数据在机械学习领域非常常见,

2.5 多层感知机

感知机不能表示异或门让人深感遗憾, 但是也无需悲观, 实际上, 感知机的绝妙之处在于它可以叠加层(通过叠加层来表示异或门是本节的要点)。这里,我们暂且不考虑叠加层具体是指什么,先从其他视角来思考一下异或 门的问题。

2.5.1 已有门电路的组合

疑惑门的制作方法有很多 , 其中之一就是组合我们前面做好的与门、与非门、或门进行配置, 这里我门用下图来表示 , 其中 非门前端的表反转输出的意思。
在这里插入图片描述
那么,请思考一下,要实现异或门的话,需要如何配置与门、与非门和 或门呢?这里给大家一个提示,用与门、与非门、或门代替下图中的各个“?”,就可以实现异或门。
在这里插入图片描述

2.4 节讲到的感知机的局限性,严格地讲,应该是“单层感知机无法 表示异或门”或者“单层感知机无法分离非线性空间”。接下来,我们将看到通过组合感知机(叠加层)就可以实现异或门。

异或门可以通过下图所示的配置来实现, 这里 x1x2表示输入信号, y 表示输出信号。 x1x2是与非门和或门的输入,而与非门和或门的输出则是与门的输入
在这里插入图片描述
现在我们来确认下, 上图的配置是否真正实现了异或门。这里把s1作为与非门的输出,把s2作为或门的输出,填入真值表中。结果如下图所示,观察 x1、x2、y,可以发现确实符合异或门的输出。
在这里插入图片描述

2.5.2 疑惑门的 实现

下面我们试着用python 来实现这个异或门。使用之前定义的AND函数、NAND函数、OR函数,可以像下面轻松的实现。
在这里插入图片描述

这样,异或门的实现就完成了。下面我们试着用感知机的表示方法(明 确地显示神经元)来表示这个异或门,结果如图所示。
在这里插入图片描述
如图所示,异或门是一种多层结构的神经网络。这里,将最左边的 一列称为第 0 层,中间的一列称为第 1 层,最右边的一列称为第 2 层。
如图所示的感知机与前面介绍的与门、或门的感知机形状不同。实际上,与门、或门是单层感知机,而异或门是 2 层感知机。叠加了多层的感知机也称为多层感知机(multi-layered perceptron)。

图中的感知机总共由 3 层构成,但是因为拥有权重的层实质 上只有2层(第0层和第1层之间,第1层和第2层之间),所以称 为“2 层感知机”。不过,有的文献认为上图的感知机是由 3 层 构成的,因而将其称为“3 层感知机”。

如图所示的 2 层感知机中,先在第 0 层和第 1 层的神经元之间进行 信号的传送和接收,然后在第 1 层和第 2 层之间进行信号的传送和接收,具 体如下所示。

  1. 第 0 层的两个神经元接收输入信号,并将信号发送至第 1 层的神经元。
  2. 第 1 层的神经元将信号发送至第 2 层的神经元,第 2 层的神经元输出 y。

这种 2 层感知机的运行过程可以比作流水线的组装作业。第 1 段(第 1 层) 的工人对传送过来的零件进行加工,完成后再传送给第 2 段(第 2 层)的工人。 第 2 层的工人对第 1 层的工人传过来的零件进行加工,完成这个零件后出货(输出)。
像这样,在异或门的感知机中,工人之间不断进行零件的传送。通过这样的结构(2层结构),感知机得以实现异或门。这可以解释为“单层感知机无法表示的东西,通过增加一层就可以解决”。也就是说,通过叠加层(加深层),感知机能进行更加灵活的表示。

2.6 从与非门到计算机(就是一个概念没啥干货)

多层感知机可以实现比之前见到的电路更复杂的电路。比如,进行加法运算的加法器也可以用感知机实现。此外,将二进制转换为十进制的编码器、满足某些条件就输出1的电路(用于等价检验的电路)等也可以用感知机表示。实际上, 使用感知机甚至可以表示计算机!
计算机是处理信息的机器, 向计算机中输入一些信息后,它会按照某种既定的方法进行处理,然后输出结果。 所谓“按照某种既定的方法进行处理”是指计算机和感知机一样, 也有输入和输出,会按照某个既定的规则进行计算
人们一般会认为计算机内部进行的处理非常复杂, 而令人惊讶的是,实际上只需要通过与非门的组合,就能在线计算机进行处理。这一令人吃惊的实事说明了什么呢?说明使用感知机也可以表示计算机, 前面介绍了,与非门可以使用感知机实现,。 也就是说如果通过组合与非门可以实现计算机的话, 那么通过组合感知机也可以表示计算机(感知机的组合可以通过叠加了多层的单层感知机来表示)。

说到仅通过与非门的组合就能实现计算机,大家也许一下子很难相信。建议有兴趣的读者看一下《计算机系统要素:从零开始构建现代计算机》。这本书以深入理解计算机为主题。论述了通过NAND构建可运行俄罗斯方块的计算机的过程。此书能让读者真实体会到,通过简单的NAND 元件就可以实现计算机这样的复杂的系统

综上,多层感知机能够进行复杂的表示,甚至可以构建计算机。那么,什么构造的感知机才能表示计算机呢?层级多深才可以构建计算机呢?
理论上可以说2层感知机就能构建计算机。这是因为,已有研究证明,2层感知机(严格的说是激活函数使用了非线性的sigmoid函数的感知机,具体参考下一章)可以表示任意函数。但是,使用2层感知机的构造,通过设定合适的权重来构建计算机是一件非常累人的事情。实际上,在用与非门等底层的元件构建计算机的情况下,分阶段地制作所需的零件(模块)会比较自然,即先实现与门和或门,然后实现半加器和全加器,接着实现算数逻辑但愿(ALU),然后实现CPU。因此,通过感知机表示计算机时,使用叠加了多层的构造来实现时比较自然的流程。
本书中不会实际来实现计算机,但是希望读者能够记住,感知机通过叠 加层能够进行非线性的表示,理论上还可以表示计算机进行的处理。

2.7 小结

本章我们学习了感知机。感知机是一种非常简单的算法,大家应该很快 就能理解它的构造。感知机是下一章要学习的神经网络的基础,因此本章的 内容非常重要。
本章所学的内容
• 感知机是具有输入和输出的算法。给定一个输入后,将输出一个既 定的值。
• 感知机将权重和偏置设定为参数。
• 使用感知机可以表示与门和或门等逻辑电路。
• 异或门无法通过单层感知机来表示。
• 使用2层感知机可以表示异或门。
• 单层感知机只能表示线性空间,而多层感知机可以表示非线性空间。
• 多层感知机(在理论上)可以表示计算机。

第三章 神经网络

上一章我们学习了感知机。关于感知机,既有好消息,也有坏消息。好消息是,即便队友复杂的函数,感知机也隐含着能够表示他的可能性。上一章已经介绍过,即便是计算机进行复杂的处理,感知机(理论上)也可以将其表示出来。坏消息是,设定权重的工作, 即确定合适的、能符合预期的输入与输出的权重,现在还是由人工进行的。上一章中,我们结合与门、或门的真值表 人工决定了合适的权重
神经网络的出现就是为了解决刚才的坏消息。具体地讲,神经网络的一个重要性质是它可以自动地从数据中学习到合适的权重参数。本章中,我们会先介绍神经网络的该要概要,然后重点关注神经网络进行识别时的处理。在下一章中,我们将了解如何从数据中学习权重参数。

3.1 从感知机到神经网络

神经网络和上一章介绍的感知机有很多共同点。这里,我们主要以两者的差异为中心,来介绍神经网络的结构

3.1.1 神经网络的例子

用图来表示神经网络的话, 如下图所示。我们吧最左边的一列称为输入层,最右边一列称之为输出层,中间的一列称之为中间层。中间层有时也称为隐藏层。隐藏一词的意思是,隐藏层的神经元(和输入层、输出层不同)肉眼看见。另外,本书吧输入层到输出层依次称为第零层、第一层、第二层(层号之所以从0开始,是为了方便后面基于Python进行实现),下图中第0层对应输入层,第一层对应中间层,第二层对应输入层。
在这里插入图片描述

上图中的网络一共由3层神经元构成,但实质上只有2层神经元有权重,因此将其称为“2层网络”,请注意,有的书也会根据构成网络的层数, 把它称之为“3层网络”。本书将根据实质上拥有权重的层数(输入层、隐藏层、输出层的总数减去1后的数量)来表示网络的名称。

只看上图的话,神经网络的形状类似于上一章的感知机,实际上,就神经元的连接方式而言,与上一章的感知机并没有任何差异。那么,神经网络中的信号时如何传递的呢 ?

3.1.2 复习感知机

在观察神经网络中信号的传递方法之前,我们现复习一下感知机。现在来思考一下下图的网络结构
在这里插入图片描述
图中的感知机接受了x1x2两个输入信号,输出y。如果用数学式来表示的话就是
在这里插入图片描述
b是被称为偏置的参数,用于控制神经元被激活的容易程度;而w1w2是表示各个信号权重的参数,用于控制各个信号的重要性。
顺便提一下,在上上图中的网络中, 偏置b并没有被画出来,如果要明确表示出b,可以像下图那样做。添加了权重为b的输入信号1。这个感知机将x1x21三个信号作为神经元的输入,将其和各自的权重相乘后,传送至下一个神经元,在下一个神经元中,计算这些加权信号的总和。如果总和超过0则输出1,否则输出0.另外,由于偏置的输入信号一直是1,所以为了区分其他神经元, 我们在图中把这个神经元涂成了灰色。
在这里插入图片描述
现在我们将上上图的表达式改写成更加简洁的形式。为了简化,我们用一个函数来表示这种分情况的动作(超过0则输出1,否则输出0),引入新函数h(x)
在这里插入图片描述
在这里插入图片描述
输入信号的总和会被函数 h(x) 转换,转换后的值就是输出y。 然后上图所表示的函数 h(x),在输入超过 0 时返回 1,否则返回 0。

3.1.3 激活函数登场

刚才登场的h(x)函数会将输入信号的总和转换为输出信号,这种函数一般称之为激活函数(activation function)。如“激活”一词所示,激活函数的作用在于决定如何来激活输入信号的总和。
现在来进一步改写这个公式, 分两个阶段进行处理, 先计算输入信号的加权总和,然后用激活函数转换这一总和。因此,如果将上面的式子写的详细一点, 则可以分成下面2个式子
在这里插入图片描述
首先,计算加权输入信号和偏置的总和,记作为a。然后,用h()函数将a转换输出y
之前的神经元都是用一个○表示的,现在可以这样表示
在这里插入图片描述
如上图所示, 表示神经元的○中明确显示了激活函数的计算过程,即信号的加权总和为节点a,然后节点a被激活函数h()转换成节点y。本书中,“神经元”和“节点”两个术语的含义相同。这里,我们称ay为“节点”,其实它和之前所说的“神经元”含义相同。
通常如下图的左图所示,神经元用一个○表示。本书中,在可以明确 神经网络的动作的情况下,将在图中明确显示激活函数的计算过程,如下图右图所示。
在这里插入图片描述
下面,我们将仔细介绍激活函数。激活函数是连接感知机和神经网络的桥梁。

本书在使用“感知机”一词时,没有严格的统一它所指的算法。一般而言,“朴素感知机”是指单层网络,指的是激活函数使用了阶跃函数(是指一旦输入超过阈值,就切换输出的函数。)的模型。“多层感知机”是指神经网络,即使用 sigmoid 函数(后述)等平滑的激活函数的多层网络。

3.2 激活函数

下图所表示的激活函数以阀值为界,一旦输入超过阀值,就切换输出。这样的函数称之为“阶跃函数”。因此,可以说感知机中使用了阶跃函数作为激活函数,也就是说,在激活函数的众多候选函数中,感知机使用了阶跃函数。那么,如果感知机使用其他函数作为激活函数,会发生什么呢?实际上,如果将激活函数从阶跃函数换成其他函数,就可以进入神经网络的世界了。下面我们就来介绍一下神经网络使用的激活函数
在这里插入图片描述

3.2.1 sigmoid函数

神经网络中经常使用的一个激活函数就是下图的式子,表示的 sigmoid 函数(sigmoid function)。在这里插入图片描述
上图中的exp(-x)表示e-x的意思。e是纳皮尔常数 2.7182 . . .。这个函数表示的 sigmoid 函数看上去有些复杂,但它也仅仅是一个函数而已,而函数就是给定某个输入后,会返回某个输出的转换器。比如,向 sigmoid 函数输入 1.0 或 2.0 后,就会有某个值被输出,类似 h(1.0) = 0.731 . . .、h(2.0) = 0.880 . . . 这样。
神经网络中用 sigmoid 函数作为激活函数,进行信号的转换,转换后的信号被传送给下一个神经元。实际上,上一章介绍的感知机和接下来要介绍 的神经网络的主要区别就在于这个激活函数。其他方面,比如神经元的多层 连接的构造、信号的传递方法等,基本上和感知机是一样的。下面,让我们 通过和阶跃函数的比较来详细学习作为激活函数的 sigmoid 函数。

3.2.2 阶跃函数的实现

这里我们试着用 Python 画出阶跃函数的图(从视觉上确认函数的形状对 理解函数而言很重要)。 阶跃函数如下图所示,当输入超过0时,输出1,否则输出0.可以想下面简单的实现。
在这里插入图片描述
这个实现简单、易于理解,但是参数x只能接受实数(浮点数)。也就是说,允许形如 step_function(3.0)的调用,但不允许参数取NumPy数组,例如step_function(np.array([1.0, 2.0]))。为了便于后面的操作,我们把它修改为支持NumPy数组的实现。为此,可以考虑下述实现。
在这里插入图片描述

上述函数的内容只有2行,由于使用了numpy中的“技巧”,可能会有点难理解, 下面我们通过python解释器来解释下
在这里插入图片描述
NumPy 数组进行不等号运算后,数组的各个元素都会进行不等号运算,生成一个布尔型数组。这里,数组 x 中大于 0 的元素被转换为 True,小于等于0的元素被转换为 False,从而生成一个新的数组 y。
数组 y 是一个布尔型数组,但是我们想要的阶跃函数是会输出 int 型的 0 或 1 的函数。因此,需要把数组 y 的元素类型从布尔型转换为 int 型。
在这里插入图片描述如上所示,可以用 astype() 方法转换 NumPy 数组的类型。astype() 方法通过参数指定期望的类型,这个例子中是 np.int64 型。Python 中将布尔型 转换为 int 型后,True 会转换为 1,False 会转换为 0。以上就是阶跃函数的 实现中所用到的 NumPy 的“技巧”。

3.2.3 阶跃函数的图形

下面我们就用图来表示上面定义的阶跃函数,为此需要使用 matplotlib 库。
在这里插入图片描述
np.arange(-5.0, 5.0, 0.1)在−5.0到5.0的范围内,以0.1为单位,生成 NumPy数组([-5.0, -4.9,。。。, 4.9])。step_function()以该NumPy数组为参数,对数组的各个元素执行阶跃函数运算,并以数组形式返回运算结果。 对数组 x、y 进行绘图, 结果如下图
在这里插入图片描述
如图所示,阶跃函数以 0 为界,输出从 0 切换为 1(或者从 1 切换为 0)。它的值呈阶梯式变化,所以称为阶跃函数。

3.2.4 sigmoid 函数的实现

下面,我们来实现 sigmoid 函数。用 Python 可以像下面这样写出式之前表示的 sigmoid 函数。
在这里插入图片描述
这里,np.exp(-x) 对应 exp(−x)。这个实现没有什么特别难的地方,但是要注意参数 x 为 NumPy 数组时,结果也能被正确计算。实际上,如果在 这个 sigmoid 函数中输入一个 NumPy 数组,则结果如下所示。
在这里插入图片描述
之所以 sigmoid 函数的实现能支持 NumPy 数组,秘密就在于 NumPy 的 广播功能(1.5.5节)。根据NumPy 的广播功能,如果在标量和NumPy数组 之间进行运算,则标量会和 NumPy 数组的各个元素进行运算。这里来看一 个具体的例子。
在这里插入图片描述
在这个例子中,标量(例子中是1.0)和 NumPy 数组之间进行了数值运 算(+、/ 等)。结果,标量和 NumPy 数组的各个元素进行了运算,运算结果以 NumPy 数组的形式被输出。刚才的 sigmoid 函数的实现也是如此,因为np.exp(-x)会生成NumPy数组,所以1/(1 + np.exp(-x))的运算将会在 NumPy 数组的各个元素间进行。
下面我们把 sigmoid 函数画在图上。画图的代码和刚才的阶跃函数的代 码几乎是一样的,唯一不同的地方是把输出 y 的函数换成了 sigmoid 函数
在这里插入图片描述

3.2.5 sigmoid 函数和阶跃函数的比较

现在我们来比较一下sigmoid 函数阶跃函数,如下图所示。两者的不同点在哪里呢?又有哪些共同点呢?
观察下图,首先注意到的是“平滑性”的不同。sigmoid 函数是一条平滑的曲线,输出随着输入发生连续性的变化。而阶跃函数以 0 为界,输出发生急剧性的变化sigmoid 函数的平滑性对神经网络的学习具有重要意义
在这里插入图片描述
另一个不同点是,相对于阶跃函数只能返回 0 或 1sigmoid 函数可以返回 0.731 . . .、0.880 . . . 等实数(这一点和刚才的平滑性有关)。也就是说,感知机中神经元之间流动的是 0 或 1 的二元信号,而神经网络中流动的是连续的实数值信号
如果把这两个函数与水联系起来,则阶跃函数可以比作“竹筒敲石”(是日本的一种庭院设施。支点架起竹筒,一端下方置石,另一端切口上翘。在切口上滴水,水积多后该端下垂,水流出,另一端翘起,之后又因重力而落下,击石发出响声), sigmoid 函数可以比作“水车”。阶跃函数就像竹筒敲石一样,只做是否传送水(0或1)两个动作而 sigmoid 函数就像水车一样,根据流过来的水量相应地调整传送出去的水量
接着说一下阶跃函数sigmoid函数的共同性质。阶跃函数sigmoid函数虽然在平滑性上有差异,但是如果从宏观视角看,可以发现它们具有相似的形状。实际上,两者的结构均是“输入小时,输出接近0(为0);随着输入增大,输出向1靠近(变成1)”。也就是说,当输入信号为重要信息时,阶跃函数和sigmoid函数都会输出较大的值;当输入信号为不重要的信息时,两者都输出较小的值。还有一个共同点是,不管输入信号有多小,或者有多大,输出信号的值都在0到1之间

3.2.6 非线性函数

阶跃函数和sigmoid函数还有其他共同点,就是两者均为非线性函数。sigmoid函数是一条曲线,阶跃函数是一条像阶梯一样的折线,两者都属于非线性的函数。

在介绍激活函数时,经常会看到“非线性函数”和“线性函数”等术语。函数本来是输入某个值后会返回一个值的转换器。向这个转换器输入某个值后,输出值是输入值的常数倍的函数称为线性函数(用数学式表示为h(x) = cx。c为常数)。因此线性函数是一条笔直的直线。而非线性函数,顾名思义,指的是不像线性函数那样呈现出一条直线的函数。

神经网络的激活函数必须使用非线性函数。换句话说,激活函数不能使用线性函数。为什么不能使用呢?因为使用线性函数的话, 加深神经网络的层数就没有意义了。
线性函数的问题在于,不管如何加深层数,总是存在于之等效的“无隐藏层的神经网络”。为了具体地(稍微直观的)理解这一点,我们来思考下面这个简单的例子。这里我们考虑吧线性函数h(x) = cx作为激活函数,把y(x)=h(h(h(x)))的运输算对应3层神经网络(该对应只是一个近似,实际的神经网络运算比这个例子要复杂,但不影响后面的结论成立。)。这个运算会进行y(x)=c*c*c*x的乘法运算,但是同样的处理可以由y(x)=ax(注意:a=c3)这一次乘法运算(即没有隐藏层的神经网络)来表示。如本例所示,使用线性函数时,无法发挥多层网络带来的优势。因此,为了发挥叠加层所带来的优势,激活函数必须使用非线性函数。

3.2.7 ReL U

到目前为止,我们介绍了作为激活函数的阶跃函数和sigmoid 函数。在神经网络发展的历史上,sigmoid 函数很早就开始被使用了,而最近则主要使用ReLU(Rectified Linear Unit)函数。
ReLU 函数在输入大于0时,直接输出该值;在输入小于等于0时,输出0.
函数表达式为 下图
在这里插入图片描述
如图所示ReLU 函数是一个非常简单的函数。因此,ReLU 函数函数的实现也很简单,可以写成下图所示。
在这里插入图片描述
这里使用了Numpy中的maximun 函数。它会从输入的数值中选择较大的那个值进行输出

本章的剩余部分的内容还是以sigmoid函数为主,但本书的后半部分, 以ReLU 函数为主

3.3 多位数组的运算

如果掌握了Numpy多维数组的运算,就可以高效的实现神经网络。因此,本节将介绍Numpy多位数组的运算,然后在进行神经网络的实现

3.3.1 多维数组

简单来说,多维数组就是“数字的集合”, 数字排成一列的集合、排成长方形的集合、排成三维状或者(更加一般化的)N维状的集合都称为多维数组。下面我们就用Numpy来生成多维数组,先从前面介绍过的一维数组开始。
在这里插入图片描述
如上图所示, 数组的维度可以通过np.dim()函数获得。此外,数组的形状可以通过实例变量shape获得,在上面的例子中, a是一个一维数组,由5个元素构成。注意,这里的a.shape的结果是一个远足。这是因为一维数组的情况下也要返回多维数组的情况下一致的结果。例如,二维数组时返回的是元祖(5,3),三维数组返回的是元祖(5,3,5) 因此一维数组时也同样以元祖的形式返回结果, 下面我们来生成一个二维数组
在这里插入图片描述
这里生成了一个32的数组A。32 的数组表示第一个维度有3个元素,第二个维度有2个元素。灵位第一个维度对应的是第0维,第二个维度对应的第一维(索引从0开始)。二维数组也称为矩阵(matrix)。如下图所示,数组的横向排列称之为(row),纵向排列称之为(column)。
在这里插入图片描述

3.3.2 矩阵乘法

下面,我们来介绍矩阵(二维数组)的乘积。比如22 的矩阵,其乘积可以像下图这样计算
在这里插入图片描述
如本例所示,矩阵的乘积是通过左边矩阵的行(横向)和右边矩阵的列(纵向)以对应元素的方式相乘后在求和而得到的,并且,运算的结果保存为心的多位数组的元素。比如
A的第一行和B的第一列的乘积结果是新数组的第一行第一列的元素,A的第2行和B的第一列的结果是新数组的第2行第一列的元素。另外,在本书的数学标记中,矩阵江永黑斜体来表示(比如,矩阵A*),以区别于单个元素的标量(比如,a,b)。这个运算在pytho中可以用如下代码实现。
在这里插入图片描述
这里的AB都是22 的矩阵,他们的乘积可以通过Numpy的np.dot()函数进行计算(乘积也称为点积)。np.dot()接受两个Nnmpy 数组作为参数,并返回数组的乘积。这里要注意的是np.dot(A,B)np.dot(B,A)值可能不一样,和一般的运算(+或等)不同,矩阵的乘积运算中,操作数(A,B)的顺序不同,结果也会不同。
这里介绍的是计算22 形状的矩阵的乘积例子,其他形状的矩阵的乘积也可以用相同的方法来计算。比如,23的矩阵和32的矩阵的乘积可以按照图下形势用python来实现
在这里插入图片描述
2
3的矩阵A和32的矩阵B的乘积可按以上方式实现,这里需要注意的是矩阵的形状(shape)。具体的讲,矩阵A的第1维的元素个数(列数)必须和 矩阵B的第0维的元素个数(行数)相等。在上面的例子中,矩阵A* 的形状是23,矩阵B* 的形状是32 矩阵A* 的第1维的元素个数是3和矩阵B的第0维的元素个数3相等,如果两个值不等,则无法计算成绩,比如, 用22和23的矩阵做乘积,则会出书以下错误。
在这里插入图片描述
这个错误的意思是,2个矩阵的元素个数不一 致 ( 维 度 的 索 引 从 0 开 始 )。也就是说,在多维数组的乘积运算中,必须使两个矩阵中的对应维度的元素个数一致,这一点很重要。我们通过下图再来确认一下。
在这里插入图片描述
在上图中,32的矩阵和24矩阵的乘积生成一个34的矩阵,如图所示,矩阵A和矩阵B的对应维度的元素个数必须保持一致,此外还有一点很重要, 就是运算结果的矩阵C的形状是由矩阵A的行数和矩阵B的列数构成的 。
另外,当
A* 是二维矩阵、B是一维数组时,图下入所示,对应维度的算数个数要保持一致的原则依然成立
在这里插入图片描述
在这里插入图片描述

[1*1+2*2,3*1+4*1,5*1+6*2]

3.3.3 神经网络的内积

下面, 我们使用Numpy 矩阵来实现神经网络。这里我们以下图中的简单神经网络为对象, 这个神经网络省略了偏置和激活函数,只有权重。
在这里插入图片描述
实现该神经网络时,要注意X,W,Y的形状,特别是X和W 的对应维度的元素个数是否一致,这一点很重要
在这里插入图片描述

如上所示,使用np.dot(多维数组的点积),可以一次性计算出Y 的结果。这意味着,即便Y 的元素个数为100或1000,也可以通过一次运算就计算出 结果!如果不使用np.dot,就必须单独计算Y 的每一个元素(或者说必须使 用 for 语句),非常麻烦。因此,通过矩阵的乘积一次性完成计算的技巧,在实现的层面上可以说是非常重要的。

3.4 3层神经网络的实现

现在我们来进行神经网络的实现。这里我们以下图的3层神经网络为对象,实现从输入到输出的(前向)处理。在代码实现方面,使用上一节介绍的Numpy多维数组。巧妙的使用Numpy数组,可以用很少的代码完成神经网络的前向处理。
在这里插入图片描述

3.4.1 顾好确认

再介绍神经网络中的处理之前, 我们先导入w12(1) 、a1(1) 等符号。这些符号可能看上去有点负责, 不过,因为只在本节使用,稍微读一下就跳过去也问题不大。

本节的重点是神经网络的运算可以作为矩阵运算打包进行。因为神经网络的各层的运算是通过矩阵的乘法运算打包进行的(从宏观的视角来考虑),所以即使忘了(未记忆)具体的符号规则, 也不影响后面的内容

我们先从定义符号开始,请看下图, 图中之突出显示了从输入层神经元x2到最后一层的神经元a1(1)的权重
在这里插入图片描述
如上图所示,权重和隐藏层的神经元的右上角有一个“(1)”,他表示权重和神经元的层号(即第一层权第一层神经元)。此外,权重的右下角有两个数字,他们是后一层的神经元和前一层的深渊元的索引号。权重右下角按照“后一层的索引号、前一层的索引号”的顺序排列。

3.4.2 各层信号传递的实现

现在看一下从输入层到第 1 层的第 1 个神经元的信号传递过程,
在这里插入图片描述
上图中增加了表示偏置的神经元“1”。请注意,偏置的右下角的索引 号只有一个。这是因为前一层的偏置神经元(神经元“1”)只有一个(任何前一层的偏置神经元“1”都只有一个。偏置权重的数量取决于后一层的神经元的数量(不包括 后一层的偏置神经元“1”))。
为了确认前面的内容,现在用数学式表示 。 通过加权信号和偏 置的和按如下方式进行计算。
在这里插入图片描述
此外,如果使用矩阵的乘法运算,则可以将第 1 层的加权和表示成下面的式
在这里插入图片描述
下面我们用 NumPy 多维数组来实现上面的式子,这里将输入信号、权重、偏置设置成任意值。
在这里插入图片描述
这个运算和上一节进行的运算是一样的。W1 是 2 × 3 的数组,X 是元素个 数为 2 的一维数组。这里,W1 和 X 的对应维度的元素个数也保持了一致。
接下来,我们观察第 1 层中激活函数的计算过程。如果把这个计算过程 用图来表示的话,则如下图所示。
在这里插入图片描述
隐藏层的加权和(加权信号和偏置的总和)用 a 表示,被 激活函数转换后的信号用 z 表示。此外,图中 h() 表示激活函数,这里我们 使用的是 sigmoid 函数。用 Python 来实现,代码如下所示。
在这里插入图片描述
这个 sigmoid() 函数就是之前定义的那个函数。它会接收 NumPy 数组,并返回元素个数相同的NumPy 数组。
ipynb

http://www.xdnf.cn/news/904069.html

相关文章:

  • Emacs定制:编译
  • 深入了解linux系统—— 进程池
  • 使用docker 安装Redis 带配置文件(x86和arm)版本
  • 从边界防护到内生安全:企业网络安全进化路线图
  • docker数据管理
  • vue-print-nb 打印相关问题
  • 电脑同时连接内网和外网的方法,附外网连接局域网的操作设置
  • 【推荐算法】DeepFM:特征交叉建模的革命性架构
  • 前端实现视频/直播预览
  • 【Kubernetes】K8s 之 ETCD - 恢复备份
  • 职业生涯思考
  • Tomcat全方位监控实施方案指南
  • 撰写脚本,通过发布/joint_states话题改变机器人在Rviz中的关节角度
  • HakcMyVM -TheWall
  • 初识AI Agent
  • 面向开发者的提示词工程④——文本推断(Inferring)
  • 数学建模期末速成 聚类分析与判别分析
  • Caliper 配置文件解析:fisco-bcos.json
  • 【计算机组成原理 第5版】白、戴编著 第六章 总线系统 课后题总结
  • 大模型安全测试报告:千问、GPT 全系列、豆包、Claude 表现优异,DeepSeek、Grok-3 与 Kimi 存在安全隐患
  • LabVIEW工业级多任务实时测控系统
  • ComfyUI 文生图教程,进行第一次的图片生成
  • 连续小波变换(Continuous Wavelet Transform, CWT)
  • 【HarmonyOS 5】出行导航开发实践介绍以及详细案例
  • Spring Boot实现接口时间戳鉴权
  • ABAP设计模式之---“简单设计原则(Simple Design)”
  • Windows无限期暂停更新
  • 模板方法模式:优雅封装不变,灵活扩展可变
  • web3-基于贝尔曼福特算法(Bellman-Ford )与 SMT 的 Web3 DeFi 套利策略研究
  • 贝叶斯深度学习!华科大《Nat. Commun.》发表BNN重大突破!