1. 程式人生 > >奇異值分解(SVD)原理及應用

奇異值分解(SVD)原理及應用

4.4 存在 post 定性 tro ant 二維 5.1 spl

一、奇異值與特征值基礎知識:

特征值分解和奇異值分解在機器學習領域都是屬於滿地可見的方法。兩者有著很緊密的關系,我在接下來會談到,特征值分解和奇異值分解的目的都是一樣,就是提取出一個矩陣最重要的特征。先談談特征值分解吧:

1)特征值:

如果說一個向量v是方陣A的特征向量,將一定可以表示成下面的形式:

技術分享圖片

這時候λ就被稱為特征向量v對應的特征值,一個矩陣的一組特征向量是一組正交向量。特征值分解是將一個矩陣分解成下面的形式:

技術分享圖片

其中Q是這個矩陣A的特征向量組成的矩陣,Σ是一個對角陣,每一個對角線上的元素就是一個特征值。我這裏引用了一些參考文獻中的內容來說明一下。首先,要明確的是,一個矩陣其實就是一個線性變換,因為一個矩陣乘以一個向量後得到的向量,其實就相當於將這個向量進行了線性變換。比如說下面的一個矩陣:

技術分享圖片 它其實對應的線性變換是下面的形式:

技術分享圖片 因為這個矩陣M乘以一個向量(x,y)的結果是:

技術分享圖片

上面的矩陣是對稱的,所以這個變換是一個對x,y軸的方向一個拉伸變換(每一個對角線上的元素將會對一個維度進行拉伸變換,當值>1時,是拉長,當值<1時時縮短),當矩陣不是對稱的時候,假如說矩陣是下面的樣子:

技術分享圖片

它所描述的變換是下面的樣子:

技術分享圖片

  這其實是在平面上對一個軸進行的拉伸變換(如藍色的箭頭所示),在圖中,藍色的箭頭是一個最主要的變化方向(變化方向可能有不止一個),如果我們想要描述好一個變換,那我們就描述好這個變換主要的變化方向就好了。反過頭來看看之前特征值分解的式子,分解得到的Σ矩陣是一個對角陣,裏面的特征值是由大到小排列的,這些特征值所對應的特征向量就是描述這個矩陣變化方向(從主要的變化到次要的變化排列)。

  當矩陣是高維的情況下,那麽這個矩陣就是高維空間下的一個線性變換,這個線性變化可能沒法通過圖片來表示,但是可以想象,這個變換也同樣有很多的變換方向,我們通過特征值分解得到的前N個特征向量,那麽就對應了這個矩陣最主要的N個變化方向。我們利用這前N個變化方向,就可以近似這個矩陣(變換)。也就是之前說的:提取這個矩陣最重要的特征。總結一下,特征值分解可以得到特征值與特征向量,特征值表示的是這個特征到底有多重要,而特征向量表示這個特征是什麽,可以將每一個特征向量理解為一個線性的子空間,我們可以利用這些線性的子空間幹很多的事情。不過,特征值分解也有很多的局限,比如說變換的矩陣必須是方陣。

2)奇異值:

下面談談奇異值分解。特征值分解是一個提取矩陣特征很不錯的方法,但是它只是對方陣而言的,在現實的世界中,我們看到的大部分矩陣都不是方陣,比如說有N個學生,每個學生有M科成績,這樣形成的一個N * M的矩陣就不可能是方陣,我們怎樣才能描述這樣普通的矩陣呢的重要特征呢?奇異值分解可以用來幹這個事情,奇異值分解是一個能適用於任意的矩陣的一種分解的方法:

技術分享圖片 假設A是一個N * M的矩陣,那麽得到的U是一個N * N的方陣(裏面的向量是正交的,U裏面的向量稱為左奇異向量),Σ是一個N * M的矩陣(除了對角線的元素都是0,對角線上的元素稱為奇異值),V’(V的轉置)是一個N * N的矩陣,裏面的向量也是正交的,V裏面的向量稱為右奇異向量),從圖片來反映幾個相乘的矩陣的大小可得下面的圖片

技術分享圖片

那麽奇異值和特征值是怎麽對應起來的呢?首先,我們將一個矩陣A的轉置 * A,將會得到一個方陣,我們用這個方陣求特征值可以得到:技術分享圖片 這裏得到的v,就是我們上面的右奇異向量。此外我們還可以得到:

