前情回顾:
我们在01笔记中介绍了感知机,并且我们发明了与门,或门,与非门,他们都是同一种结构的感知机,并且留下了一个问题,怎么创造异或门。02笔记中,我们介绍用与门,或门,与非门创造异或门,异或门是一种多层感知机。我们还说明了一个感知机就是一个神经元。接下来,我们用阶跃函数的方式来说明是否输出1。阶跃函数就是一种激活函数,我们还介绍了sigmoid函数和ReLU函数。他们都是非线性的函数,我们说明了为什么激活函数不能是线性的函数(形如y=cx)。
以上只是简单的提到我们学习了什么内容,需要大家先自行回忆,用自己的语言来解释这段文字提到的概念,当回忆不清楚的时候,就单击下面的链接看一看。务必先回忆再阅读,这样学习效率更好。
新伙伴可以先阅读前面两篇笔记,再看这篇笔记。
多维数组的运算
多维数组是什么
简单地讲,多维数组就是“数字的集合”,数字排成一列的集合、排成长方形的集合、排成三维状或者(更加一般化的)N维状的集合都称为多维数组
数组的维数可以通过np.ndim()函数获得。此外,数组的形状可以通过实例变量shape获得。 以下A,B,C分别是1,2,3维数组。
import numpy as np
A = np.array([1, 2, 3, 4, 5])
print(A)
print(A.shape)
B = np.array([[1, 2], [3, 4], [5, 6]])
print(B)
print(B.shape)
C = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]], [[9, 10], [11, 12]]])
print(C)
print(C.shape)
[1 2 3 4 5]
(5,)
[[1 2]
[3 4]
[5 6]]
(3, 2)
#3×2的数组表示第一个维度有3个元素,第二个维度有2个元素
[[[ 1 2]
[ 3 4]]
[[ 5 6]
[ 7 8]]
[[ 9 10]
[11 12]]]
(3, 2, 2)
#第一个维度有 3 个元素(对应最外层的三个二维数组),第二个维度有 2 个元素(对应每个二维数组中的两行),第三个维度有 2 个元素(对应每行中的两个数值)
其中二维数组也称为矩阵(matrix),数组的横向排列称为行(row),纵向排列称为列(column) 。
矩阵乘法
该部分属于线性代数的内容,这里不详细说了。学习线性代数可以去看b站上发布的mit线性代数的课,Gilbert Strang教授讲得很好。 这里多提一嘴,关于矩阵大小的问题。
两个矩阵是否能够相乘,以及相乘之后的矩阵是什么形状。举例,矩阵A点乘矩阵B。
代码实现:乘积可以通过NumPy的np.dot()函数计算(乘积也称为点积)
神经网络的内积
根据内积的性质,我们可以用矩阵相乘的方式表示原来的式子。这里没有考虑激活函数。
abcdef是指权重,b1,b2,b3指偏置。
将1,2,3,4,5,6赋值给a,b,c,d,e,f。
【不考虑偏置的情况】的代码展示
如上所示,使用np.dot(多维数组的点积),可以一次性计算出Y的结果。这意味着,即便Y的元素个数为100或1000,也可以通过一次运算就计算出结果!如果不使用np.dot,就必须单独计算Y的每一个元素(或者说必须使用for语句),非常麻烦。因此,通过矩阵的乘积一次性完成计算的技巧,在实现的层面上可以说是非常重要的。
三层神经网络的代码实现
神经元的三层网络
符号确认
为什么这样设,因为这样与矩阵的位置相对应。
此外,如果使用矩阵的乘法运算,则可以将第1层的加权和表示成下面的式(3.9)。
代码:
从输入层到第一层
从第一层到第二层
最后是第2层到输出层的信号传递。输出层的实现也和之前的实现基本相同。不过,最后的激活函数和之前的隐藏层有所不同。 输出层的激活函数用σ()表示,不同于隐藏层的激活函数h()(σ读作sigma)。这里我们用的激活函数是恒等函数。
输出层所用的激活函数,要根据求解问题的性质决定。一般地,回归问题可以使用恒等函数,二元分类问题可以使用sigmoid函数,多元分类问题可以使用softmax函数。关于输出层的激活函数,我们将在下一节详细介绍。
总结:
至此,我们已经介绍完了3层神经网络的实现。现在我们把之前的代码实现全部整理一下。这里,我们按照神经网络的实现惯例,只把权重记为大写字母W1,其他的(偏置或中间结果等)都用小写字母表示。
init_network()函数会进行权重和偏置的初始化,并将它们保存在字典变量network中。这个字典变量network中保存了每一层所需的参数(权重和偏置)。
forward()函数中则封装了将输入信号转换为输出信号的处理过程。另外,这里出现了forward(前向)一词,它表示的是从输入到输出方向的传递处理。后面在进行神经网络的训练时,我们将介绍后向(backward,从输出到输入方向)的处理。