如何让奇异值分解(SVD)变得不“奇异”?
關鍵時刻,第一時間送達!
閱讀本文需要 8 分鐘
在之前的一篇文章:劃重點!通俗解釋協方差與相關系數,紅色石頭為大家通俗化地講解了協方差是如何定義的,以及如何直觀理解協方差,并且比較了協方差與相關系數的關系。
本文紅色石頭將繼續使用白話語言,介紹機器學習中應用十分廣泛的矩陣分解方法:奇異值分解(SVD)。本文不注重詳細的數學推導,只注重感性的理解以及如何在實際應用中使用它們。
1
普通方陣的矩陣分解(EVD)
我們知道如果一個矩陣 A 是方陣,即行列維度相同(mxm),一般來說可以對 A 進行特征分解:
其中,U 的列向量是 A 的特征向量,Λ 是對角矩陣,Λ 對角元素是對應特征向量的特征值。
舉個簡單的例子,例如方陣 A 為:
那么對其進行特征分解,相應的 Python 代碼為:
運行輸出:
特征分解就是把 A 拆分,如下所示:
其中,特征值?λ1=3.41421356,對應的特征向量 u1=[0.81649658 0.57735027];特征值?λ2=0.58578644,對應的特征向量 u2=[-0.81649658 0.57735027],特征向量均為列向量。
值得注意的是,特征向量都是單位矩陣,相互之間是線性無關的,但是并不正交。得出的結論是對于任意方陣,不同特征值對應的特征向量必然線性無關,但是不一定正交。
02
對稱矩陣的矩陣分解(EVD)
如果方陣 A 是對稱矩陣,例如:
對稱矩陣特征分解滿足以下公式:
那么對其進行特征分解,相應的 Python 代碼為:
運行輸出:
特征分解就是把 A 拆分,如下所示:
其中,特征值?λ1=2.61803399,對應的特征向量 u1=[0.85065081 0.52573111];特征值?λ2=0.38196601,對應的特征向量 u2=[-0.52573111 0.85065081],特征向量均為列向量。
注意,我們發現對陣矩陣的分解和非對稱矩陣的分解除了公式不同之外,特征向量也有不同的特性。對稱矩陣的不同特征值對應的特征向量不僅線性無關,而且是相互正交的。什么是正交呢?就是特征向量內積為零。驗證如下:
0.85065081 * -0.52573111 + 0.52573111 * 0.85065081 = 0
重點來了,對稱矩陣 A 經過矩陣分解之后,可以寫成以下形式:
對上式進行驗證:
這種分解形式非常有用,待會紅色石頭即將介紹。
3
奇異值分解(SVD)
我們發現,在矩陣分解里的 A 是方陣或者是對稱矩陣,行列維度都是相同的。但是實際應用中,很多矩陣都是非方陣、非對稱的。那么如何對這類矩陣進行分解呢?因此,我們就引入了針對維度為 mxn 矩陣的分解方法,稱之為奇異值分解(Singular Value Decomposition)。
假設矩陣 A 的維度為 mxn,雖然 A 不是方陣,但是下面的矩陣卻是方陣,且維度分別為 mxm、nxn。
因此,我們就可以分別對上面的方陣進行分解:
其中,Λ1 和?Λ2 是對焦矩陣,且對角線上非零元素均相同,即兩個方陣具有相同的非零特征值,特征值令為?σ1,?σ2, ... ,?σk。值得注意的是,k<=m 且 k<=n。
根據?σ1,?σ2, ... , σk 就可以得到矩陣 A 的特征值為:
接下來,我們就能夠得到奇異值分解的公式:
其中,P 稱為左奇異矩陣,維度是 mxm,Q 稱為右奇異矩陣,維度是 nxn。Λ 并不是方陣,其維度為 mxn,Λ 對角線上的非零元素就是 A 的特征值?λ1,?λ2, ... ,?λk。圖形化表示奇異值分解如下圖所示:
舉個簡單的例子來說明,令 A 為 3x2 的矩陣:
則有:
計算得到特征向量 P 和對應的特征值?σ 為:
然后,有:
計算得到特征向量 Q 和對應的特征值?σ?為:
則我們看可以得到 A 的特征值為:
最后,整合矩陣相乘結果,滿足奇異值分解公式。
奇異值分解可以寫成以下和的形式:
其中,p1 和 q1 分別為左奇異矩陣和右奇異矩陣的特征向量。
4
如何形象化理解 SVD
奇異值分解到底有什么用呢?如何形象化地理解奇異值?我們一起來看下面的例子。
首先放上男神的照片:
我們對該圖片進行奇異值分解,則該圖片可寫成以下和的形式:
上式中,λ1,?λ2, ... ,?λk 是按照從大到小的順序的。
首先,若我們只保留最大的奇異值 λ1,舍去其它奇異值,即 A=λ1p1q1T,然后作圖:
結果完全看不清楚,再多加幾個奇異值,取前 5 個最大的奇異值,然后作圖:
現在貌似有點輪廓了,繼續增加奇異值,取前 10 個最大的奇異值,然后作圖:
又清晰了一些,繼續將奇異值增加到 20 個,然后作圖:
現在已經比較清晰了,繼續將奇異值增加到 50 個,然后作圖:
可見,取前 50 個最大奇異值來重構圖像時,已經非常清晰了。我們得到和原圖差別不大的圖像。也就是說,隨著選擇的奇異值的增加,重構的圖像越來越接近原圖像。
基于這個原理,奇異值分解可以用來進行圖片壓縮。例如在本例中,原始圖片的維度是 870x870,總共需要保存的像素值是:870x870=756900。若使用 SVD,取前 50 個最大的奇異值即可,則總共需要存儲的元素個數為:
(870+1+870)x50=87050
顯然,所需存儲量大大減小了。在需要存儲許多高清圖片,而存儲空間有限的情況下,就可以利用 SVD,保留奇異值最大的若干項,舍去奇異值較小的項即可。
值得一提的是,奇異值從大到小衰減得特別快,在很多情況下,前 10% 甚至 1% 的奇異值的和就占了全部的奇異值之和的 99% 以上了。這對于數據壓縮來說是個好事。
SVD 數據壓縮的算法圖示如下:
SVD 數據壓縮的示例代碼為:
from skimage import io import matplotlib.pyplot as plt from PIL import Imageimg=io.imread('./ng.jpg') m,n = img.shape io.imshow(img) plt.show()P, L, Q = np.linalg.svd(img) tmp = np.diag(L) if m < n:d = np.hstack((tmp,np.zeros((m,n-m)))) else:d = np.vstack((tmp,np.zeros((m-n,n))))# k = 50 img2 = P[:,:50].dot(d[:50,:50]).dot(Q[:50,:]) io.imshow(np.uint8(img2)) plt.show()tmp = np.uint8(img2) im = Image.fromarray(tmp) im.save("out.jpg")現在,你已經完全了解了奇異值分解了吧。是不是挺簡單也挺有意思呢?
參考文獻:
https://zhuanlan.zhihu.com/p/26306568
https://www.zhihu.com/question/22237507/answer/53804902
推薦閱讀
【干貨】我的機器學習入門路線圖
長文!機器學習筆試精選 100 題【附詳細解析】
劃重點!通俗解釋協方差與相關系數
總結
以上是生活随笔為你收集整理的如何让奇异值分解(SVD)变得不“奇异”?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C/C++只做经典编程语言
- 下一篇: 如何能能够学好软件编程技术