技術分享圖片 這裏的σ就是上面說的奇異值,u就是上面說的左奇異向量。奇異值σ跟特征值類似,在矩陣Σ中也是從大到小排列,而且σ的減少特別的快,在很多情況下,前10%甚至1%的奇異值的和就占了全部的奇異值之和的99%以上了。也就是說,我們也可以用前r大的奇異值來近似描述矩陣,這裏定義一下部分奇異值分解:

技術分享圖片

r是一個遠小於m、n的數,這樣矩陣的乘法看起來像是下面的樣子:

技術分享圖片

右邊的三個矩陣相乘的結果將會是一個接近於A的矩陣,在這兒,r越接近於n,則相乘的結果越接近於A。而這三個矩陣的面積之和(在存儲觀點來說,矩陣面積越小,存儲量就越小)要遠遠小於原始的矩陣A,我們如果想要壓縮空間來表示原矩陣A,我們存下這裏的三個矩陣:U、Σ、V就好了。

二、奇異值的計算:

奇異值的計算是一個難題,是一個O(N^3)的算法。在單機的情況下當然是沒問題的,matlab在一秒鐘內就可以算出1000 * 1000的矩陣的所有奇異值,但是當矩陣的規模增長的時候,計算的復雜度呈3次方增長,就需要並行計算參與了。Google的吳軍老師在數學之美系列談到SVD的時候,說起Google實現了SVD的並行化算法,說這是對人類的一個貢獻,但是也沒有給出具體的計算規模,也沒有給出太多有價值的信息。

其實SVD還是可以用並行的方式去實現的,在解大規模的矩陣的時候,一般使用叠代的方法,當矩陣的規模很大(比如說上億)的時候,叠代的次數也可能會上億次,如果使用Map-Reduce框架去解,則每次Map-Reduce完成的時候,都會涉及到寫文件、讀文件的操作。個人猜測Google雲計算體系中除了Map-Reduce以外應該還有類似於MPI的計算模型,也就是節點之間是保持通信,數據是常駐在內存中的,這種計算模型比Map-Reduce在解決叠代次數非常多的時候,要快了很多倍。

Lanczos叠代就是一種解對稱方陣部分特征值的方法(之前談到了,解A’* A得到的對稱方陣的特征值就是解A的右奇異向量),是將一個對稱的方程化為一個三對角矩陣再進行求解。按網上的一些文獻來看,Google應該是用這種方法去做的奇異值分解的。請見Wikipedia上面的一些引用的論文,如果理解了那些論文,也“幾乎”可以做出一個SVD了。

由於奇異值的計算是一個很枯燥,純數學的過程,而且前人的研究成果(論文中)幾乎已經把整個程序的流程圖給出來了。更多的關於奇異值計算的部分,將在後面的參考文獻中給出,這裏不再深入,我還是focus在奇異值的應用中去。

三、奇異值與主成分分析(PCA):

主成分分析在上一節裏面也講了一些,這裏主要談談如何用SVD去解PCA的問題。PCA的問題其實是一個基的變換,使得變換後的數據有著最大的方差。方差的大小描述的是一個變量的信息量,我們在講一個東西的穩定性的時候,往往說要減小方差,如果一個模型的方差很大,那就說明模型不穩定了。但是對於我們用於機器學習的數據(主要是訓練數據),方差大才有意義,不然輸入的數據都是同一個點,那方差就為0了,這樣輸入的多個數據就等同於一個數據了。以下面這張圖為例子:

技術分享圖片 這個假設是一個攝像機采集一個物體運動得到的圖片,上面的點表示物體運動的位置,假如我們想要用一條直線去擬合這些點,那我們會選擇什麽方向的線呢?當然是圖上標有signal的那條線。如果我們把這些點單純的投影到x軸或者y軸上,最後在x軸與y軸上得到的方差是相似的(因為這些點的趨勢是在45度左右的方向,所以投影到x軸或者y軸上都是類似的),如果我們使用原來的xy坐標系去看這些點,容易看不出來這些點真正的方向是什麽。但是如果我們進行坐標系的變化,橫軸變成了signal的方向,縱軸變成了noise的方向,則就很容易發現什麽方向的方差大,什麽方向的方差小了。

