03.矩陣與線性變換(矩陣乘法)

本文主要內容:線性變換(矩陣乘法)->基向量變換->Python計算和模擬->線性相關的矩陣變換->應用題.

1.線性變化是什麼?

變化本身是一種函數,線性變化中接受向量作為輸入,並輸出向量,在線性代數中,我們依靠矩陣乘法實現線性變換.

線性的含義:

(1)直線(網格線等)經過轉換後仍然時直線,不能彎曲

(2)原點保持固定

正常線性變換會保持原有網格等距且平行.

不是線性變化的例子(扭曲了):

若一個變換L滿足以下兩條性質,則稱L時線性的:

L(vec v+vec w) = L(vec v) + L(vec w) 可加性\ L(c vec v) = cL(vec v) 成比例(一階齊次)

2.線性變換與基向量 的規律

變換M1 = [[a,b],[c,d]]中,每次修改扭曲都臨時建立一個 M_1vec i =[[a],[c]],一個 M_1vec j =[[b],[d]]的模擬坐標系,使一切向量跟著變換.原有的總坐標系不變,使得不同向量的長度方向發生變換(而不是保持一不變).

註:本教程使用和Python一樣的表示方法,用 [[a,b],[c,d]]來表示 egin {bmatrix} a&b\ c&d end {bmatrix}

3.列出旋轉任意角度的變換矩陣

只要跟蹤 vec i和vec j 的變換就行.

4.Python計算線性變換

代碼:

import numpy a = numpy.array([[1,-3],[2,4]]) b = numpy.array([[5],[7]]) print (numpy.dot(a,b)) #[[-16],[ 38]]

5.Python模擬線性變換

注意這裡和為 的基.

變換前: vec v=-1vec i+2vec j

變換後依然是: L(vec v)=-1*L(vec i)+2*L(vec j) [這裡利用了可加性和成比例的特性]

操作是 將vec i=[[1],[0]],和vec j=[[0],[1]], 轉換為

vec i_變=[[1],[-2]],和vec j_變=[[3],[0]].

因此轉換矩陣為:L_martix = [[1,3],[-2,0]]

寫作L(vec i)=dot(L_{martix},vec i) , L(vec j)=dot(L_{martix},vec j) , L(vec v)=dot(L_{martix},vec v)

6.當列線性相關時,所有向量將擠壓成一條線,面積變為0

舉例:當轉換矩陣為L_martix = [[2,-2],[1,-1]]

因為兩列線性相關,不同列等比例 frac 2 {-2} = frac 1{-1} ,所以 vec i和vec j 共線,所以所有向量都線性相關了.

7.應用題

有一張井字網格圖片(密布等距的橫線和豎線),對這張圖片進行變換,已知變換規則是原圖片的所有平行線在變換後依然等距且平行,仍屬於同一平面.

已知原來圖片上的3個點[50,20]和[20,30]和[40,60],分別變換為 [40,80]和 [60,30],[30,20],請問變換的規則是什麼?

答:根據題意,根據變換後的平行線依然"等距和平行",了解到進行了2*2的線性變換,同時,並未說明原點不變化,原點可能偏移.

假設變換的矩陣為:

egin {bmatrix} a&b\ c&d end {bmatrix}

假設偏移的矩陣為:

egin {bmatrix} off\_x\ off\_y end {bmatrix}

接著就可以聯立方程求解了:

50a + 20b + off_x = 40

50c + 20d + off_y = 80

20a + 30b + off_x = 60

20c + 30d + off_y = 30

40a + 60b + off_x = 30

40c + 60d + off_y = 20

因為本文作者數學差,算不出來,就借用sympy求並驗證.

import sympy as sp a,b,c,d,off_x,off_y = sp.symbols("a,b,c,d,off_x,off_y") ans = sp.solve([ 50*a + 20*b + off_x-40, 50*c + 20*d + off_y-80, 20*a + 30*b + off_x-60, 20*c + 30*d + off_y-30, 40*a + 60*b + off_x -30, 40*c + 60*d + off_y - 20], [a,b,c,d,off_x,off_y]) #{a: -9/11, b: -5/11, c: 14/11, d: -13/11, off_x: 90, off_y: 40}

