【机器学习基础】数学推导+纯Python实现机器学习算法18:奇异值分解SVD
Python機器學習算法實現
Author:louwill
Machine Learning Lab
? ? ?
???? 奇異值分解(Singular Value Decomposition,SVD)作為一種常用的矩陣分解和數據降維方法,在機器學習中也得到了廣泛的應用,比如自然語言處理中的SVD詞向量和潛在語義索引,推薦系統中的特征分解,SVD用于PCA降維以及圖像去噪與壓縮等。作為一個基礎算法,我們有必要將其單獨拎出來在機器學習系列中進行詳述。
特征值與特征向量
???? 在學習SVD原理之前,我們有必要對矩陣的特征值與特征向量進行回顧。矩陣的特征值與特征向量定義如下:
???? 其中為矩陣,為一維向量,則定義為矩陣的一個特征值,向量是矩陣的特征值所對應的特征向量。
???? 實際計算時,我們通過求解齊次方程來計算矩陣的特征值和特征向量。
???? 將矩陣計算出特征值和特征向量的直接好處就是我們可以將矩陣進行分解,假設矩陣有個特征值,以及每個特征值對應的特征向量,那么矩陣就可以用下式進行分解:
???? 在線性代數中,我們也將上式成為矩陣的對角化,或者求矩陣的相似矩陣。一般我們會將矩陣的個特征向量進行標準化和正交化處理,滿足,所以就有,即為酉矩陣。最終上述分解表達式可表示為:
???? 矩陣要計算特征值和特征向量的一個必要條件就是該矩陣必須要為方陣,即矩陣維度為。
???? 但大多數情況下,我們碰到的矩陣都是非方陣的的情形。當矩陣行列不等時,如果我們也想對其進行矩陣分解,那就必須使用SVD了。
SVD詳解
???? 假設現在我們要對非方陣進行矩陣分解,定義分解表達式為:
???? 其中為矩陣,為對角陣,為矩陣。和均為酉矩陣,即和滿足:
???? SVD的圖解示意如下圖所示。
???? 我們可以通過求解齊次方程的形式來求解特征值和特征矩陣,那么在上式中,我們如何求解這三個矩陣呢?
???? 還是需要借助于矩陣的特征值和特征向量。
???? 由于矩陣是非方陣,現在將矩陣與其轉置矩陣做矩陣乘法運算,可得到的方陣,然后對該矩陣求特征值和特征向量:
???? 由上式我們即可求得方陣的個特征值和特征向量,該個特征向量構成的特征矩陣即為矩陣。我們把矩陣中的每個向量稱為矩陣的左奇異向量。
???? 同理,將矩陣的其轉置矩陣與矩陣做矩陣乘法運算,同樣可得的方陣,然后對該矩陣求特征值和特征向量:
???? 由上式我們即可求得方陣的個特征值和特征向量,該個特征向量構成的特征矩陣即為矩陣。我們把矩陣中的每個向量稱為矩陣的右奇異向量。
???? 左奇異矩陣和右奇異矩陣求出來后,我們只剩下中間的奇異值矩陣尚未求出。奇異值矩陣除了對角線上的奇異值,其余元素均為0,所以我們只要求出矩陣的奇異值即可。可推導:
???? 所以我們可由上述推導計算得到奇異值矩陣。實際上,由下述推導:
???? 可知特征值矩陣為奇異值矩陣的平方,即特征值為奇異值的平方。
Python SVD實現
???? Python中numpy和scipy兩個科學計算庫都直接提供了SVD的實現方式,所以我們這里就不再基于numpy手寫SVD的實現過程了。下面基于numpy.linalg線性代數模塊下的svd函數來看一個計算實例。
import numpy as np # 創建一個矩陣A A = np.array([[0,1],[1,1],[1,0]]) # 對其進行SVD分解 u, s, vt = np.linalg.svd(A, full_matrices=True) print(u.shape,?s.shape,?vt.shape) (3, 3) (2,) (2, 2)???? 然后分別查看u、s和v矩陣,并驗證下是否可由這三個矩陣恢復到矩陣A。
# 矩陣u print(u,?s,?v.T) array([[-4.08248290e-01, 7.07106781e-01, 5.77350269e-01],[-8.16496581e-01, 5.55111512e-17, -5.77350269e-01],[-4.08248290e-01, -7.07106781e-01, 5.77350269e-01]]) array([1.73205081, 1. ]) array([[-0.70710678, -0.70710678],[-0.70710678,??0.70710678]])???? 可以看到該svd函數對結果中的奇異值矩陣進行簡化了,只給出了奇異值向量,將矩陣中其余為0的元素均省去了。
???? 基本能夠恢復矩陣A,因浮點數存在計算誤差,這里可以忽略不計。
SVD圖像壓縮
????? 我們可以嘗試將SVD用于圖像的壓縮算法。其原理就是保存像素矩陣的前k個奇異值,并在此基礎上做圖像恢復。由SVD的原理我們可以知道,在SVD分解中越靠前的奇異值越重要,代表的信息含量越大。
???? 下面我們嘗試對一個圖像進行SVD分解,并分別取前1~50個奇異值來恢復該圖像。需要恢復的圖像如下(厚著臉皮拿筆者自己作為示例):
???? 實現代碼如下:
import numpy as np import os from PIL import Image from tqdm import tqdm # 定義恢復函數,由分解后的矩陣恢復到原矩陣 def restore(u, s, v, K): '''u:左奇異矩陣v:右奇異矩陣s:奇異值矩陣K:奇異值個數'''m, n = len(u), len(v[0])a = np.zeros((m, n)) for k in range(K):uk = u[:, k].reshape(m, 1)vk = v[k].reshape(1, n) # 前k個奇異值的加總a += s[k] * np.dot(uk, vk) a = a.clip(0, 255) return np.rint(a).astype('uint8') A = np.array(Image.open("./ml_lab.jpg", 'r')) # 對RGB圖像進行奇異值分解 u_r, s_r, v_r = np.linalg.svd(A[:, :, 0]) u_g, s_g, v_g = np.linalg.svd(A[:, :, 1]) u_b, s_b, v_b = np.linalg.svd(A[:, :, 2]) # 使用前50個奇異值 K = 50 output_path = r'./svd_pic' # 恢復圖像 for k in tqdm(range(1, K+1)):R = restore(u_r, s_r, v_r, k)G = restore(u_g, s_g, v_g, k)B = restore(u_b, s_b, v_b, k)I = np.stack((R, G, B), axis=2) Image.fromarray(I).save('%s\\svd_%d.jpg'?%?(output_path,?k))???? 當僅使用一個奇異值時,被壓縮后的圖像模糊一團,除了顏色線條啥也看不出:
???? 當使用前10個奇異值時,恢復后的壓縮圖像隱約可見輪廓,就像打了馬賽克一樣:
???? 如此繼續擴大奇異值的數量,當我們取到前50個奇異值的時候,恢復后的壓縮圖像已經相對清晰許多了:
???? 漸進效果如下:
???? 總體而言就是圖像清晰度隨著奇異值數量增多而變好。當奇異值k不斷增大時,恢復后的圖像就會無限逼近于真實圖像。這便是基于SVD的圖像壓縮原理。
往期精彩:
數學推導+純Python實現機器學習算法17:XGBoost
數學推導+純Python實現機器學習算法16:Adaboost
數學推導+純Python實現機器學習算法15:GBDT
數學推導+純Python實現機器學習算法14:Ridge嶺回歸
數學推導+純Python實現機器學習算法13:Lasso回歸
數學推導+純Python實現機器學習算法12:貝葉斯網絡
數學推導+純Python實現機器學習算法11:樸素貝葉斯
數學推導+純Python實現機器學習算法10:線性不可分支持向量機
數學推導+純Python實現機器學習算法8-9:線性可分支持向量機和線性支持向量機
數學推導+純Python實現機器學習算法7:神經網絡
數學推導+純Python實現機器學習算法6:感知機
數學推導+純Python實現機器學習算法5:決策樹之CART算法
數學推導+純Python實現機器學習算法4:決策樹之ID3算法
數學推導+純Python實現機器學習算法3:k近鄰
數學推導+純Python實現機器學習算法2:邏輯回歸
數學推導+純Python實現機器學習算法1:線性回歸
往期精彩回顧適合初學者入門人工智能的路線及資料下載機器學習及深度學習筆記等資料打印機器學習在線手冊深度學習筆記專輯《統計學習方法》的代碼復現專輯 AI基礎下載機器學習的數學基礎專輯獲取一折本站知識星球優惠券,復制鏈接直接打開:https://t.zsxq.com/yFQV7am本站qq群1003271085。加入微信群請掃碼進群:總結
以上是生活随笔為你收集整理的【机器学习基础】数学推导+纯Python实现机器学习算法18:奇异值分解SVD的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【深度学习】基于深度学习的数据增广技术一
- 下一篇: 【Python基础】告别枯燥,60 秒