一般來說,方差大的方向是信號的方向,方差小的方向是噪聲的方向,我們在數據挖掘中或者數字信號處理中,往往要提高信號與噪聲的比例,也就是信噪比。對上圖來說,如果我們只保留signal方向的數據,也可以對原數據進行不錯的近似了。

PCA的全部工作簡單點說,就是對原始的空間中順序地找一組相互正交的坐標軸,第一個軸是使得方差最大的,第二個軸是在與第一個軸正交的平面中使得方差最大的,第三個軸是在與第1、2個軸正交的平面中方差最大的,這樣假設在N維空間中,我們可以找到N個這樣的坐標軸,我們取前r個去近似這個空間,這樣就從一個N維的空間壓縮到r維的空間了,但是我們選擇的r個坐標軸能夠使得空間的壓縮使得數據的損失最小。

還是假設我們矩陣每一行表示一個樣本,每一列表示一個feature,用矩陣的語言來表示,將一個m * n的矩陣A的進行坐標軸的變化,P就是一個變換的矩陣從一個N維的空間變換到另一個N維的空間,在空間中就會進行一些類似於旋轉、拉伸的變化。

技術分享圖片

而將一個m * n的矩陣A變換成一個m * r的矩陣,這樣就會使得本來有n個feature的,變成了有r個feature了(r < n),這r個其實就是對n個feature的一種提煉,我們就把這個稱為feature的壓縮。用數學語言表示就是:

技術分享圖片 但是這個怎麽和SVD扯上關系呢?之前談到,SVD得出的奇異向量也是從奇異值由大到小排列的,按PCA的觀點來看,就是方差最大的坐標軸就是第一個奇異向量,方差次大的坐標軸就是第二個奇異向量…我們回憶一下之前得到的SVD式子:

技術分享圖片 在矩陣的兩邊同時乘上一個矩陣V,由於V是一個正交的矩陣,所以V轉置乘以V得到單位陣I,所以可以化成後面的式子

技術分享圖片 將後面的式子與A * P那個m * n的矩陣變換為m * r的矩陣的式子對照看看,在這裏,其實V就是P,也就是一個變化的向量。這裏是將一個m * n 的矩陣壓縮到一個m * r的矩陣,也就是對列進行壓縮,如果我們想對行進行壓縮(在PCA的觀點下,對行進行壓縮可以理解為,將一些相似的sample合並在一起,或者將一些沒有太大價值的sample去掉)怎麽辦呢?同樣我們寫出一個通用的行壓縮例子:

技術分享圖片 這樣就從一個m行的矩陣壓縮到一個r行的矩陣了,對SVD來說也是一樣的,我們對SVD分解的式子兩邊乘以U的轉置U‘

技術分享圖片 這樣我們就得到了對行進行壓縮的式子。可以看出,其實PCA幾乎可以說是對SVD的一個包裝,如果我們實現了SVD,那也就實現了PCA了,而且更好的地方是,有了SVD,我們就可以得到兩個方向的PCA,如果我們對A’A進行特征值的分解,只能得到一個方向的PCA。

四、奇異值與潛在語義索引LSI:

潛在語義索引(Latent Semantic Indexing)與PCA不太一樣,至少不是實現了SVD就可以直接用的,不過LSI也是一個嚴重依賴於SVD的算法,之前吳軍老師在矩陣計算與文本處理中的分類問題中談到:

“三個矩陣有非常清楚的物理含義。第一個矩陣X中的每一行表示意思相關的一類詞,其中的每個非零元素表示這類詞中每個詞的重要性(或者說相關性),數值越大越相關。最後一個矩陣Y中的每一列表示同一主題一類文章,其中每個元素表示這類文章中每篇文章的相關性。中間的矩陣則表示類詞和文章雷之間的相關性。因此,我們只要對關聯矩陣A進行一次奇異值分解,w 我們就可以同時完成了近義詞分類和文章的分類。(同時得到每類文章和每類詞的相關性)。”

上面這段話可能不太容易理解,不過這就是LSI的精髓內容,我下面舉一個例子來說明一下,下面的例子來自LSA tutorial,具體的網址我將在最後的引用中給出:

技術分享圖片 這就是一個矩陣,不過不太一樣的是,這裏的一行表示一個詞在哪些title中出現了(一行就是之前說的一維feature),一列表示一個title中有哪些詞,(這個矩陣其實是我們之前說的那種一行是一個sample的形式的一種轉置,這個會使得我們的左右奇異向量的意義產生變化,但是不會影響我們計算的過程)。比如說T1這個title中就有guide、investing、market、stock四個詞,各出現了一次,我們將這個矩陣進行SVD,得到下面的矩陣:

技術分享圖片 左奇異向量表示詞的一些特性,右奇異向量表示文檔的一些特性,中間的奇異值矩陣表示左奇異向量的一行與右奇異向量的一列的重要程序,數字越大越重要。

繼續看這個矩陣還可以發現一些有意思的東西,首先,左奇異向量的第一列表示每一個詞的出現頻繁程度,雖然不是線性的,但是可以認為是一個大概的描述,比如book是0.15對應文檔中出現的2次,investing是0.74對應了文檔中出現了9次,rich是0.36對應文檔中出現了3次;

其次,右奇異向量中一的第一行表示每一篇文檔中的出現詞的個數的近似,比如說,T6是0.49,出現了5個詞,T2是0.22,出現了2個詞。

然後我們反過頭來看,我們可以將左奇異向量和右奇異向量都取後2維(之前是3維的矩陣),投影到一個平面上,可以得到:

技術分享圖片 在圖上,每一個紅色的點,都表示一個詞,每一個藍色的點,都表示一篇文檔,這樣我們可以對這些詞和文檔進行聚類,比如說stock 和 market可以放在一類,因為他們老是出現在一起,real和estate可以放在一類,dads,guide這種詞就看起來有點孤立了,我們就不對他們進行合並了。按這樣聚類出現的效果,可以提取文檔集合中的近義詞,這樣當用戶檢索文檔的時候,是用語義級別(近義詞集合)去檢索了,而不是之前的詞的級別。這樣一減少我們的檢索、存儲量,因為這樣壓縮的文檔集合和PCA是異曲同工的,二可以提高我們的用戶體驗,用戶輸入一個詞,我們可以在這個詞的近義詞的集合中去找,這是傳統的索引無法做到的。

五、SVD推薦系統

線性代數相關知識:

任意一個M*N的矩陣A(M行*N列M>N),可以被寫成三個矩陣的乘積:

1. U:(M行M列的列正交矩陣)

2. S:(M*N的對角線矩陣,矩陣元素非負)

3. V:(N*N的正交矩陣的倒置)

A=U*S*V‘(註意矩陣V需要倒置)

直觀地說:

假設我們有一個矩陣,該矩陣每一列代表一個user,每一行代表一個item

技術分享圖片

如上圖,ben,tom….代表user,season n代表item

矩陣值代表評分(0代表未評分):

如 ben對season1評分為5,tom對season1 評分為5,tom對season2未評分。

機器學習和信息檢索:

機器學習的一個最根本也是最有趣的特性是數據壓縮概念的相關性。

如果我們能夠從數據中抽取某些有意義的感念,則我們能用更少的比特位來表述這個數據。

從信息論的角度則是數據之間存在相關性,則有可壓縮性。

SVD就是用來將一個大的矩陣以降低維數的方式進行有損地壓縮。

降維:

下面我們將用一個具體的例子展示svd的具體過程。

首先是A矩陣。

A =

     5     5     0     5
     5     0     3     4
     3     4     0     3
     0     0     5     3
     5     4     4     5
     5     4     5     5

(代表上圖的評分矩陣)

使用matlab調用svd函數:

[U,S,Vtranspose]=svd(A)

U =
   -0.4472   -0.5373   -0.0064   -0.5037   -0.3857   -0.3298
   -0.3586    0.2461    0.8622   -0.1458    0.0780    0.2002
   -0.2925   -0.4033   -0.2275   -0.1038    0.4360    0.7065
   -0.2078    0.6700   -0.3951   -0.5888    0.0260    0.0667
   -0.5099    0.0597   -0.1097    0.2869    0.5946   -0.5371
   -0.5316    0.1887   -0.1914    0.5341   -0.5485    0.2429

S =
   17.7139         0         0         0
         0    6.3917         0         0
         0         0    3.0980         0
         0         0         0    1.3290
         0         0         0         0
         0         0         0         0