驗證一下:(從上面程序接著寫)

 a,b,c,d,off_x,off_y = ans[a],ans[b],ans[c],ans[d],ans[off_x],ans[off_y] M = sp.Matrix([[a,b],[c,d]]) off_M = sp.Matrix([[off_x],[off_y]]) p = [] p.append(sp.Matrix([[50],[20]])) p.append(sp.Matrix([[20],[30]])) p.append(sp.Matrix([[40],[60]])) for i in p: print (M1*i + off_M) #Matrix([[40], [80]]) #Matrix([[60], [30]]) #Matrix([[30], [20]])

下一節的鏈接:

袁傑雄:04.複合線性變換[python線性代數]?

zhuanlan.zhihu.com圖標

動畫代碼:

附註代碼:

import numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.axisartist.axislines import SubplotZerofrom moviepy.editor import VideoClipfrom moviepy.video.io.bindings import mplfig_to_npimagefrom pylab import *import mathzhfont = mpl.font_manager.FontProperties(fname=/usr/share/fonts/truetype/wqy/wqy-microhei.ttc,size=13)plt.rcParams[axes.unicode_minus]=False #負號顯示解決方案plt.style.use("seaborn")X_MIN,X_MAX = -3,5Y_MIN,Y_MAX = -3,5def set_axis_middle(fig): ax = SubplotZero(fig, 111) fig.add_subplot(ax) # ax.spines[right].set_color(none) # ax.spines[top].set_color(none) # ax.spines[left].set_color(none) # ax.spines[bottom].set_color(none) # plt.xticks([]) # plt.yticks([]) ax.set_aspect(1.) #設置高寬比 ax.set_xlim(X_MIN,X_MAX) ax.set_ylim(Y_MIN,Y_MAX) return axfig = plt.figure()def draw_vector(ax,x,y,u,v,c,s="",s2=""): ax.quiver(x,y, u,v,angles=xy, scale_units=xy, scale=1,color = c) if s == "": try : u = u[0] v = v[0] except: pass plt.text(x+u/2,y+v/2,r"$[^{"+str(u)+"}_{"+str(v)+"}]$", fontproperties=zhfont) else: plt.text(x+u/2,y+v/2,s2 + r"$vec{"+s+"}$", fontproperties=zhfont)def update(second): static = False if second>3: rate = 2 if second>4: static = True elif 1<=second<=3: rate =second-1 elif second<1: rate = 0 ax = set_axis_middle(fig) i = np.array([[1],[0]]) j = np.array([[0],[1]]) UV = np.array([[-1],[2]]) liner_transform = np.array([[1,3],[-2,0]]) cur_transform = np.array([[1,0],[0,1]]) + (liner_transform-np.array([[1,0],[0,1]]))/2*rate i = np.dot(cur_transform,i) j = np.dot(cur_transform,j) draw_vector(ax,0,0,UV[0]*i[0],UV[0]*i[1] ,"g","i",str(UV[0][0])) draw_vector(ax,UV[0]*i[0],UV[0]*i[1] ,UV[1]*j[0],UV[1]*j[1] ,"y","j",str(UV[1][0])) draw_vector(ax,0,0,i[0],i[1] ,"g","i" if not static else "") draw_vector(ax,0,0,j[0],j[1] ,"y","j" if not static else "") UV = np.dot(cur_transform,UV) draw_vector(ax,0,0,UV[0],UV[1] ,"r","v" if not static else "") return mplfig_to_npimage(fig)if 1: animation = VideoClip(update, duration = 6) animation.write_gif("test.gif", fps=7)

推薦閱讀:

AI演算法眼中的世界是什麼樣子?這些圖像或許能幫你更好地理解
可視化 服裝3D結構設計(製版)
一張圖告訴你全球葡萄酒都產自哪些國家
畫給設計師看的營銷大法
一張圖看懂:比特幣在世界各地合法性

TAG:Python | 可視化 | 線性代數 |