2021-02-16 分類: 網(wǎng)站建設(shè)
線性代數(shù)是什么?
在大學數(shù)學學科中,線性代數(shù)是最為抽象的一門課,從初等數(shù)學到線性代數(shù)的思維跨度比微積分和概率統(tǒng)計要大得多。很多人學過以后一直停留在知其然不知其所以然的階段,若干年之后接觸圖形編程或機器學習等領(lǐng)域才發(fā)現(xiàn)線性代數(shù)的應(yīng)用無處不在,但又苦于不能很好地理解和掌握。的確,多數(shù)人很容易理解初等數(shù)學的各種概念,函數(shù)、方程、數(shù)列一切都那么的自然,但是一進入線性代數(shù)的世界就好像來到了另一個陌生的世界,在各種奇怪的符號和運算里迷失了。
我在初接觸線性代數(shù)的時候簡直感覺這是一門天外飛仙的學科,一個疑問在我腦子里浮現(xiàn)出來:
線性代數(shù)到底是一種客觀的自然規(guī)律還是人為的設(shè)計?
如果看到這個問題,你的反應(yīng)是“這還用問,數(shù)學當然是客觀的自然規(guī)律了”,我一點兒都不覺得奇怪,我自己也曾這樣認為。從中學的初等數(shù)學和初等物理一路走來,很少人去懷疑一門數(shù)學學科是不是自然規(guī)律,當我學習微積分、概率統(tǒng)計時也從來沒有懷疑過,唯獨線性代數(shù)讓我產(chǎn)生了懷疑,因為它的各種符號和運算規(guī)則太抽象太奇怪,完全對應(yīng)不到生活經(jīng)驗。所以,我還真要感謝線性代數(shù),它引發(fā)了我去思考一門數(shù)學學科的本質(zhì)。其實,不止是學生,包括很多數(shù)學老師都不清楚線性代數(shù)到底是什么、有什么用,不僅國內(nèi)如此,在國外也是這樣,國內(nèi)的孟巖寫過《理解矩陣》,國外的Sheldon Axler教授寫過《線性代數(shù)應(yīng)該這樣學》,但都還沒有從根本上講清楚線性代數(shù)的來龍去脈。對于我自己來講,讀大學的時候沒有學懂線性代數(shù),反而是后來從編程的角度理解了它。很多人說數(shù)學好可以幫助編程,我恰好反過來了,對程序的理解幫助了我理解數(shù)學。
本文的目標讀者是程序員,下面我就帶各位做一次程序員在線性代數(shù)世界的深度歷險!既然是程序員,在進入線性代數(shù)的領(lǐng)域之前,我們不妨先從考察一番程序世界,請思考這樣一個問題:
計算機里面有匯編、C/C++、Java、Python等通用語言,還有Makefile、CSS、SQL等DSL,這些語言是一種客觀的自然規(guī)律還是人為的設(shè)計呢?
為什么要問這樣一個看起來很蠢的問題呢?因為它的答案顯而易見,大家對天天使用的程序語言的認識一定勝過抽象的線性代數(shù),很顯然程序語言雖然包含了內(nèi)在的邏輯,但它們本質(zhì)上都是人為的設(shè)計。所有程序語言的共同性在于:建立了一套模型,定義了一套語法,并將每種語法映射到特定的語義。程序員和語言實現(xiàn)者之間遵守語言契約:程序員保證代碼符合語言的語法,編譯器/解釋器保證代碼執(zhí)行的結(jié)果符合語法相應(yīng)的語義。比如,C++規(guī)定用new A()語法在堆上構(gòu)造對象A,你這樣寫了C++就必須保證相應(yīng)的執(zhí)行效果,在堆上分配內(nèi)存并調(diào)用A的構(gòu)造函數(shù),否則就是編譯器違背語言契約。
從應(yīng)用的角度,我們能不能把線性代數(shù)視為一門程序語言呢?答案是肯定的,我們可以用語言契約作為標準來試試。假設(shè)你有一個圖像,你想把它旋轉(zhuǎn)60度,再沿x軸方向拉伸2倍;線性代數(shù)告訴你,“行!你按我的語法構(gòu)造一個矩陣,再按矩陣乘法規(guī)則去乘你的圖像,我保證結(jié)果就是你想要的”。實際上,線性代數(shù)和SQL這樣的DSL非常相似,下面來作一些類比:
所以,從應(yīng)用的角度看,線性代數(shù)是一種人為設(shè)計的領(lǐng)域特定語言(DSL),它建立了一套模型并通過符號系統(tǒng)完成語法和語義的映射。實際上,向量、矩陣、運算規(guī)則的語法和語義都是人為的設(shè)計,這和一門語言中的各種概念性質(zhì)相同,它是一種創(chuàng)造,但是前提是必須滿足語言契約。
為什么要有線性代數(shù)?
可能有人對把線性代數(shù)當成一門DSL不放心,我給你一個矩陣,你就把我的圖形旋轉(zhuǎn)了60度沿x軸拉伸了2倍,我總感覺不踏實啊,我都不知道你“底層”是怎么做!其實,這就像有的程序員用高級語言不踏實,覺得底層才是程序的本質(zhì),老是想知道這句話編譯成匯編是什么樣?那個操作又分配了多少內(nèi)存?別人在Shell里直接敲一個wget命令就能取下一個網(wǎng)頁,他非要用C語言花幾十分鐘來寫一堆代碼才踏實。其實,所謂底層和上層只是一種習慣性的說法,并不是誰比誰更本質(zhì)。程序的編譯和解釋本質(zhì)上是不同模型間的語義映射,通常情況下是高級語言映射為低級語言,但是完全也可以把方向反過來。Fabrice Bellard用JavaScript寫了一個虛擬機,把Linux跑在JavaScript虛擬機上,這就是把機器模型往JavaScript模型上映射。
建立新模型肯定依賴于現(xiàn)有的模型,但這是建模的手段而不是目的,任何一種新模型的目的都為了更簡單地分析和解決某一類問題。線性代數(shù)在建立的時候,它的各種概念和運算規(guī)則依賴于初等數(shù)學的知識,但是一旦建立起來這層抽象模型之后,我們就應(yīng)該習慣于直接利用高層次的抽象模型去分析和解決問題。說到線性代數(shù)是為了比初等數(shù)學更容易地分析和解決問題,下面我們通過一個例子來實際感受一下它的好處:
給定三角形的頂點(x1, y1), (x2, y2), (x3, y3),求三角形的面積。
初等數(shù)學中三角形面積最著名的計算公式是area = 1/2 * base * height ,當三角形有一條邊恰好在坐標軸上時我們就很容易算出它的面積。但是,假如同樣一個三角形我們把坐標軸旋轉(zhuǎn)一下,讓它的邊不在坐標軸上,怎么辦?我們還能得到它的底和高嗎?答案肯定是可以的,但是就明顯復雜了,而且還要分很多種情況去分別討論。
相反,如果我們用線性代數(shù)知識來解決這個問題就非常輕松。在線性代數(shù)中兩個向量a,b的叉積(Cross Product)是一個向量,其方向與a,b垂直,其大小等于a,b構(gòu)成的平行四邊形的面積:
我們可以把三角形的邊視為向量,所以三角形的面積等于兩個邊向量的叉積向量的長度除以二:
area = 1/2 * length(cross_product((x2 - x1, y2 - y1), (x3 - x1, y3 - y1)))
注:length表示取向量長度,cross_product表示兩個向量的叉積。
這樣一個在初等數(shù)學里面有點兒小難的問題在線性代數(shù)中瞬間搞定!可能有人會說,你直接基于叉積來做,當然簡單了,但是叉積本身不是也挺復雜的嗎?你把它展開試試看呢?是的,模型的作用就是把一部分復雜性隱藏到模型中,使得模型的使用者可以更加簡單地解決問題。曾經(jīng)有人質(zhì)疑C++太復雜,C++之父Bjarne Stroustrup這樣回答:
Complexity will go somewhere: if not the language then the application code.
在特定環(huán)境下,問題的復雜性是由其本質(zhì)決定的,C++把一部分的復雜性納入了語言和標準庫,目的是使得應(yīng)用程序更為簡單。當然,并非所有場合C++都使得問題更加簡單,但是從原理上講,C++的復雜性是有道理的。除了C++,Java、SQL、CSS等各種語言和框架莫不如是,想象一下,如果不使用數(shù)據(jù)庫,動不動就自己去做數(shù)據(jù)存儲和管理是多么復雜??!這樣我們就不難理解為什么線性代數(shù)要定義叉積這樣奇怪的運算了,它和C++把很多常用的算法和容器納入STL是同一道理。同樣的,甚至你還可以在線性代數(shù)中定義自己想要的運算拿來復用。所以,數(shù)學一點兒不死板,它和程序一樣是活活潑潑的,你理解了它的來龍去脈就能駕馭自如。說到這里,我們就順便回答一個很常見的疑惑:
線性代數(shù)的點積、叉積還有矩陣運算都很奇怪,為什么要定義這些運算呢?它們的定義又為什么是這個樣子呢?
其實,和程序復用一樣,線性代數(shù)定義點積、叉積和矩陣運算是因為它們的應(yīng)用非常廣,有很大的復用價值,可以作為我們分析和解決問題的基礎(chǔ)。比如,很多問題都涉及到一個向量到另一個向量的投影或是求兩個向量的夾角,那么就會考慮專門定義點積(Dot Product)這個運算:
點積概念的提出屬于設(shè)計,有發(fā)揮創(chuàng)造的余地;一旦設(shè)計定了,具體公式就不能隨意發(fā)揮了,必須符合邏輯,保證它映射到初等數(shù)學模型的正確性。這就像一門高級語言可以定義很多概念,什么高階函數(shù)、閉包等等,但是它必須保證映射到底層實現(xiàn)時在執(zhí)行產(chǎn)生的效果符合其定義的規(guī)范。
線性代數(shù)好在哪里?
上面說了,線性代數(shù)是一種高層次抽象模型,我們可以采用學習一門程序語言的方法去學習它的語法和語義,但是這一認識不只針對線性代數(shù),它是對每一門數(shù)學學科通用的,可能有人會有疑問
微積分、概率論也是高層次抽象,那么線性代數(shù)這種高層次抽象的特點在哪里呢?
這就問到了根本上,線性代數(shù)的核心:向量模型。我們在初等數(shù)學中學習的坐標系屬于笛卡爾所提出的解析模型,這個模型很有用,但同時也有很大的缺點。坐標系是人為加上的虛擬參考系,但是我們要解決的問題,比如求面積,圖形旋轉(zhuǎn)、拉伸等應(yīng)用都是和坐標系無關(guān)的,建立一個虛擬的坐標系往往無助于解決問題,剛才三角形面積的例子就是這樣。
向量模型很好地克服了解析模型的缺點,如果說解析模型代表了某種“絕對性”的世界觀,那么向量模型就代表了某種“相對性”的世界觀,我推薦把向量模型和解析模型看作對立的兩種模型。
向量模型中定義了向量和標量的概念。向量具有大小和方向,滿足線性組合法則;標量是只有大小沒有方向的量(注:標量的另一種更深刻的定義是在旋轉(zhuǎn)變換下保持不變的量)。向量模型的優(yōu)點之一是其坐標系無關(guān)性,也就是相對性,它在定義向量和運算規(guī)則的時候從一開始就拋開了坐標系的束縛,不管你坐標軸怎么旋轉(zhuǎn),我都能適應(yīng),向量的線性組合、內(nèi)積、叉積、線性變換等等運算全部都是坐標系無關(guān)的。注意,所謂坐標系無關(guān)性不是說就沒有坐標系了,還是有的,剛才三角形例子的頂點就是用坐標表示的,只是在解決問題的時候不同的坐標系不會構(gòu)成影響。用一個比喻,Java號稱平臺無關(guān),不是說Java就是空中樓閣,而是說你用Java編程時底層是Linux還是Windows往往對你沒有影響。
向量模型有什么好處呢?除了剛才三角形面積問題是一個例子,下面我再舉一個幾何的例子:
給定三維坐標系中的一點(x0, y0, z0)和一個平面a*x + b*y + c*z + d = 0,求點到平面的垂直距離?
這個問題如果是要從解析幾何的角度去解決幾乎復雜到?jīng)]法下手,除非是平面恰好是過坐標軸的特殊情況,但是如果從向量模型考慮就很簡單:根據(jù)平面方程,平面的法向量(Normal Vector)是v=(a, b, c),設(shè)從平面上任意一點(x, y, z)到(x0, y0, z0)的向量為w,那么通過點積dot_product(w, v)算出w到v的投影向量p,其大小就是(x0, y0, z0)到平面a*x + b*y + c*z + d = 0的垂直距離。這里用到了向量模型的基本概念:法向量,投影向量,點積,整個問題解決過程簡潔明快。
下面再給大家留一道相似的練習題(熟悉機器學習的朋友可能會發(fā)現(xiàn)這是線性代數(shù)在線性分類中的應(yīng)用):
給定n維空間中的兩點(a1, a2, ... an),(b1, b2, ... bn)和一個超平面c1*x1 + c2*x2 ... + cn*xn + d = 0,請判斷兩點在超平面的同側(cè)或異側(cè)?
離開向量,下面我們要請出線性代數(shù)的另一個主角:矩陣(Matrix)。
線性代數(shù)定義了矩陣和向量、矩陣和矩陣的乘法,運算規(guī)則很復雜,用來做什么也不清楚,很多初學者都不能很好地理解,可以說矩陣是學好線性代數(shù)的攔路虎。遇到復雜的東西,往往需要先避免一頭陷入細節(jié),先從整體上把握它。其實,從程序的角度看,無論形式多么奇怪,它無非是一種語法,語法必然對應(yīng)了語義,所以理解矩陣的重點在于理解其語義。矩陣的語義不止一種,在不同的環(huán)境中有不同的語義,在同一環(huán)境中也可以有不同的解讀,最常見的包括:1)表示一個線性變換;2)表示列向量或行向量的集合;3)表示子矩陣的集合。
矩陣作為一個整體對應(yīng)的是線性變換語義:用矩陣A乘以一個向量v得到w,矩陣A就代表了v到w的線性變換。比如,如果想要把向量v0按逆時針方向旋轉(zhuǎn)60度得到v',只需要用旋轉(zhuǎn)變換矩陣(Rotation Matrix)去乘v0就可以了。
除了旋轉(zhuǎn)變換,拉伸變換也是一種常見的變換,比如,我們可以通過一個拉伸矩陣把向量沿x軸拉伸2倍(請試著自己給出拉伸矩陣的形式)。更重要的是,矩陣乘法有一個很好的性質(zhì):滿足結(jié)合率,這就意味著可以對線性變換進行疊加。舉個例子,我們可以把“沿逆時針旋轉(zhuǎn)60度”的矩陣M和“沿x軸拉伸2倍”的矩陣N相乘,得到一個新矩陣T來代表“沿逆時針旋轉(zhuǎn)60度并沿x軸拉伸2倍”。這是不是很像我們Shell中把多個命令通過管道進行疊加呢?
上面重點介紹了向量模型的坐標系無關(guān)性,除此之外,向量模型的另一優(yōu)點是它能描述線性關(guān)系,下面我們來看一個熟悉的Fibonacci數(shù)列的例子:
Fibonacci數(shù)列定義為:f(n) = f(n-1) + f(n-2), f(0) = 0, f(1) = 1;問題:輸入n,請給出求f(n)的時間復雜度不超過O(logn)的算法。
首先,我們構(gòu)造兩個向量v1=(f(n+1), f(n))和v2=(f(n+2), f(n+1)),根據(jù)Fibonacci數(shù)列性質(zhì),我們可以得到從v1到v2的遞推變換矩陣:
并進一步得到:
這樣就把線性遞推問題轉(zhuǎn)化為了矩陣的n次冪經(jīng)典問題,在O(log n)時間復雜度內(nèi)解決。除了線性遞推數(shù)列,初等數(shù)學中著名的n元一次方程組問題也可以轉(zhuǎn)化為矩陣和向量乘法形式更容易地解決。這個例子是想說明,凡是滿足線性關(guān)系的系統(tǒng)都是向量模型的用武之地,我們往往可以把它轉(zhuǎn)化為線性代數(shù)得到簡潔高效的解決方案。
總結(jié)
本文提出了一種觀點:從應(yīng)用的角度,我們可以把線性代數(shù)視為一門特定領(lǐng)域的程序語言。線性代數(shù)在初等數(shù)學基礎(chǔ)上建立了向量模型,定義了一套語法和語義,符合程序語言的語言契約。向量模型具有坐標系無關(guān)性和線性性,它是整個線性代數(shù)的核心,是解決線性空間問題的好模型。向量的概念、性質(zhì)、關(guān)系、變換是掌握和運用線性代數(shù)的重點。
網(wǎng)頁題目:人工智能基礎(chǔ)-算法工程師為什么要懂線性代數(shù)?
網(wǎng)站URL:http://jinyejixie.com/news/101232.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計、手機網(wǎng)站建設(shè)、網(wǎng)站導航、網(wǎng)站策劃、靜態(tài)網(wǎng)站、標簽優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容