作為一名程式人,如果想接觸、結合數學,我在先前專欄〈程式人的數學書〉曾經提過一些建議,若這引起了你對數學的興趣,下一步你可能會想知道:對於寫程式來說,實用的數學是?離散數學嗎?
雖然離散數學的非連續性運算,是電腦可以表達的運算,不過,離散數學的範圍太廣,包含了邏輯、集合、圖論、狀態機等,有些你可能早就接觸過,只不過沒意識到那是離散數學的範疇罷了。
寫程式實用的數學?
就我個人經驗而言,至今為止接觸過、寫程式時最有用的一門數學是……?線性代數!我知道很多學生時代曾接觸線性代數的人,聽到線性代數會感到驚恐,別擔心,我也一樣。
就算是擅長線性代數,出版過《有限維向量空間》(Finite-Dimensional Vector Spaces)的美國數學教授哈爾莫斯,談到自己第一次學習線性代數時,遭遇也是滿悲慘的,對此,「線代啟示錄」作者在〈如何學好線性代數?〉也描述了哈爾莫斯的這段歷程。
回想起大學時代接觸線性代數的經驗,那就像:還沒熟練第一門程式語言是怎麼一回事之前,就要理解物件導向、函數式等抽象的純粹性,這都是不可能的事情。在沒有看過足夠的(爛)程式碼之前,你說你可以理解那些抽象的前因後果?類似地,如果沒看過足夠的運算轉換場合,就要能理解線性代數的定義、定理、證明,怎麼可能?更別說「證明」這件事,基本上並不是程式人的工作。
〈如何學好線性代數?〉談到,明白線性代數是指「有一天你在洗澡時豁然開悟,奔出浴室光著身子在馬路上邊跑邊叫」對我來說,在那個「豁然開悟」的時間點之前,我已經寫了不少與線性代數相關的程式碼——具體來說,就是在面對運算轉換問題時,特意練習、思考該如何以向量、矩陣來描述,當這個習慣成為自然,伴隨著實作的經驗,回頭看看線性代數時,才終於有了「原來是這麼一回事」的領悟。
向量、矩陣的幾何意義
我寫過不少的2D/3D繪圖、建模程式,而這類程式的入門,一開始脫不了三角函式等幾何轉換,在我早期的程式實作,是基於逐條的幾何公式,例如座標點(x,y)要位移(tx,ty),我會以nx=x+tx、ny=y+ty來實現,後來才發現在OpenSCAD這麼寫很蠢,因為,只要寫n_coord=[x,y]+[tx,ty]就可以了,理由是OpenSCAD的[x,y]不只是list,而是個向量。
就如同直角座標(x,y)提供x軸、y軸的位移資訊,極座標(r,a)代表長度與度數資訊,向量是用來描述方向與大小,雖然向量不包含位置資訊,不過,常會使用向量(x,y)來表示直角座標(x,y),這是因為隱含著「從原點開始,以向量(x,y)移動」的意思。如此一來,我們就可以用各種向量運算來解決幾何的問題,例如,有些用三角函式等幾何公式描述上很複雜的問題,透過向量內積、外積等作法,就可以輕鬆地描述。
至於矩陣,可以想想一條線性的數學公式。例如nx=a*x+b*y+c*z,就是將x、y當成是輸入,nx當成是輸出。如果是一組數學公式呢?你可以當成是三次輸入,三次輸出:
nx=a*x+b*y+c*z ny=d*x+e*y+f*z nz=g*x+h*y+i*z
不過,你也可以把這樣的狀況看成:輸入一個向量[x,y,z],得到一個向量[nx,ny,nz],實作其中轉換機制的,就是矩陣,若用二維陣列表示該矩陣的話,就是。
這其實是一個有趣的觀點,向量像是程式語言中函式的參數,矩陣像是函式的實作,轉換過程不過就是個函式呼叫,〈程式設計大佬眼裡的線性代數〉就是從程式語言的觀點來看線性代數。
也就是說,線性代數所談的,就是在描述一組線性方程式時,將變量視為向量,將轉換過程(線性方程式的係數)以矩陣表示,將向量轉換為另一個向量,線性代數就是討論向量之間、矩陣與向量之間關係的一門學問。
就幾何來看,因為經常用向量來代表座標,而座標與座標之間的轉換,也就是:向量之間的轉換方式,可以使用矩陣表示。由於幾何可以視覺化,我們如果能夠從幾何觀點來認識向量、矩陣,從而認識線性代數當中的行列式、特徵向量、特徵值等,這些部分就會顯得更加具體,在〈如何理解線性代數?〉裡,就闡明了那些高深名詞,各意謂著幾何中的哪些東西。
從做中學的程式工具
若想從做中學,使用可撰寫程式碼、提供向量、矩陣運算方案的繪圖工具,從幾何中認識、熟悉向量、矩陣,自然是最好的方式。例如OpenSCAD裡,向量、矩陣是一級公民,是個不錯的方案,自從體認到向量、矩陣的優異性之後,我花了很多時間改寫dotSCAD程式庫,而基於向量、矩陣的實作不但簡明,效率也上升了不少。
對OpenSCAD沒興趣的話,不妨考慮p5.js,因為它入門簡單、提供p5.Vector,也可以透過applyMatrix套用矩陣轉換;若想進一步運用,可以試試Three.js,或者甚至WebGL等基於JavaScript的方案,這必然會接觸不少向量與矩陣變換。
方才談到,線性代數探討的課題之一,是向量透過矩陣如何轉換為另一向量。就幾何而言,這可以是二維座標轉換至二維座標,或是二維轉三維、三維轉二維等。這麼一來,你可以說座標變動了,然而以相對的觀點而言,也可說是座標系統變動了。
p5.js的translate、rotate等就是這樣的概念,透過這些函式可以改變座標系統,然而,point、circle等繪圖函式並不知道自己的座標系統改變了,它們還是在自己的空間裡繪圖,被指定的x、y資訊會被轉換至畫布的座標系統,也就是在畫布的空間裡繪圖。
而這就是向量空間變換的概念,談到這個,若你接觸過資料科學、機器學習,應該就有印象了,其中談到主成分分析(Principal Component Analysis, PCA)、核方法(Kernel method)等維度變化技巧時,其實就是空間變換(降維、升維)的概念。
也就是說,就工具而言,接觸NumPy、Pandas時資料科學工具時,有不少機會可從向量、矩陣來思考,因此,當我們使用這些工具時,不要將公式逐條看待,而是可以試著將變數組織為向量,公式的係數實現為矩陣(可參考先前專欄〈陣列程式設計〉),這麼一來,我們若要進一步往機器學習scikit-learn、PyTorch等相關方案前進時,就會是很大的助力。
線性系統轉換的抽象化
在幾何、資料科學甚至是機器學習等領域裡,當我們習慣用向量、矩陣來思考、描述後,此時,就會發現:雖然被轉換的系統不同,然而其中有許多共通的計算與考量,如果將這些共通部分從幾何、資料科學、機器學習裡等實際應用中抽離出來,就是極為純粹(然而抽象)的線性代數了。
如果你跟我一樣,學生時代沒明白過線性代數,或許可以透過程式設計,從幾何等實際應用程式的實作,來理解線性代數,等到哪天解的問題夠多了,再回頭看看線代課本,或許就如同看物件導向、函數式等的理論書籍,可以別有一番體會。
專欄作者
熱門新聞
2024-08-14
2024-12-20
2024-12-22
2024-12-22