1. 程式人生 > >資料預處理系列:(十二)用截斷奇異值分解降維

資料預處理系列:(十二)用截斷奇異值分解降維

博主簡介:風雪夜歸子(英文名: Allen),機器學習演算法攻城獅,喜愛鑽研Machine Learning的黑科技,對Deep Learning和Artificial Intelligence充滿興趣,經常關注kaggle資料探勘競賽平臺,對資料、Machine Learning和Artificial Intelligence有興趣的各位童鞋可以一起探討哦,個人CSDN部落格: http://blog.csdn.net/u013719780?viewmode=contents

用截斷奇異值分解降維

截斷奇異值分解(Truncated singular value decomposition,TSVD)是一種矩陣因式分解(factorization)技術,將矩陣M分解成UΣΣV。它與PCA很像,只是SVD分解是在資料矩陣上進行,而PCA是在資料的協方差矩陣上進行。通常,SVD用於發現矩陣的主成份。

Getting ready

TSVD與一般SVD不同的是它可以產生一個指定維度的分解矩陣。例如,有一個n×n矩陣,通過SVD分解後仍然是一個n

×n矩陣,而TSVD可以生成指定維度的矩陣。這樣就可以實現降維了。

這裡我們還用iris資料集來演示TSVD:

In [1]:
from sklearn.datasets import load_iris
iris = load_iris()
iris_data = iris.data

How to do it...

TSVD物件的用法和其他物件類似。首先匯入需要的類,初始化,然後擬合:

In [5]:
from sklearn.decomposition import TruncatedSVD
In [6]:
svd
= TruncatedSVD(2) iris_transformed = svd.fit_transform(iris_data) iris_data[:5]
Out[6]:
array([[ 5.1,  3.5,  1.4,  0.2],
       [ 4.9,  3. ,  1.4,  0.2],
       [ 4.7,  3.2,  1.3,  0.2],
       [ 4.6,  3.1,  1.5,  0.2],
       [ 5. ,  3.6,  1.4,  0.2]])
In [7]:
iris_transformed[:5]
Out[7]:
array([[ 5.91220352, -2.30344211],
       [ 5.57207573, -1.97383104],
       [ 5.4464847 , -2.09653267],
       [ 5.43601924, -1.87168085],
       [ 5.87506555, -2.32934799]])

最終結果如下圖所示:

In [10]:
%matplotlib inline
import matplotlib.pyplot as plt
f = plt.figure(figsize=(5, 5))
ax = f.add_subplot(111)

ax.scatter(iris_transformed[:, 0], iris_transformed[:, 1], c=iris.target)
ax.set_title("Truncated SVD, 2 Components")
Out[10]:
<matplotlib.text.Text at 0x8600be0>

How it works...

現在我們演示了scikit-learn的TruncatedSVD模組,讓我們看看只用scipy學習一些細節。

首先,我們用scipylinalg處理SVD:

In [12]:
import numpy as np
from scipy.linalg import svd
D = np.array([[1, 2], [1, 3], [1, 4]])
D
Out[12]:
array([[1, 2],
       [1, 3],
       [1, 4]])
In [13]:
U, S, V = svd(D, full_matrices=False)
U.shape, S.shape, V.shape
Out[13]:
((3, 2), (2,), (2, 2))

我們可以根據SVD的定義,用UUSSVV還原矩陣DD

In [15]:
np.diag(S)
Out[15]:
array([[ 5.64015854,  0.        ],
       [ 0.        ,  0.43429448]])
In [16]:
np.dot(U.dot(np.diag(S)), V)
Out[16]:
array([[ 1.,  2.],
       [ 1.,  3.],
       [ 1.,  4.]])

TruncatedSVD返回的矩陣是UUSS的點積。如果我們想模擬TSVD,我們就去掉最新奇異值和對於UU的列向量。例如,我們想要一個主成份,可以這樣:

In [17]:
new_S = S[0]
new_U = U[:, 0]
new_U.dot(new_S)
Out[17]:
array([-2.20719466, -3.16170819, -4.11622173])

一般情況下,如果我們想要截斷維度tt,那麼我們就去掉NtN−t個奇異值。

There's more...

TruncatedSVD還有一些細節需要注意。

符號翻轉(Sign flipping)

TruncatedSVD有個“陷阱”。隨著隨機數生成器狀態的變化,TruncatedSVD連續地擬合會改變輸出的符合。為了避免這個問題,建議只用TruncatedSVD擬合一次,然後用其他變換。這正是管線命令的另一個用處。

要避免這種情況,可以這樣:

In [23]:
tsvd = TruncatedSVD(2)
tsvd.fit(iris_data)
tsvd.transform(iris_data)[:5]
Out[23]:
array([[ 5.91220352, -2.30344211],
       [ 5.57207573, -1.97383104],
       [ 5.4464847 , -2.09653267],
       [ 5.43601924, -1.87168085],
       [ 5.87506555, -2.32934799]])

稀疏矩陣

TruncatedSVD相比PDA的一個優勢是TruncatedSVD可以操作PDA處理不了的矩陣。這是因為PCA必須計算協方差矩陣,需要在整個矩陣上操作,如果矩陣太大,計算資源可能會不夠用。