【機(jī)器學(xué)習(xí)】數(shù)據(jù)科學(xué)中必須知道的5個(gè)關(guān)于奇異值分解(SVD)的應(yīng)用
譯者 | Arno
前言:本文為大家介紹了5個(gè)關(guān)于奇異值分解(SVD)的應(yīng)用,希望對(duì)大家有所幫助。想要獲取更多的機(jī)器學(xué)習(xí)、深度學(xué)習(xí)資源,歡迎大家點(diǎn)擊上方藍(lán)字關(guān)注我們的公眾號(hào):磐創(chuàng)AI
奇異值分解(SVD)是數(shù)據(jù)科學(xué)中常見(jiàn)的降維技術(shù)
我們將在這里討論5個(gè)必須知道的SVD應(yīng)用,并了解它們?cè)跀?shù)據(jù)科學(xué)中的作用
我們還將看到在Python中實(shí)現(xiàn)SVD的三種不同方法
“Another day has passed, and I still haven’t used y = mx + b.”
這聽(tīng)起來(lái)是不是很熟悉?我經(jīng)常聽(tīng)到我大學(xué)的熟人抱怨他們花了很多時(shí)間的代數(shù)方程在現(xiàn)實(shí)世界中基本沒(méi)用。
好吧,但我可以向你保證,并不是這樣的。特別是如果你想開(kāi)啟數(shù)據(jù)科學(xué)的職業(yè)生涯。
線性代數(shù)彌合了理論與概念實(shí)際實(shí)施之間的差距。對(duì)線性代數(shù)的掌握理解打開(kāi)了我們認(rèn)為無(wú)法理解的機(jī)器學(xué)習(xí)算法的大門(mén)。線性代數(shù)的一種這樣的用途是奇異值分解(SVD)用于降維。

你在數(shù)據(jù)科學(xué)中一定很多次遇到SVD。它無(wú)處不在,特別是當(dāng)我們處理降維時(shí)。但它是什么?它是如何工作的?SVD應(yīng)用有什么?
事實(shí)上,SVD是推薦系統(tǒng)的基礎(chǔ),而推薦系統(tǒng)是谷歌,YouTube,亞馬遜,F(xiàn)acebook等大公司的核心。
我們將在本文中介紹SVD的五個(gè)超級(jí)有用的應(yīng)用,并將探討如何在Python中以三種不同的方式使用SVD。
我們將在此處遵循自上而下的方法并首先討論SVD應(yīng)用。如果你對(duì)它如何工作感興趣的,我在下面會(huì)講解SVD背后的數(shù)學(xué)原理?,F(xiàn)在你只需要知道四點(diǎn)來(lái)理解這些應(yīng)用:
SVD是將矩陣A分解為3個(gè)矩陣--U,S和V。
S是奇異值的對(duì)角矩陣。將奇異值視為矩陣中不同特征的重要性值
矩陣的秩是對(duì)存儲(chǔ)在矩陣中的獨(dú)特信息的度量。秩越高,信息越多
矩陣的特征向量是數(shù)據(jù)的最大擴(kuò)展或方差的方向
在大多數(shù)應(yīng)用中,我們希望將高秩矩陣縮減為低秩矩陣,同時(shí)保留重要信息。
1. SVD用于圖像壓縮
我們有多少次遇到過(guò)這個(gè)問(wèn)題?我們喜歡用我們的智能手機(jī)瀏覽圖像,并隨機(jī)將照片保存。然后突然有一天 ,提示手機(jī)沒(méi)有空間了!而圖像壓縮有助于解決這一問(wèn)題。
它將圖像的大小(以字節(jié)為單位)最小化到可接受的質(zhì)量水平。這意味著你可以在相同磁盤(pán)空間中存儲(chǔ)更多圖像。
圖片壓縮利用了在SVD之后僅獲得的一些奇異值很大的原理。你可以根據(jù)前幾個(gè)奇異值修剪三個(gè)矩陣,并獲得原始圖像的壓縮近似值,人眼無(wú)法區(qū)分一些壓縮圖像。以下是在Python中編寫(xiě)的代碼:
# 下載圖片 "https://cdn.pixabay.com/photo/2017/03/27/16/50/beach-2179624_960_720.jpg"
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import cv2
# 灰度化讀取圖片
img = cv2.imread('beach-2179624_960_720.jpg', 0)
# 得到svd
U, S, V = np.linalg.svd(img)
# 得到矩陣的形狀
print(U.shape, S.shape, V.shape)
# 以不同component數(shù)繪制圖像
comps = [638, 500, 400, 300, 200, 100]
plt.figure(figsize = (16, 8))
for i in range(6):
low_rank = U[:, :comps[i]] @ np.diag(S[:comps[i]]) @ V[:comps[i], :]
if(i == 0):
plt.subplot(2, 3, i+1), plt.imshow(low_rank, cmap = 'gray'), plt.axis('off'), plt.title("Original Image with n_components =" + str(comps[i]))
else:
plt.subplot(2, 3, i+1), plt.imshow(low_rank, cmap = 'gray'), plt.axis('off'), plt.title("n_components =" + str(comps[i]))
Output:

如果你說(shuō)即使是最后一張圖像,看起來(lái)好像也不錯(cuò)!是的,如果沒(méi)有前面的圖像對(duì)比,我也不會(huì)猜到這是經(jīng)過(guò)壓縮的圖像。
2. SVD用于圖像恢復(fù)
我們將通過(guò)矩陣填充的概念(以及一個(gè)很酷的Netflix示例)來(lái)理解圖像恢復(fù)。
矩陣填充是在部分觀察的矩陣中填充缺失元素的過(guò)程。Netflix問(wèn)題就是一個(gè)常見(jiàn)的例子。
給定一個(gè)評(píng)級(jí)矩陣,其中每個(gè)元素(i,j)表示客戶i對(duì)電影j的評(píng)級(jí),即客戶i觀看了電影j,否則該值為缺失值,我們想要預(yù)測(cè)剩余的元素以便對(duì)客戶于提出好的建議。
有助于解決這個(gè)問(wèn)題的基本事實(shí)是,大多數(shù)用戶在他們觀看的電影和他們給這些電影的評(píng)級(jí)中都有一個(gè)模式。因此,評(píng)級(jí)矩陣幾乎沒(méi)有獨(dú)特的信息。這意味著低秩矩陣能夠?yàn)榫仃囂峁┳銐蚝玫慕啤?/p>
這就是我們?cè)赟VD的幫助下所能夠?qū)崿F(xiàn)的。
你還在哪里看到這樣的屬性?是的,在圖像矩陣中!由于圖像是連續(xù)的,大多數(shù)像素的值取決于它們周圍的像素。因此,低秩矩陣可以是這些圖像的良好近似。
下面是結(jié)果的一張截圖:

問(wèn)題的整個(gè)表述可能很復(fù)雜并且需要了解其他一些概念。你可以參閱下面的論文[1]。
3. SVD用于特征臉
論文“Eigenfaces for Recognition”于1991年發(fā)表。在此之前,大多數(shù)面部識(shí)別方法都涉及識(shí)別個(gè)體特征,如眼睛或鼻子,并根據(jù)這些特征之間的位置,大小和關(guān)系來(lái)開(kāi)發(fā)模型。
特征臉?lè)椒ㄔ噲D在面部圖像中提取相關(guān)信息,盡可能有效地對(duì)其進(jìn)行編碼,并將一個(gè)面部編碼與數(shù)據(jù)庫(kù)中的模型編碼進(jìn)行比較。
通過(guò)將每個(gè)面部表達(dá)為新面部空間中所選擇的特征臉的線性組合來(lái)獲得編碼。
讓我把這個(gè)方法分解為五個(gè)步驟:
收集面部訓(xùn)練集
通過(guò)找到最大方差的方向-特征向量或特征臉來(lái)找到最重要的特征
選擇對(duì)應(yīng)于最高特征值的M個(gè)特征臉。這些特征臉現(xiàn)在定義了一個(gè)新的面部空間
將所有數(shù)據(jù)投影到此面部空間中
對(duì)于新面部,將其投影到新面部空間中,找到空間中最近的面部,并將面部分類為已知或未知面部
你可以使用PCA和SVD找到這些特征臉。這是我在Labeled Faces in the Wild數(shù)據(jù)集中上執(zhí)行SVD后獲得的幾個(gè)特征臉中的第一個(gè):
我們可以看到,只有前幾行中的圖像看起來(lái)像實(shí)際的面部。其他看起來(lái)很糟糕,因此我放棄了它們。我保留了總共120個(gè)特征臉,并將數(shù)據(jù)轉(zhuǎn)換為新的面部空間。然后我使用k近鄰分類器來(lái)預(yù)測(cè)基于面部的姓名。
你可以在下面看到分類報(bào)告。顯然,還有改進(jìn)的余地。你可以嘗試調(diào)整特征臉的數(shù)量或使用不同的分類器進(jìn)行試驗(yàn):

