写在最前面
1.本文将尽量简明直观的介绍点积运算,及其在python中的简单应用。对点积运算的理解将对机器学习的算法编写提供相当大的帮助。
2.本文代码使用python及numpy科学算法库进行编写。
3.很重要的一点是:向量A与向量B的点积 并不等于 向量B与向量A的点积,我们用A·B表示两个向量的点积运算,则A·B!=B·A(或者你习惯于A·B<>B·A的表述)。
一维相量的点积运算
若A 和 B 均为一维向量,且均包含有n个元素,则A与B的点积为:
A[0]B[0]+A[1]B[1]+...+A[n]*B[n]。
# A 和 B 均为一维向量,且均包含有n个元素,则A与B的点积为:
# A[0]*B[0]+A[1]*B[1]+...+A[n]*B[n]。
# 即下标相同的元素的乘积之和。没错,出来的是一个数字。
# 举个例子
A=[1,2,3,4,5]
B=[5,4,3,2,1]
print('A与B的点积为:',np.dot(A,B)) #此处np.dot(A,B)就是求A与B的点积运算
#输出>A与B的点积为: 35
上例中,35=1*5+2*4+3*3+4*2+5*1=5+8+9+8+5
如果你认为这很简单,那么有没有想过二维向量的点积会如何呢?
哦,对了,提一句。一般我们使用大写字母表示向量,小写字母表示具体的某一项。不出意外的话,是国际通用的。
二维向量的点积运算
二维数组的点积相对复杂一些。
先来个简单的例子解释一下:
我们还是假设有A,B两个向量。如果A,B都是(2,2)向量,那么A和B的点积将会组成一个新的向量,我们叫做C。
猜猜C会长什么样子呢?C将是(2,2)向量。先来看例子,再来解释。
A = [[1, 2],[3,7]]
B = [[4, 3],[5, 0]]
print('A与B的点积为:\n',np.dot(A,B))
#输出>a与b的点积为:
[[14 3]
[47 9]]
这个结果是如何出来的呢?请原谅我没有手写板,直接在纸上画了。
或许你已经看出规律:
1.A的第一行与B的第一列,对应元素的乘积之和,构成了新向量C的第一行第一列,坐标为(0,0)的元素。
2.A的第一行与B的第二列,对应元素的乘积之和,构成了新向量C的第一行第二列,坐标为(0,1)的元素。
3.A的第二行与B的第一列,对应元素的乘积之和,构成了新向量C的第二行第一列,坐标为(1,0)的元素。
总结来看,新向量元素的坐标,y值取决于A向量所处的行,x值取决于B向量所处的列。而每个元素的计算,总是A的行元素与B的列元素的点积。
所以,如果两个二维向量想实现点积运算,是需要有一定条件的。条件是什么呢?
假如要计算 A·B,那么,A(点击号前面的向量)中x方向元素的数量应该于B(点积号后面的向量)中y方向的数量相同。
关于我在文章中对向量的标识,这里需要稍微提一下。如果A为(3,2)向量,则代表A在y方向有3个元素,在x方向有两个元素,就像下图那样。
是不是比手写的漂亮了很多?恩恩,是的。
接下来,我们将对上面提出的两个向量点积的前提条件,做个实例。
A=np.array([1,2,3,4]).reshape(4,1)
B=np.array([1,2,3,4,5,6,7,8]).reshape(2,4)
print('A与B的点积为:\n',np.dot(A,B))
#>报错:shapes (4,1) and (2,4) not aligned: 1 (dim 1) != 2 (dim 0)
上面的代码中,我们将A声明为(4,1)向量,将B声明为(2,4)向量。A和B的具体形式为:
A:[ [1]
[2]
[3]
[4] ]
B:[ [1 2 3 4]
[5 6 7 8] ]
当我们执行点积运算时,报错了,因为A的x方向为1个元素,而b的y方向为2个元素。无法进行点积运算。 如果我们稍作修改,将A和B的位置颠倒,事情将大不相同。如下:
A=np.array([1,2,3,4]).reshape(4,1)
B=np.array([1,2,3,4,5,6,7,8]).reshape(2,4)
print("A\n",A)
print("B\n",B)
print('B与A的点积为:\n',np.dot(B,A))
#>输出:
A:[ [1]
[2]
[3]
[4] ]
B:[ [1 2 3 4]
[5 6 7 8] ]
B与A的点积为:
[ [30]
[70] ]
B与A的值均未变,我们只是更换了A与B的位置,B·A中,B的x方向有4个元素,A的y方向有四个元素。最终的结果,C在y方向上跟随B,有两个元素;在x方向上跟随A,有一个元素。C:(2,1)。
这有什么用
点击运算是向量运算中的一种,在程序中使用向量运算,可以大大提升执行效率。就点积运算而言,对于机器学习的算法编写,是大有帮助的。接下来我们将做一个简单的介绍,如果你并没有接触机器学习,依然可以看一下,这个例子并不复杂。
而关于机器学习,后期会有一系列文章。
在下面例子中,你只需要知道它是机器(深度)学习中的一部分就可以了,无需考虑太多关于机器学习的内容。
现在我们有两组数据,用L1和L2表示,L1,1表示第一组元素的第一个数,L2,3表示第二组元素的第三个数。
用L2,1举例,我们要求L2,2=w2,1×L1,1+w2,2×L1,2
其中 wx,y表示L2中,第x个元素对应于L1中第y个元素所特有的参数。上图L1和L2构成了一个2×3的网络。则L2中对应的w的总数量应该为2×3=6个。
要实现一个等式计算出所有L2中三个元素最终的值,我们就用到了点积。如下:
1.向量A1表示L1中两个元素的输出值,则A1:(2,1)
2.向量W表示L2中所有的w,则W:(3,2)。L2中总共三个元素,每个元素对应2个w值。
3.用展开的方式书写:
L2,1=w1,1×A11,1+w1,2×A11,2
L2,2=w2,1×A11,1+w2,2×A11,2
L2,3=w3,1×A11,1+w3,2×A11,2
最终构成的L2 我们用向量A2表示,则A2:(3,1)。
所以,有没有想到上面我们提到的点积?用点积表示:A2=W·A1
在程序里试一下:
A1=np.array([1,2]).reshape(2,1)
W=np.array([1,2,3,4,5,6]).reshape(3,2)
print('A2=W·A1:\n',np.dot(W,A1))
#>输出:
A2=W·A1:
[ [ 5]
[11]
[17] ]
如果不用点积,你要写多少代码呢?更重要的是,点积节约了大量运算的时间。