寫在最前面
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] ]
如果不用點積,你要寫多少代碼呢?更重要的是,點積節約了大量運算的時間。