看看一些預(yù)測(cè)值及其真實(shí)標(biāo)簽:

聚類是將類似對(duì)象劃分在一起的任務(wù)。這是一種無(wú)監(jiān)督的機(jī)器學(xué)習(xí)技術(shù)。對(duì)于我們大多數(shù)人來(lái)說(shuō),聚類是K-Means聚類(一種簡(jiǎn)單但功能強(qiáng)大的算法)的代名詞,但是,這并不是準(zhǔn)確的說(shuō)法。
考慮以下情況:

顯然,同心圓中有2個(gè)簇。但是,n_clusters = 2的KMeans給出了以下簇:
K-Means絕對(duì)不是這里使用的合適算法。譜聚類是一種可以解決這個(gè)問(wèn)題的技術(shù),它源于圖論。以下是基本步驟:
從數(shù)據(jù)Affnity matrix(A)或Adjacent matrix開(kāi)始。這表示一個(gè)對(duì)象與另一個(gè)對(duì)象的相似程度。在圖中,這將表示點(diǎn)之間是否存在邊緣
找到每個(gè)對(duì)象的 Degree matrix (D) 。這是一個(gè)對(duì)角矩陣,其元素(i,i)等于對(duì)象i相似的對(duì)象數(shù)
找到Affnity matrix的 Laplacian matrix(L) (L):L = A - D
根據(jù)它們的特征值找到Laplacian matrix的最高k個(gè)特征向量
在這些特征向量上運(yùn)行k-means,將對(duì)象聚類為k類
你可以通過(guò)下面的鏈接閱讀完整的算法及其數(shù)學(xué)原理^2,而scikit-learn中譜聚類的實(shí)現(xiàn)類似于KMeans:
from sklearn.datasets import make_circles
from sklearn.neighbors import kneighbors_graph
from sklearn.cluster import SpectralClustering
import numpy as np
import matplotlib.pyplot as plt
# s生成數(shù)據(jù)
X, labels = make_circles(n_samples=500, noise=0.1, factor=.2)
# 可視化數(shù)據(jù)
plt.scatter(X[:, 0], X[:, 1])
plt.show()
# 訓(xùn)練和預(yù)測(cè)
s_cluster = SpectralClustering(n_clusters = 2, eigen_solver='arpack',
affinity="nearest_neighbors").fit_predict(X)
# 可視化結(jié)果
plt.scatter(X[:, 0], X[:, 1], c = s_cluster)
plt.show()
你將從上面的代碼中得到以下不錯(cuò)的聚類結(jié)果:

5. SVD用于從視頻中刪除背景
想一想如何區(qū)分視頻背景和前景。視頻的背景基本上是靜態(tài)的 - 它看不到很多變化。所有的變化都在前景中看到。這是我們用來(lái)將背景與前景分開(kāi)的屬性。
以下是我們可以采用的步驟來(lái)實(shí)現(xiàn)此方法:
從視頻創(chuàng)建矩陣M -- 這是通過(guò)定期從視頻中采樣圖像快照,將這些圖像矩陣展平為數(shù)組,并將它們存儲(chǔ)為矩陣M的列。
我們得到以下矩陣M的圖:
你認(rèn)為這些水平和波浪線代表什么?花一點(diǎn)時(shí)間考慮一下。
水平線表示在整個(gè)視頻中不改變的像素值?;旧?,這些代表了視頻中的背景。波浪線顯示變化并代表前景。
因此,我們可以將M視為兩個(gè)矩陣的總和 - 一個(gè)表示背景,另一個(gè)表示前景
背景矩陣沒(méi)有看到像素的變化,因此是多余的,即它沒(méi)有很多獨(dú)特的信息。所以,它是一個(gè)低秩矩陣
因此,M的低秩近似是背景矩陣。我們?cè)诖瞬襟E中使用SVD
我們可以通過(guò)簡(jiǎn)單地從矩陣M中減去背景矩陣來(lái)獲得前景矩陣
這是視頻一個(gè)刪除背景后的幀:

到目前為止,我們已經(jīng)討論了SVD的五個(gè)非常有用的應(yīng)用。但是,SVD背后的數(shù)學(xué)實(shí)際上是如何運(yùn)作的?作為數(shù)據(jù)科學(xué)家,它對(duì)我們有多大用處?讓我們?cè)谙乱还?jié)中理解這些要點(diǎn)。
我在本文中大量使用了“秩”這個(gè)術(shù)語(yǔ)。事實(shí)上,通過(guò)關(guān)于SVD及其應(yīng)用的所有文獻(xiàn),你將非常頻繁地遇到術(shù)語(yǔ)“矩陣的秩”。那么讓我們從了解這是什么開(kāi)始。
矩陣的秩
矩陣的秩是矩陣中線性無(wú)關(guān)的行(或列)向量的最大數(shù)量。如果向量r不能表示為r1和r2的線性組合,則稱向量r與向量r1和r2線性無(wú)關(guān)。

考慮下面的三個(gè)矩陣:

在矩陣A中,行向量r2是r1的倍數(shù),r2 = 2 r1,因此它只有一個(gè)無(wú)關(guān)的行向量。Rank(A)= 1
在矩陣B中,行向量r3是r1和r2之和,r3 = r1 + r2,但r1和r2是無(wú)關(guān)的,Rank(B)= 2
在矩陣C中,所有3行彼此無(wú)關(guān)。Rank(C)= 3
矩陣的秩可以被認(rèn)為是由矩陣表示的獨(dú)特信息量多少的代表。秩越高,信息越高。
SVD
SVD將矩陣分解為3個(gè)矩陣的乘積,如下所示:

如果A是m x n矩陣:
U是左奇異向量的m×m矩陣
S是以遞減順序排列的奇異值的m×n對(duì)角矩陣
V是右奇異向量的n×n矩陣
為什么SVD用于降維?
你可能想知道我們?yōu)槭裁匆?jīng)歷這種看似辛苦的分解??梢酝ㄟ^(guò)分解的替代表示來(lái)理解原因。見(jiàn)下圖:

