繼續跟著上一次線性代數學習之一切從向量開始的對線性代數進行惡補,最近這塊的學習時間會分配多一些,因為要被考了嘛不捉急一點,這裡依然是對向量的一個探討~~當然依然是概念很多,也很枯燥,但是理解這些基礎也是在之後學習更深入的學習線性代數必經之路,數學本身是一個非常嚴謹的學科,中間落了任何環節對於後面的學習都會受到影響,所以切勿焦躁~~
規範化和單位向量:向量的長度:如上一次的學習一直在提到向量是具有「方向」的,但是既然它是一個有向的線段,除了方向肯定也是有大小的,所以對於向量來說除了在看待方向之外,通常也要看一下這個向量的大小是多少?對於這麼一個向量:
它是個二維向量,直接在二維平面上繪製如下:
其實就是求這個直角三角形的斜邊的大小對不?
而其實根據初中所學的勾股定理就能算出其斜邊的大小來,由於現在自己數學的水平可能停留在了小學。。所以用度娘上的一張圖回憶一下:
所以:
向量的模:二維向量:而在線性代數裡,對於向量u的大小是用這樣的雙豎線來表示的,如下:
對於這個大小有一個專業的詞來表示:向量的模。
思考:為啥要用雙豎線來表示呢?【了解】另外為啥在表示向量的模時是用的雙豎線呢?
這是因為單豎線跟數學中求一個數的絕對值重合了,所以對於向量的取模用的是雙豎線。換言之,單豎線和雙豎線裡面作用的對象是不一樣的,單豎線裡面作用的是一個個的數,而雙豎線裡面作用的是一個個的向量;另一個層面為啥使用雙豎線是因為咱們目前的這種求解的方式是求的圓點到向量所代表點的歐拉距離,啥叫歐拉距離?百科一下:
嗯,反正詞挺高大上的,直觀理解就是咱們目前的勾股定理求斜邊,另外圖中提到了一個更加高大上的詞:「2範數」,它又是啥呢?
有些抽象,也不用過多糾結,看一下它的另一個定義:
其中看到木有,對於二範數的符號表示就是用的雙豎線對不?
而它剛好就是對於咱們勾股定理中的求平方再開二次根是一種形態:
實際上把二範數這個概念作用在向量上跟歐拉距離是重合的,關於這塊有個了解既可。
三維向量:上面是針對二維向量的求解模的方式,那如果是三維的向量其模又是如何求解的呢?比如:
它所對應的三維坐標情況如下:
此時也就是在立體幾何中計算OP這個線段的長度既可,此時就需要有立體幾何的知識了,不過也不是太難,看一下:先做一個輔助線:
這樣一看OP其實就是這個直角三角形的斜邊的長度對麼?
但是此時看一下這個直角三角形已知大小的邊貌似只有它:
所以此時要能算出斜邊OP還需要知道OA的大小,而它其實又是另一個直接三角形的斜邊,如下:
所以根據勾股定理此時就可以很方便地求出OA這個向量的大小,如下:
所以咱們就可以算出OP這個向量的模了,如下:
其實發現規律木有,對於三維的和二維的其計算模的最終都是取向量每個坐標軸分量的平方和再開根。
N維向量:所以,對於N維向量:
它的U的長度或模的公式為:
單位向量 unit vector:
既然我們已經能算出向量的大小了,那麼就可以算出它的單位了,如下:
上面這啥意思,其實就是用向量除以向量的大小,最終得出來的就是單位向量,而將式子展開一下就變為:
其中單位向量用這個字符來表示:
以平面坐標來理解單位向量:
而這個向量的長度為5,然後它的單位向量就是整個向量的1/5對不?所以標藍的就是單位向量:
其中單位向量的方向依然是保持不變的。而單位向量的模記住永遠等於1:
既然它的大小是固定的1,所以說對於單位向量來說大小已經不重要了,而重要的是指它的方向,所以總結如下:
如果只需要求得向量的方向可以使用單位向量既可;而如果只求向量的大小則直接求向量的模既可。
而根據U的向量求出U向量的單位向量的過程叫做:歸一化、規範化(normalize)。
標準單位向量 standard unit vector:另外單位向量其實是有無數個的,這裡從坐標軸就可以得知:
圖中是以(0,0)為圓心,半徑為1做一個圓,從坐標原點到圓上的任意一點所對應的向量都是一個單位向量, 那當然就是無數個嘍,但是!!!在二維空間中,有兩個非常特殊的單位向量:
也就是這倆單位向量只由0,1組成的,這樣的單向向量就叫做:標準單位向量(Standard Unit Vector)。而標準單位向量是指向坐標軸的正方向,也就是圖中標藍的那兩個。另外單位向量中只能有一個維度的值為1,其它維度的值都應該為0,比如:
二維空間中,有兩個標準單位向量:
三維空間中,有三個標準單位向量:
對應三維坐標軸如下:
那n維空間中,則有n個標準單位向量:
那標準單位向量有啥用呢?很重要!!!在未來空間的學習中就可以看到了,待未來再來體會,目前先來了解它的概念。
實現向量規範化:接下來則來編程實現一下上面理論所描述的求一個向量的模和求一個向量的單位向量。
求向量的模:調用一下:
求向量的單位向量:知道了單位向量的計算大小之後,就可以來算它的單位向量了,也就是規範化,如下:
但是!!這種寫法不夠優,為啥?
所以可以提前一下:
下面來調用一下:
為了驗證確實計算出來的是單位向量,咱們對它進行一下取模,因為所有的單位向量的長度都為1,如下:
然後再換一個向量試一下:
優化:目前對於求向量的單位向量寫法還是有待加強的,目前咱們是用的乘:
貌似直接用向量除以向量的模不就可以了麼,而且閱讀性也更加的好,如下:
運行一下唄:
/Users/xiongwei/opt/anaconda3/bin/python3.8 /Users/xiongwei/Documents/workspace/python/Play-with-Linear-Algebra/02-Vectors/03-Implement-Our-Own-Vector/main_vector.pyTraceback (most recent call last): File "/Users/xiongwei/Documents/workspace/python/Play-with-Linear-Algebra/02-Vectors/03-Implement-Our-Own-Vector/main_vector.py", line 27, in <module> print("normalize {} is {}".format(vec, vec.normalize())) File "/Users/xiongwei/Documents/workspace/python/Play-with-Linear-Algebra/02-Vectors/03-Implement-Our-Own-Vector/playLA/Vector.py", line 14, in normalize return Vector(self) / self.norm()TypeError: unsupported operand type(s) for /: 'Vector' and 'float'norm((5, 2)) = 5.385164807134504norm((3, 1)) = 3.1622776601683795norm((0, 0)) = 0.0
Process finished with exit code 1報錯了,為啥呢?因為目前咱們的Vector還不支持除法操作,所以像Vector乘法一樣,定義相關的魔法函數既可,如下:
此時再運行就ok了。但是此時還是有待完善之處,下面來算一下零向量的單位向量,看一下:
所以此時咱們可以加一個判斷:
但是!!還是有些問題的,因為self.norm()返回的是浮點型,浮點型不能用==來進行判斷,應該怎麼判斷呢?這裡比較好的做法是判斷兩個浮點數之間的距離小於某一個非常小的數,比如0.00000000001之類的,則就認為這倆浮點數是相等的,所以可以這樣:
其中EPSILON是一個非常非常小的數,可以理解為0,這裡看一下網上https://blog.csdn.net/norman_irsa/article/details/80630656對這個名詞的解釋:
由於這個精度值肯定在未來還會被其它的類使用,所以這裡將其定義成一個公共的:
也就是1/(10^8),接下來咱們就可以在Vector中來引用它了:
此時再運行當然也是會報錯的,就是咱們自定義的異常:
咱們在調用時就可以捕獲這個異常了:
此時就比較完美了,當然這裡又涉及到N多Pyton的語法,不懂的直接照抄就行~~重點是學習線性代數相當的知識。
向量的點乘與幾何意義:向量的點乘:接下來學習一下非常非常重要的要領----向量的點乘,啥是向量的點乘呢,看下面:
也就是兩個向量之間的乘法操作,在之前咱們已經介召了向量的數量乘法,那是向量與數之間的乘,而向量與向量之間的乘法又是如何定義的呢?像這樣?
圖中也看到了一個大紅叉,肯定不是這樣像向量的+那樣直接將向量對應的元素相成再組成一個向量的,為什麼?這塊之後再來揭示,目前先保留這個疑問,其實對於向量之間的乘法定義是這樣的:
那為啥要這樣定義呢?也是後續再來揭示,目前先記住它就成。
從上面這個公式可以看出一個重要的特性:兩個向量「相乘」,結果是一個數【又稱之為標量】!而非向量~~而更嚴格的說法:這叫兩個向量的點乘(dot product)或者是兩個向量的內積(inner product)。
而上面定義了相量的點乘之後,在幾何意義上其實它正好等於這樣的一個結果:
其中cosθ是指向量u和向量v之間的夾角,那為啥會有這樣的一個結論呢?下面來證明一下:
還是以二維空間為例,有這麼兩個向量:
其中為啥那個綠色的那條是向量u-向量v?其實很簡單,還記得向量的加法麼?
所以此時等式可以寫成:
而根據餘弦定理:
又可以推導出:
然後將2.||u||.||v||.cosθ挪到等式左邊,形態為:
此時等號左邊剛好等於我們要論證式子左邊,接下來只要將等式右邊證明成是它那麼就可以了:
下面進一步推導,將坐標代入進去等式右邊就為:
是不是就推導出了向量點乘的公式了?
向量點乘的直觀理解:為了進一步加深對於向量點乘的理解,這裡以一種更加直觀的視角進一步理解一下:
此時其實向量v可以向向量u做一個垂線:
而此時根據餘弦公式:
此時可以很輕鬆的算出藍色鄰邊的大小為:
此時咱們就可以將向量點乘幾何公式進行一下變化,如下:
發現原來向量的點乘是使用投影的方式讓兩個向量都指向同一個方向兩個向量大小的乘積,背後可以理解向量的點乘也就是想辦法在處理向量是具有方向性這樣一個事情,它認為不同方向的向量是不能直接做乘法的,將一個向量投影到另一個向量上不就具有相同的方向了麼?此時再相乘不就有意義了,同理反過來,也可以將向量u投影到向量v上來,如下:
另外,其實也可以將向量投影以坐標系的x軸和y軸上來理解向量的點乘,比如:
此時將向量u投影到x軸上為:
而將其投影到y軸上為:
同理將向量v進行xy軸的投影如下:
此時同方向的向量就可以做乘法了:
而對於另外兩組搭配:
由於它們是完全不相同的方向,相互都沒影響誰,所以相乘之後其實就是為0,所以這也是為啥向量的點乘中只有x1*x2+y1*y2的原因之所在了:
當然這種理解方式只是為了加深咱們對於向量點乘的理解,這個推導過程在實際使用時可以忽略~~
實現向量的點乘操作:接下來則回到python中實現一下點乘:
接下來調用運行一下:
這裡有一個注意點:有些數學庫會將u * v定義為逐元素相乘的向量量,即:
由於這種計算是不具備數學含義的,所以咱們的實現中就不實現了。但是在實際使用數學庫中可能會誤認為提供的方法就是向量的點乘其實它是如上所說的這種,所以在實際使用數學庫時需要小心。
向量點乘的應用:學習了向量點乘有啥意義呢?下面則來探討這樣的一個話題。
向量的夾角:根據上面的公式發現可以很輕鬆的求出兩向量的夾角,如下:
而根據餘弦值,就可以判斷夾角的類型了,如下:
此時就有如下結論了:
根據上面的這個特點,這裡回憶一下之前所學的標準單位向量,其也可以判斷所有標準單位向量都是垂直的:
判斷兩個向量的相似程度(推薦系統):
正因為有上面這種可以判斷向量夾角的關係,所以可以用它來判斷兩個物品的相似程度,如下:
舉個例子你在網上看了一部電影,然後呢之後系統就可以根據你的喜好進行電影推薦了,此時就可以把電影想像成一個向量,然後對多部電影進行向量的點乘運算就可以求出相似性,這裡簡單理解,當然真正的推薦系統不可以有這麼簡單的。
幾何意義:此時可以根據如下公式很輕鬆地算出來:
其中投影點的方向就是求向量u的單位向量,還記得之前說單位向量的意義主要是用來判斷方向的麼?
Numpy中向量的基本使用:前言:對於向量的各種運算目前都是我們自己來封裝的,其實對於python中有一個非常著名的跟線性代數相關的庫---Numpy,所以這裡將來學習一下使用專業的數學庫是如何完成向量的基本操作的。這裡新建一個新的文件:
說明環境木問題,那正式用numpy編寫咱們的向量之前,先思考一下:在python中不是已經有列表的概念了:
用它足以表達向量了,為啥還要搞個numpy出來呢?其實有一個非常重要的原因是在python中的這個列表裡面可以存放任意類型,不同類型也可以存其中,比如說:
這是因為python的列表其實就是一個動態的數組,而數組這個數據結構本身就是用來存儲數據用的,而並非為了數學計算所準備的,然後numpy中就不一樣的,它純是為了數學計算而生,它裡面只能存儲一種數據類型的,而正因為如此,使用numpy進行數學運算速度也是非常快的。
np.array的創建:為了驗證它裡面只能存儲同一種數據類型,下面來試一下:
另外numpy中生成的vector是可以變的,而我們之前設計的Vector類是不可變的,下面看一下:
創建零向量:其中傳的是向量的一個維度,從列印來看輸出的是浮點數。
另外還有一個創建指定維度的向量,如下:
還有一種是我們可以在指定維度的基礎上還能指定向量裡面的值是多少,如下:
np.array的基本屬性:首先能知道向量有多少個元素:
另外還可以取出向量中某個位置的元素:
下面來看一下咱們取出的vec是不是numpy類型,列印一下:
np.array的基本運算:加法:減法:數量乘法:向量的點乘:
注意它的結果是一個數(標量),下面來看一下:
其實這就是在之前所說的:
所以說它不是真正意義上的點乘,那具體如何實現點乘呢?如下:
取模:求單位向量:歸一化、規範化既然求出了向量的模,就可以求出它的單位向量了,注意單位向量的模永遠是1,它的重點是關注方向,這裡再三強調:
此時算一下單位向量的模,看一下它的大小是否是1:
另外如果是零向量,numpy中是木有考慮這種異常情況的,所以此時算它的單位向量時就會報錯:
/Users/xiongwei/Documents/workspace/python/Play-with-Linear-Algebra/02-Vectors/03-Implement-Our-Own-Vector/main_numpy_vector.py:45: RuntimeWarning: invalid value encountered in true_divide print(zero3 / np.linalg.norm(zero3))
Process finished with exit code 0所以如果在使用numpy求向量的單位向量時需要注意零向量的情況,異常需要咱們自己來處理。