作业地址:吴恩达《深度学习》作业线上版 - 知乎 (zhihu.com)
写的很好的笔记:吴恩达《深度学习》笔记汇总 - 知乎 (zhihu.com) 我的「吴恩达深度学习笔记」汇总帖(附 18 个代码实战项目) - 知乎 (zhihu.com)
此处只记录需要注意的点,若想看原笔记请移步。
我们只需要管理神经网络的输入和输出,而不用指定中间的特征,也不用理解它们究竟有没有实际意义。
所有输入数据的集合构成一个矩阵(其中每个输入样本用列向量的形式表示,这是为了方便计算机的计算):
需要注意X矩阵的行表示特征数量nx,列表示m个样本。
Y矩阵表示m个样本,每个样本标签为0或1。
注意区别误差函数和损失函数,误差函数是定义在每个样本上的,而损失函数是定义在整个样本上的。
向量化计算前向和反向传播中,1/m怎么来的?
这段代码有一点需要注意:
db2=np.sum(dZ2, axis=1, keepdims=True)
db1=np.sum(dZ1, axis=1, keepdims=True)
这个keepdims=True
是必不可少的。使用np.sum, np.mean
这种会导致维度变少的计算时,如果加了keepdims=True
,会让变少的那一个维度保持长度1。比如一个[4, 3]的矩阵,我们对第二维做求和,理论上得到的是一个[4]的向量。但如果用了keepdims=True
,就会得到一个[4, 1]的矩阵。
保持向量的维度,可以让某些广播运算正确进行。比如我要用[4, 3]的矩阵减去[4]的矩阵就会报错,而减去[4, 1]的矩阵就不会报错。
注意:输入层并不计入层数,但可以用第“0”层称呼输入层
我们要记住,全体样本是把每个样本以列向量的形式横向堆叠起来,堆成了一个矩阵。我们心中对X, Y的矩阵形状要有数。
为什么在前向传播中要缓存?
记不住公式没关系,编程的时候对着翻译就行。
超参数则包括:
我们直接从超参数的作用来给超参数下定义。超参数的取值会决定参数 W,b 的取值,它们往往只参与训练,而不参与最后的推理计算。可以说,除了网络中要学习的参数外,网络中剩下的可以变动的数值,都是超参数。
一个简单区别超参数的方法是:超参数一般是我们手动调的。我们常说“调参”,说的是超参数。
self.W: List[np.ndarray] = [] //表示W是一个矩阵
第一个API是
np.savez(filename, a_name=a, b_name=b, ...)
它可以把ndarray
类型的数据a, b, ...
以键值对的形式记录进一个.npz
文件中,其中键值对的键是数据的名称,值是数据的值。
第二个API是np.load(filename)
。它可以从.npz
里读取出一个词典。词典中存储的键值对就是我们刚刚保存的键值对。
比如,我们可以用如下方法存取W, b
两个ndarray
:
W = np.zeros((1, 1))
b = np.zeros((1, 1))
np.savez('a.npz', W=W, b=b)
params = np.load('a.npz')
assert W == params['W']
assert b == params['b']
学会了这两个API的用法后,我们来看看该怎么存取神经网络的参数:
def save(self, filename: str):
save_dict = {}
for i in range(len(self.W)):
save_dict['W' + str(i)] = self.W[i]
for i in range(len(self.b)):
save_dict['b' + str(i)] = self.b[i]
np.savez(filename, **save_dict)
def load(self, filename: str):
params = np.load(filename)
for i in range(len(self.W)):
self.W[i] = params['W' + str(i)]
for i in range(len(self.b)):
self.b[i] = params['b' + str(i)]
和刚刚介绍的用法一样,这里我们要给神经网络中每一个参数取一个独一无二的名字,再把所有名字和值合并成键值对。保存和读取,就是对键值对的写和读。
这里我使用了**save_dict
这种传参方式。在Python中,func(**dict)
的作用是把一个词典的值当作函数的键值对参数。比如我要写func(a=a, b=b)
,我可以定义一个词典d={'a':a, 'b':b}
,再用func(**d)
把词典传入函数的键值对参数。
吴恩达《深度学习专项》第一阶段总结与第二阶段预览 - 知乎 (zhihu.com)
自我感觉达到文章里Level3的水平了,对于计算中的某些细节还有些不清楚,比如导数的计算,怎么来的,反向传播的过程中的cache存储等。