3.12 Numpy 快速入门
在前面的小节中,我们已经讨论了两种新的数学工具:向量和矩阵。
在Numpy 中,你能够以多种方式创建向量和矩阵。大多数神经网络模型中常用的运算技巧已经在前面的代码中列出。注意创建一个向量和一个矩阵的过程是相同的。如果你只创建一个只有一行的矩阵,你就创建了一个向量。而且,与通常在数学中做的一样,我们通过行、列来创建矩阵。
让我们来看看一些可以对这些向量和矩阵做的运算。
import numpy as np
a = np.array([0,1,2,3])
b = np.array([4,5,6,7])
c = np.array([[0,1,2,3],[4,5,6,7]])
d = np.zeros((2,4))
e = np.random.rand(2,5)
## 查看输出
print(a)
print(b)
print(c)
print(d)
print(e)
## 做逐元素矩阵运算
print(a * 0.1)
print(c * 0.2)
print(a * b)
print(a * b * 0.2)
print(a * c)
## 下面的语句会出错
print(a * e)
虽然上面的运算式看上去很简单,但实际上并不容易理解。我们需要谨记一点,尽管这种乘法表达式很简单,但并不属于矩阵乘法代数。也就是说,这种乘法会扭曲信息,所以要非常小心这种操作。实际上,这种看似简单的乘法可以拆分成两步。第一步是做数据的清洗和过滤,第二步才是对数据的矩阵乘法。上面的计算中,第1,2个标量乘法是满足矩阵代数的,可以放心操作,它实际上代表的是向量或者矩阵的整体收缩或放大。第3种乘法则表面上看来不符合矩阵代数,但它实际代表的是向量的赋权,它可以写成矩阵乘法:
其中 代表的是以向量 a 的元素为对角元素,其他非对角元为0的方矩阵。
用Numpy的语句写下,上面的语句为:
a = np.diag[list(a)] # 转换为对角矩阵
result = np.matmul(b,a)
# 使用矩阵乘法, 注意我调换了a和b的位置
print(result)
可以验证这个结果和 得到的结果是一致的。
同样地, 实际上也可以用矩阵表达出来。它的矩阵表达形式是
请你试着把这个式子表达为Numpy的形式,并且理解自己试试输出的结果。
但是,Numpy其实支持一种不符合矩阵代数的计算。比如
A = np.array([[0,1,2,3],[4,5,6,7]])
B = np.array([[1,1,1,1],[2,3,4,5]])
print(A*B)
这样计算的结果就是逐元素相乘,没有任何矩阵乘法的意义。而且这种乘法非常危险,它不报错。如果你在你的神经网络算法里面用了这样的乘法,那么请你记住,你可能完全改变了数据,你不能期待算法会有什么好的预测结果。因此,我不建议使用任何简化的乘法来处理矩阵。矩阵代数作为代数是严格自洽的,这意味着你使用它会很安全。但像上面的乘法却不是代数自洽的,使用它们会非常非常危险。我的建议是绝对不要使用这种乘法。
关于Numpy, 还有一个我们已经熟知的点乘算法。就是乘法。点乘要求左边矩阵的列数要等于右边矩阵的行数。比如我们看下面的一些代码:
import numpy as np
a = np.zeros((2,4))
b = np.zeros((4,3))
print(a.dot(b))
h = np.zeros((5,4)).T # T表示将矩阵转置,即行列互换
i = np.zeros((5,6))
print(h.dot(i))
你可以尝试更多的一些矩阵,来熟练这种点乘的法则。
实际上,矩阵不仅仅有点乘,还有向量的叉乘,矩阵的直乘,直和。但是这些概念超出神经网络学习的范畴了。所以我们暂时不需要去理解它们。但如果你对算法感兴趣,你需要知道,矩阵的知识非常深奥难懂,需要很长的时间你才能理解它们。但一旦你理解了它们,它会是你的秘密武器。
网友评论