分解允許我們將原始矩陣表示為低秩矩陣的線性組合。
在實(shí)際應(yīng)用中,你將觀察到的只有前幾個(gè)(比如k)奇異值很大。其余的奇異值接近于零。因此,可以忽略除前幾個(gè)之外而不會(huì)丟失大量信息。請(qǐng)參見(jiàn)下圖中的矩陣截?cái)喾绞剑?/p>
總結(jié)以下3點(diǎn):
使用SVD,我們能夠用3個(gè)較小的矩陣U,S和V表示我們的大矩陣A
這在大型計(jì)算中很有用
我們可以得到A的k-秩近似。為此,選擇前k個(gè)奇異值并相應(yīng)地截?cái)?個(gè)矩陣。
我們知道什么是SVD,它是如何工作的,以及它在現(xiàn)實(shí)世界中的用途。但是我們?nèi)绾巫约簩?shí)現(xiàn)SVD呢?
SVD的概念聽(tīng)起來(lái)很復(fù)雜。你可能想知道如何找到3個(gè)矩陣U,S和V。如果我們手動(dòng)計(jì)算這些矩陣,這是一個(gè)漫長(zhǎng)的過(guò)程。
幸運(yùn)的是,我們不需要手動(dòng)執(zhí)行這些計(jì)算。我們可以用三種簡(jiǎn)單的方式在Python中實(shí)現(xiàn)SVD。
1. numpy中的SVD
NumPy是Python中科學(xué)計(jì)算的基礎(chǔ)包。它具有有用的線性代數(shù)功能以及其他應(yīng)用。
你可以使用numpy.linalg中的SVD獲取完整的矩陣U,S和V。注意,S是對(duì)角矩陣,這意味著它的大多數(shù)元素都是0。這稱為稀疏矩陣。為了節(jié)省空間,S作為奇異值的一維數(shù)組而不是完整的二維矩陣返回。
import numpy as np
from numpy.linalg import svd
# 定義二維矩陣
A = np.array([[4, 0], [3, -5]])
U, S, VT = svd(A)
print("Left Singular Vectors:")
print(U)
print("Singular Values:")
print(np.diag(S))
print("Right Singular Vectors:")
print(VT)
# 檢查分解是否正確
# @ 表示矩陣乘法
print(U @ np.diag(S) @ VT)
2. scikit-learn中的Truncated SVD
在大多數(shù)常見(jiàn)的應(yīng)用中,我們不希望找到完整的矩陣U,S和V。我們?cè)诮稻S和潛在語(yǔ)義分析中看到了這一點(diǎn),還記得嗎?
我們最終會(huì)修剪矩陣,所以為什么要首先找到完整的矩陣?
在這種情況下,最好使用sklearn.decomposition中的TruncatedSVD。你可以通過(guò)n_components參數(shù)指定所需的特征數(shù)量輸出。n_components應(yīng)嚴(yán)格小于輸入矩陣中的特征數(shù):
import numpy as np
from sklearn.decomposition import TruncatedSVD
A = np.array([[-1, 2, 0], [2, 0, -2], [0, -2, 1]])
print("Original Matrix:")
print(A)
svd = TruncatedSVD(n_components = 2)
A_transf = svd.fit_transform(A)
print("Singular values:")
print(svd.singular_values_)
print("Transformed Matrix after reducing to 2 features:")
print(A_transf)
3. scikit-learn中的Randomized SVD
Randomized SVD提供與Truncated SVD相同的結(jié)果,并且具有更快的計(jì)算時(shí)間。Truncated SVD使用ARPACK精確求解,但隨機(jī)SVD使用了近似技術(shù)。
import numpy as np
from sklearn.utils.extmath import randomized_svd
A = np.array([[-1, 2, 0], [2, 0, -2], [0, -2, 1]])
u, s, vt = randomized_svd(A, n_components = 2)
print("Left Singular Vectors:")
print(u)
print("Singular Values:")
print(np.diag(s))
print("Right Singular Vectors:")
print(vt)
[1]: https://sci-hub.tw/10.1145/3274250.3274261
—END— 聲明:部分內(nèi)容來(lái)源于網(wǎng)絡(luò),僅供讀者學(xué)術(shù)交流之目的。文章版權(quán)歸原作者所有。如有不妥,請(qǐng)聯(lián)系刪除。
往期精彩回顧
適合初學(xué)者入門(mén)人工智能的路線及資料下載 (圖文+視頻)機(jī)器學(xué)習(xí)入門(mén)系列下載 機(jī)器學(xué)習(xí)及深度學(xué)習(xí)筆記等資料打印 《統(tǒng)計(jì)學(xué)習(xí)方法》的代碼復(fù)現(xiàn)專輯
機(jī)器學(xué)習(xí)交流qq群955171419,加入微信群請(qǐng)掃碼
感谢您访问我们的网站,您可能还对以下资源感兴趣:
国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频
