文章说明:本文主要内容来自吴恩达老师的神经网络课程的课后练习,结合何宽的博客,希望能为大家更加通俗清晰地理解和解决一些在使用Python实现神经网络中可能遇到的一些问题。
文章目录
- 常见的科学计算库中的易错点和技巧
- 矩阵相加
- 矩阵乘法
- 广播机制的缺点
常见的科学计算库中的易错点和技巧
矩阵相加
看一下下面的这两个随机数组“a”和“b”:
a = np.random.randn(2, 3) # a.shape = (2, 3)
b = np.random.randn(2, 1) # b.shape = (2, 1)
c = a + b
问数组c的维度是多少?
答: 因为B的列维数为1,所以先为B的列向量复制3次,使得A与B的行维数与列维数都相等,然后进行每项元素的相加,得:c.shape = (2, 3)
这个其实就是Python语法中的广播机制。
另一种情况是A、B矩阵元素相乘,即A * B
,只有当A与B的矩阵之间维数相等时,A、B才能相乘,若A矩阵的列数不等于B矩阵的列数,或A矩阵的行数不等于B矩阵的行数,则不能将两个矩阵相乘,程序会报错,如下:
a = np.random.randn(4, 3) # a.shape = (4, 3)
b = np.random.randn(3, 2) # b.shape = (3, 2)
c = a * b
# ValueError: operands could not be broadcast together with shapes (4,3) (3,2)
然而,当a,b矩阵的行数或列数中有一个相等时,乘法是可以成立的,如下:
# a,b矩阵的行数相等,列数不相等
a = np.random.randn(3, 3)
b = np.random.randn(3, 1)
c = a * b
"""
[[ 0.30044552 0.32163572 0.83089828]
[-0.41384331 0.140933 0.20342014]
[ 0.15084242 -0.24968459 0.06532467]]
"""
在这种情况下,将会使用广播机制,b会被复制三次,就会变成(3,3),再使用元素乘法。所以有:
c.shape = (3, 3)
.
矩阵乘法
np.dot(a,b
在a和b上执行矩阵乘法,而a * b
执行元素方式的乘法。
例如下面的两个随机数组a
和b
:
a = np.random.randn(4, 3) # a.shape = (4, 3
b = np.random.randn(3, 2) # b.shape = (3, 2)
c = np.dot(a, b)
问c的维度是多少?
答: 两个矩阵相乘,获得的矩阵行数等于前一个矩阵的行数,列数等于后一个矩阵的列数c.shape = (4, 2)
。
广播机制的缺点
当使用numpy进行科学计算的时候,可能对产生一个秩为1的矩阵,例如:
import numpy as np
a = np.random.randn(5)
a.shape
# (5,)
此时,如果将a矩阵与a矩阵的转置相乘,你猜结果会如果
print(np.dot(a,a.T))
# 3.948322708713407
结果竟然得到一个数,而不是矩阵。
在来看看另一个例子:
A = np.random.randn(4,3)
B = np.sum(A, axis = 0)
B.shape
来猜测一些结果如何
答案是:(3,)
。这是因为对A矩阵进行行纵向相加后,返回了一个秩为1的矩阵。
那么为了确保A.shape
是(4,1)
而不是(4,)
,则需要在sum
函数中添加参数keepdims = True
,这使我们的代码更加地严谨。
小结:
在写神经网络时,不推荐使用类似的秩为1的矩阵,可能会造成一些误差。
但是可以将a转变为一个数组:
a = np.random.randn(5,1)
a.shape
# (5,1)
这个时候,就不会发生刚才的状况了。
小技巧:
当自己不确定矩阵a的形状是否正确,则可以使用assert(a.shape==(m,n)
来断言a的形状,此时如果a的形状错误,则程序会抛出异常,这样就不怕出错了。
未完待续~~~