Vtranspose =
   -0.5710   -0.2228    0.6749    0.4109
   -0.4275   -0.5172   -0.6929    0.2637
   -0.3846    0.8246   -0.2532    0.3286
   -0.5859    0.0532    0.0140   -0.8085
技術分享圖片

分解矩陣之後我們首先需要明白S的意義。

可以看到S很特別,是個對角線矩陣。

每個元素非負,而且依次減小,具體要講明白元素值的意思大概和線性代數的特征向量,特征值有關。

但是可以大致理解如下:

在線性空間裏,每個向量代表一個方向。

所以特征值是代表該矩陣向著該特征值對應的特征向量的方向的變化權重。

所以可以取S對角線上前k個元素。

當k=2時候即將S(6*4)降維成S(2*2)

同時U(6*6),Vtranspose(4*4)相應地變為 U(6*2),Vtranspose(4*2).

如下圖(圖片裏的usv矩陣元素值和我自己matlab算出的usv矩陣元素值有些正負不一致,但是本質是相同的):

技術分享圖片

此時我們用降維後的U,S,V來相乘得到A2

A2=U(1:6,1:2)*S(1:2,1:2)*(V(1:4,1:2))‘ //matlab語句

結果:

A2 =

    5.2885    5.1627    0.2149    4.4591
    3.2768    1.9021    3.7400    3.8058
    3.5324    3.5479   -0.1332    2.8984
    1.1475   -0.6417    4.9472    2.3846
    5.0727    3.6640    3.7887    5.3130
    5.1086    3.4019    4.6166    5.5822

此時我們可以很直觀地看出,A2和A很接近,這就是之前說的降維可以看成一種數據的有損壓縮。

接下來我們開始分析該矩陣中數據的相關性。

我們將u的第一列當成x值,第二列當成y值。即u的每一行用一個二維向量表示,同理v的每一行也用一個二維向量表示。

如下圖:

技術分享圖片

從圖中可以看出:

Season5,Season6特別靠近。Ben和Fred也特別靠近。

同時我們仔細看一下A矩陣可以發現,A矩陣的第5行向量和第6行向量特別相似,Ben所在的列向量和Fred所在的列向量也特別相似。

所以從直觀上我們發現U矩陣和V矩陣可以近似來代表A矩陣,換據話說就是將A矩陣壓縮成U矩陣和V矩陣,至於壓縮比例得看當時對S矩陣取前k個數的k值是多少。

到這裏,我們已經完成了一半。

尋找相似用戶:

依然用實例來說明:

我們假設,現在有個名字叫Bob的新用戶,並且已知這個用戶對season n的評分向量為:[5 5 0 0 0 5]。(此向量為列向量)

我們的任務是要對他做出個性化的推薦。

我們的思路首先是利用新用戶的評分向量找出該用戶的相似用戶。

技術分享圖片

如上圖(圖中第二行式子有錯誤,Bob的轉置應為行向量)。

對圖中公式不做證明,只需要知道結論,結論是得到一個Bob的二維向量,即知道Bob的坐標。

將Bob坐標添加進原來的圖中:

技術分享圖片

然後從圖中找出和Bob最相似的用戶。

註意,最相似並不是距離最近的用戶,這裏的相似用余弦相似度計算。(關於相似度還有很多種計算方法,各有優缺點)

即夾角與Bob最小的用戶坐標。

可以計算出最相似的用戶是ben。

接下來的推薦策略就完全取決於個人選擇了。

這裏介紹一個非常簡單的推薦策略:

找出最相似的用戶,即ben。

觀察ben的評分向量為:【5 5 3 0 5 5】。

對比Bob的評分向量:【5 5 0 0 0 5】。

然後找出ben評分過而Bob未評分的item並排序,即【season 5:5,season 3:3】。

即推薦給Bob的item依次為 season5 和 season3。

最後還有一些關於整個推薦思路的可改進的地方:

1.

svd本身就是時間復雜度高的計算過程,如果數據量大的情況恐怕時間消耗無法忍受。 不過可以使用梯度下降等機器學習的相關方法來進行近似計算,以減少時間消耗。

2.

相似度計算方法的選擇,有多種相似度計算方法,每種都有對應優缺點,對針對不同場景使用最適合的相似度計算方法。

3.

推薦策略:首先是相似用戶可以多個,每個由相似度作為權重來共同影響推薦的item的評分。

奇異值分解(SVD)原理及應用