矩陣
在線性代數裏,用的最多的概念是【矩陣】。
一個具體的矩陣:
一個抽象的矩陣:
矩陣,是把數字按照橫豎排起來。
- 您看上圖,前一個是 行 列 (),後一個是 行 列 ()。
來源:向量的擴展,向量是橫着的一排數字,每個數字代表一個維度的分量。
-
比方說,學生的考試科目,是有 個維度。
那在年紀成績評比時,通常是按所有維度算的 ->
而評比單科王是按一個維度算的 ->
還有一些可能只是按基礎算 ->
,可以用來計算和某個候選人的相似性。
每一個評比的要求都是一個向量,而又有這麼多評比,所以就有了 。
這麼多向量如果把它們放在一起,該怎麼排列呢?
如同所示,這種把向量按照橫豎排起來的擺放方式,是很自然的結果,只不過數學家給它取了一個名字:矩陣
,並且發現了一系列相應的計算
。
所以說,矩陣就是把向量按照橫豎排起來的擺放方式而得來的,矩陣不是原因,而是結果,矩陣產生的原因就是向量的擴展。
作用,是將以前的單個計算
(倆個元素的加減乘除)變成了批處理
(倆個矩陣的加減乘除)。
如:
- 倆個元素之間的計算:
- 倆個矩陣之間的批處理:
正是這種計算方式,將以前的單個計算
(倆個元素的加減乘除)變成了批處理
(倆個矩陣的加減乘除)。
這種批處理的計算,與計算機搭配起來,簡直是絕配 — 所以,線性代數對於我們來說,生活和工作都能用上。
運算:矩陣加法、矩陣數乘、矩陣乘法。
-
矩陣加法:,前提是倆個相加的矩陣的行列相同
-
矩陣數乘:
-
矩陣乘法:
第一個矩陣的形狀是 ,第二個矩陣的形狀是 ,倆倆相乘的矩陣是 ,中間的 被劃掉了 ---- 因此倆個矩陣相乘需要滿足一個條件,乘號前的矩陣的 列數 要等於後面矩陣的 行數。
矩陣乘法很重要吧,我在編程時經常聽別人說起,況且那時候並沒有學工程數學。
- 先確定生成矩陣的尺寸,乘號前的矩陣的 列數 要等於後面矩陣的 行數;
- 生成矩陣的第 行第 列的值爲:前面矩陣第 行 和 後面矩陣第 列的點乘/內積,就是一一對應,每個數字相乘再相加。
矩陣乘法就 種情況,和數字、和向量、和矩陣 相乘。
-
矩陣卷積(二維):矩陣 以某個步長在 矩陣 表面 滑動加權求和。
演示一下卷積過程,
接着矩陣 從矩陣 的 左上角 準備滑動,如下圖:
黃色區域的元素相乘,得到 個 ,相加值爲 。假設設定的滑動步長爲 ,開始滑動,新一輪計算,方法相同,如下圖:
繼續滑動,對應位置相乘再求和得到 ,如下圖:
繼續滑動,對應位置相乘再求和得到 2,如下圖:
…,最終矩陣卷積生成的矩陣,對比 矩陣 生成的矩陣小了一圈,如下圖:
矩陣 (小矩陣),也被稱爲“卷積核”、“濾波器”;矩陣卷積也是卷積神經網絡的原理。
工程應用:圖像平滑
上面所說的矩陣卷積是二維的,因此我們以灰色圖爲例,彩色圖是三維的。
圖片是由很多 的值排列而成,像素值越大圖片就越亮;
- 如果像素是 ,那像素即黑色;
- 如果像素是 ,那像素即白色;
而矩陣正好有行、列,我們可以把圖片轉爲矩陣,通過操控矩陣來改變圖片。
圖片平滑:讓一張清晰的圖片變模糊
。
因爲圖片的像素值反應了一個圖片的亮度,如果我們把圖片中的像素值和周圍的像素值相似,那整個圖片的色調就差不多,也變模糊了。
而圖片平滑的過程和矩陣卷積的過程是一樣的,最核心的地方就是設計卷積核。
圖像平滑算法:
- 設計一個卷積核,使得圖像矩陣的每一個像素值儘可能的與周圍的像素值接近,這張圖片每部分就會差不多;
- 積核尺寸、滑動步長、周邊範圍等超參數設計,以需求而定;
- 需要考慮一個細節,矩陣卷積生成的矩陣會縮小一圈,圖片也會變小一圈;解決方法是在矩陣A最外圍補一圈零。
# 運行:在命令行輸入 python 當前源文件.py
import numpy as np
from PIL import Image # 圖片處理模塊
from scipy import signal
# 1.讀取一張圖片
filename = "./demo.png"
img_rgb = Image.open(filename)
img_rgb.show()
# 2.將彩色圖片轉爲灰度圖
img_gray = img_rgb.convert('L')
img_gray.show()
# 3.將灰度圖轉爲像素矩陣
matrix = np.asarray(img_gray)
print("matrix.shape=", matrix.shape)
# 4.定義卷積核(均值濾波器)
filter_3x3 = np.array([[ 1/9, 1/9, 1/9 ],
[ 1/9, 1/9, 1/9 ],
[ 1/9, 1/9, 1/9 ]])
print("filter_3x3=", filter_3x3.shape) # 採用的 3*3 的過濾器
print(np.around(filter_3x3, decimals=2)) # 打印圖片的像素值
# 5.開始卷積(圖像平滑)
result = signal.convolve2d(matrix, filter_3x3, mode='same')
print("result.shape=", result.shape)
print(np.around(result, decimals=0))
# 6.把像素矩陣轉回圖片
img_rlt = Image.fromarray(result)
img_rlt.show()
讀取的圖片 demo.png
:
簡單起見,轉爲黑白圖片(二維):
調用圖像平滑算法:
有些模糊了,但 可能不太明顯,可以改爲 看看(會更模糊)。
- filter_3x3 改爲 filter_7x7
# 7x7的,均值是 1/49
filter_7x7 = np.ones((7,7)) / (7*7)
除此之外,卷積核還可以改進,一般採用高斯分佈(在保留細節方面,圖片平滑效果最好),因此也稱爲 “高斯濾波器”。
二維高斯分佈:
在 的 矩陣 中,也就是卷積核的權重不要全設置爲相同的數;濾波器的設計應該隨中心逐層遞減。
# 7x7 高斯濾波器
gaussian_filter_7x7 = np.array([ [ 0.00000067, 0.00002292, 0.00019117, 0.00038771, 0.00019117, 0.00002292, 0.00000067],
[ 0.00002292, 0.00078633, 0.00655965, 0.01330373, 0.00655965, 0.00078633, 0.00002292],
[ 0.00019117, 0.00655965, 0.05472157, 0.11098164, 0.05472157, 0.00655965, 0.00019117],
[ 0.00038771, 0.01330373, 0.11098164, 0.22508352, 0.11098164, 0.01330373, 0.00038771],
[ 0.00019117, 0.00655965, 0.05472157, 0.11098164, 0.05472157, 0.00655965, 0.00019117],
[ 0.00002292, 0.00078633, 0.00655965, 0.01330373, 0.00655965, 0.00078633, 0.00002292],
[ 0.00000067, 0.00002292, 0.00019117, 0.00038771, 0.00019117, 0.00002292, 0.00000067] ])
# 調用的時候,將 filter_3x3 改爲 gaussian_filter_7x7。
除此之外,還可以實現圖片的邊緣檢測(應用在自動駕駛的車道檢測、計算機視覺基礎等等)。
# 第 4 步,定義卷積核改爲定義算子
sobel = np.array([[ -1, -2, -1 ],
[ 0, 0, 0 ],
[ 1, 2, 1 ]])
# 調用語句 result = signal.convolve2d(matrix, filter_3x3, mode='same')
result = signal.convolve2d(matrix, sobel, mode='same')
左邊是原圖,右邊是效果圖(邊緣檢測算法):
看待矩陣的四種視角:數據、系統、變換、空間
學線代時,可能比較注重具體的計算,但學完了卻發現對線代的理解還是不夠深刻。
一個可能的原因是,沒有特別深刻的理解,我們在代數中的這些符號,比如說 矩陣,這個 矩陣 到底表示什麼?
代數,是用字母代表數,但我們到底代表的是哪些數…在更加抽象的數學裏,我們的代數代表的不僅僅是數,而是一個對象。
那麼,代表的這個對象是什麼?
這個就是我們要明確的。
看待矩陣的四種視角:
- 數據:把矩陣看成數據,行列,每一行代表一個樣本,每一列代表一個特徵,多用於數據科學;
- 系統:把矩陣看成線性系統(中學的多元一次方程組),那求解那些線性方程組就可以用矩陣運算,多用於計算線性代數的線性方程組;
- 變換:把矩陣看成對向量的一個函數,或者說是一種變換,因爲一個矩陣和一個向量相乘,得到結果依然是向量,可以把矩陣看成輸入一個向量,輸出一個向量的函數,多用於圖形學的圖像圖形的變化;
- 空間:把矩陣看成一個空間,這樣看一個矩陣乘一個向量,就是向量在矩陣所表示的空間中所對應的位置是哪裏,多用於線性代數的向量空間。
線性變換
矩陣可不僅僅是隻能處理圖片的數字表格,試着換一種角度看矩陣:變換。
- 矩陣乘法:,畫在幾何。
(紅色) 經過 得到 另一個向量(綠色), 如同一個函數,一個向量輸入進去,會輸出另一個向量。
只不過,在線性代數裏,我們稱 爲一種變換,即把一個向量(或矩陣)變成另一個變量(或矩陣)。
若我們把矩陣看做一個變換,圖形變換就會十分方便。
圖形變換:圖形的縮放、旋轉、仿射等等,也用於遊戲開發、動漫製作等等。
工程應用:圖形變化
或許您應該有一個疑問,矩陣,是怎樣實現圖形變換的 ???
圖形的變化:
- 圖形旋轉
- 圖形平移
- 圖形放大
- 圖形縮小
- 圖形翻轉
- 圖形剪切(正體 變斜體)
- … …
比如,這個是怎麼做到的:
經過旋轉:
先考慮一個小問題吧,怎麼使得一個圖形繞 軸左右翻轉 ?
其實,黃色的梯形是由 個點組成,經歷 個點的座標,也就是 個列向量。
首先,我們讓 翻轉,翻轉後也就是 。
現在我們改爲以矩陣的形式翻轉:
我們需要做的就是找到一個能使其轉換完成的 ,因爲輸入的矩陣和輸出的矩陣都是同行同列(2行, 1列),根據矩陣乘法的要求, 就必須是 2行, 2列。
得到一個式子:
- 令 則有:
我們確定好 四個係數的值,通過比對等式倆邊的係數即可,
- 因爲 ,推出 ;
- 因爲 , 推出 ;
所以,矩陣 。
可這個翻轉計算只是針對 ,爲了提高計算效率(批處理),我們把 的點化爲列向量後,排成一個矩陣。
矩陣 再和 排成的矩陣 計算即可:
以上是圖形的左右翻轉(繞 軸)。
圖形的上下翻轉(繞 軸)原理也相同。
線性變換,也可以實現圖形的水平剪切。
剪切:把 正體字 變成 斜體字,就是一個剪切。
圖形的水平剪切如上圖,縱座標不變,橫座標運動。
結合矩陣:,有一個控制係數 .
根據矩陣乘法 ,令 則有:
通過對比係數,,當 時,往右剪切;當 時,往左剪切。
圖形的豎直剪切如下圖,縱座標運動,橫座標不變。
變換矩陣:,注意 的值,變換的方向不一樣。
完整代碼:
# 運行:在命令行輸入 python 當前源文件.py
import numpy as np
import matplotlib.pyplot as plt
# 1.定義變換矩陣A,用於圖形平移(豎直平移)
A = np.array([[1,0],[0,-1]])
# 1.定義變換矩陣A,用於圖形剪切
# k = -0.8
# A = np.array([[1,0],[k,1]])
# 1.定義變換矩陣A,圖形旋轉
# theta = -(3.14/4)
# A = np.array([[np.cos(theta),np.sin(theta)],[-np.sin(theta),np.cos(theta)]])
# 1.定義變換矩陣A,圖形整體放大 1 倍
# A = np.array([[2,0],[0,-2]])
# 1.定義變換矩陣A,圖形整體縮小 0.75 倍
# A = np.array([[0.5,0],[0,0.5]])
# 2. 定義輸入矩陣(即輸入圖形)
B = np.array([[0, 1, 1, 0, 0],[1, 1, 0, 0, 1]])
# 3. 計算輸出矩陣(矩陣乘法)
Y = np.dot(A,B)
# 4. 繪製圖形
plt.axis([-3,3,-3,3])
plt.axvline(x=0, color='#A9A9A9')
plt.axhline(y=0, color='#A9A9A9')
plt.grid(True)
plt.plot(B[0],B[1],'-yo',lw=2) # 繪製輸入圖形
plt.plot(Y[0],Y[1],'-go',lw=2) # 繪製輸入圖形
plt.show()
具體用法,請往下看。
圖形平移:
- 豎直平移的變換矩陣是:,水平平移的變換矩陣是:。
# 1.定義變換矩陣A,用於圖形平移(豎直平移)
A = np.array([[1,0],[0,-1]])
圖形剪切:
- 水平剪切的變換矩陣是:,豎直剪切的變換矩陣是:, 會影響方向。
# 1.定義變換矩陣A,用於圖形剪切
k = -0.8
A = np.array([[1,0],[k,1]])
圖形放大:
水平放大的矩陣是:,豎直放大的變換矩陣是:
# 1.定義變換矩陣A,圖形整體放大 1 倍
A = np.array([[2,0],[0,2]])
圖形縮小同理。
圖形旋轉:
- 逆時針旋轉的變換矩陣是:,順時針旋轉的變換矩陣是:。
# 1.定義變換矩陣A,圖形旋轉
theta = -(3.14/4)
A = np.array([[np.cos(theta),np.sin(theta)],[-np.sin(theta),np.cos(theta)]])
旋轉的角度最複雜,我們可能不太清楚這個角度是怎麼來的。
矩陣變化的推導
我們推導一下,圖形旋轉的變化過程。
推導的前置知識:高中的三角函數。
不一定要每一步都弄明白,但要知道我們可以把矩陣看成一種對向量的變換(函數),這個很重要,理解的越深刻越好。
我們看最簡單的情況,如下圖。
藍色的向量旋轉 度角得到紅線 ,如果我們設這個變換的矩陣爲 ,則有這樣一個式子:
- 令 ,則有:。
因爲是經過旋轉得到的,因此新的座標和原來的座標一定是有聯繫的,這個聯繫就是角度 。
推導過程:
- 設向量(藍色)的模爲 ,由三角關係式得到:,即 ;,即 。
- 向量(紅色)由於僅有旋轉沒有伸縮,因此紅色向量的模依然是 :,即 ;,即
- ,
- ,比對係數確定
- ,一步步化簡得到最後的。
- ,這個結果就是變換 矩陣 呀!!!
圖形旋轉角度就是這麼推導過來的,在《數學女孩 4》的矩陣 — 線性變換一節,裏面就有其TA圖形變換的推導過程。
總結
第一部分,介紹了矩陣、來源、運算,工程應用是矩陣卷積,趁熱打鐵去搞定卷積網絡吧。
第二部分,介紹了看待矩陣的四種視角,我們選的是變換,工程應用是圖形圖像處理。
歸根結底,是函數表示變換。任意函數都是從輸入到輸出的變換。矩陣可以看做是向量的函數:)
這種變換,還可以擴展到三維空間,比如說電視成像、轉播。
電視機成像的原理大概是,通過一把電子槍,把電子打到屏幕上:
不過對於這樣的彩色圖片一把電子槍是不夠的:
可以把這幅圖片以 紅色、綠色、藍色 爲基,分爲三張圖片:
用三把電子槍分別把 紅色、綠色、藍色 的電子打到屏幕上,來呈現出彩色的畫面:
電視轉播則不同,信號不是以 紅色、綠色、藍色 的電子傳過來的,而是另一個顏色空間的表示方法。
不是靠三原色 傳遞,而是通過 、 傳遞。
- ,採用亮度-色差來描述顏色的顏色空間
- ,模擬視頻中的明度、彩度、同步脈衝分解開來各自傳送的端子。
彩色電視機背後有 、 接口,完整地插入 、 信號就可以看到彩色圖片了:
- 若是接入 ,可產生黑白圖像;
- 若是再接入 、 ,就會產生彩色圖像。
將 轉換爲 、,這個過程也是矩陣函數的一個實例:
加油:)