教程是本人学习吴恩达老师DeepLearing系列课程中整理的最为详细的学习笔记。学习视频主要来自B站[双语字幕]吴恩达深度学习deeplearning.ai_哔哩哔哩_bilibili?,以及DeepLearning官方网站Deep Learning by deeplearning.ai | Coursera。该系列课程总共有180多个,我会将学习笔记陆续分享出来,为有兴趣深度学习的同仁提供便利。再次由衷感谢吴恩达老师的精彩讲解和无私奉献!
特别说明:图片来源于吴恩达老师视频截图。
附文本:
Python让你能够使用广播运算,一般来说python numpy程序语言给你提供了很高的灵活性,我想,这算是一门编程语言的优势,同时也是弱势。我认为是一种优势,是因为它让语言的表现力更强,语言的灵活性很大,就是说,你可以用一行代码完成很多运算。但也有弱势,因为广播和这么大的灵活性,有时可能会引入非常细微的错误,非常奇怪的bug。如果你不熟悉所有复杂的广播运作的方式,比如,你想用列向量,把它加到一个行向量,你可能会预计它会报错,说维度不匹配,或者类型错误之类的。但实际上,你会得到一个行向量和列向量求和之后的矩阵。python的这些奇怪的效果有其内在的逻辑,但是如果你不熟悉python,我看过很多学生写出很奇怪非常难调试的bug。所以我想在这个视频里,跟你分享一些技巧,对我来说非常有用,可以排除、简化或者说消灭我自己代码里各种奇奇怪怪的bug,我希望通过这些提示和技巧,你可以更容易写出无bug的python和numpy代码。
为了说明python-numpy不太直观的效果,尤其是在python-numpy中构建向量时的怪事,我很快展示一下。我们令a = np.random.randn(5),这生成了5个随机高斯变量,储存在数组a中。我们print一下,看看a的形状是怎么样的。a.shape打印出来是(5,)结构。所以这是所谓的python秩为1的数组,它既不是行向量也不是列向量。这导致它有些略微不直观的效果。所以比如我们把a转置打印出来,看起来和a还是一样的。如果我们打印一下a和a的转置的内积,你可能觉得a乘以a转置,或者说外积可能会得到一个矩阵,但实际这样做得到的是一个数字。
我建议,当你编写神经网络程序时,你就不要用这种数据结构,其中形状是(5,)或者(n,)这种秩为1的数组。相反,如果你令a为这种5×1矩阵的话,那么就可以令a变成5×1列向量。而之前a和a的转置看起来是一样的,但现在看看a转置就是一个行向量了。注意一个微妙的区别,在这个数据结构中,有两个方括号,当我们打印a转置时,以前这里只有一个方括号,所以这(两个方括号)是区别这是一个1×5矩阵,而不是这些秩为1的数组(1个方括号)。如果你打印出来,比如a和a转置的乘积,这样就会得到一个向量的外积,对吧?所以,向量的外积可以得到一个矩阵。现在我们仔细看看这里见到的东西。我们刚才跑的第一个命令,是这个。这创建了一个数据结构,a.shape就是这个奇怪的(5,) ,有时这叫秩为1的数组,这是一个非常有趣的数据结构,它的行为和行向量和列向量并不一样,所以有些效果没有那么直观。
那么我推荐的是,当前你进行编程练习时,或者实现神经网络的logistic回归时,你就不用这些秩为1的数组。相反,每次创建数组时,你要把它定义成列向量,所以这创建一个5×1向量,或者把它变成一个行向量,那么你的向量的行为也许更容易理解一些。所以在这种情况下,a.shape就等于(5,1)。所以这个行为很像,但实际上这就是一个列向量。所以你可以将它看成是5×1矩阵,它是一个列向量。而下面这个a.shape是(1,5),然后这里的行为和行向量一致,所以当你需要一个向量时,就用这两种形式,不要再用秩为1的数组。
还有一件事,如果在代码中做了很多事情,已经记不清了一个向量具体的维度是多少,我们可以用assert()这样一个声明,确保这是一个向量,所以这是一个列向量。这些assert()执行起来很快,它们也可以看成是代码的文档,所以不要犹豫,你觉得需要的时候就使用assert()声明。
最后,如果由于某种原因,你得到了一个秩为1的数组,你可以使用将一个5×1数组或者1×5数组 reshape成一个列向量或行向量。它(列向量和行向量)的行为更好预测。
所以,有时候看到学生很难调试一些错误,都来自于秩为1数组的反直觉行为。通过消除代码中的秩为1的数组,我们可以让代码变得更加简单。而我其实并没有觉得这样写代码限制太多。我只是从来不会用秩为1的数组。所以重点在于,要简化你的代码,不要使用秩为1的数组,始终使用n×1的矩阵,基本上是列向量,或者1×n矩阵,基本上是行向量。随意插入assert()声明,来仔细检查你的矩阵和数组的维度。不要害怕调用reshape,来确保你的矩阵或向量是你需要的维度。
所以我希望这一套建议,能帮助你消除python代码中的错误,并使习题更容易完成。