Tensorflow快餐教程 6 矩陣分解

2021-08-19 16:40:00 字數 4226 閱讀 8434

摘要: 特徵分解,奇異值分解,moore-penrose廣義逆

我們在《線性代數》課學過方陣的特徵向量和特徵值。

定義:設a∈f

n×na∈fn×n

是n階方陣。如果存在非零向量x∈f

n×1x∈fn×1使ax

=λxax=λx

對某個常數λ∈f

λ∈f成立,則稱λ

λ是a的特徵值(eigenvalue),x是屬於特徵值λ

λ的特徵向量。設σσ

是數域f上向量空間v上的線性變換,如果某個非零向量u∈v

u∈v被σ

σ對映到自己的常數倍σ(u

)=λu

σ(u)=λu

,則稱常數λ∈f

λ∈f是σ

σ的特徵值,向量u是屬於特徵值λ

λ的特徵向量。

又找λλ

又找a確實不是一件容易事。好在,我們可以把這事兒交給tensorflow去解決。我們可以用tf.self_adjoint_eigvals來求特徵值,相當於matlab的eig函式,只不過名字長了點。

例:

>>> a1 = tf.constant([[3,2,1],[0,-1,-2],[0,0,3]],dtype=tf.float64)

>>> sess.run(a1)

array([[ 3., 2., 1.],

[ 0., -1., -2.],

[ 0., 0., 3.]])

>>> sess.run(tf.self_adjoint_eigvals(a1))

array([-1., 3., 3.])

附:matlab例:

> a1 = [3,2,1;0,-1,-2;0,0,3]

a1 =

3 2 1

0 -1 -2

0 0 3

> eig(a1)

ans =3-1

3

也就是說,a1矩陣有3個特徵值-1,3,3。

我們把用self_adjoint_eigvals求出來的向量轉換成對角矩陣:

>>> sess.run(tf.diag(tf.self_adjoint_eigvals(a1))) 

array([[-1., 0., 0.],

[ 0., 3., 0.],

[ 0., 0., 3.]])

同樣,我們把每個特徵向量組成乙個矩陣,假設為v. 

這樣,我們可以得到乙個公式:a=v

diag

(λ)v

−1a=vdiag(λ)v−1

按照上面公式方法對矩陣a所做的操作叫做a的特徵分解(eigen decomposition)

不是每乙個矩陣都可以分解成特徵值和特徵向量。在某些情況下,特徵分解存在,但是值是複數而不是實數。幸運的是,機器學習中遇到的方陣基本都可以分解成a=q

λqta=qλqt

,其中q是特徵向量構成的正交矩陣,λ

λ是對角矩陣。

對於多數方陣,我們可以進行特徵值分解。如果對於非方陣該怎麼辦呢?答案是我們有類似的奇異向量(singular vector)和奇異值(singular value). 通過奇異向量和奇異值,我們可以把非方陣進行奇異值分解(singular value decomposition),簡稱svd. 

svd將矩陣分解為三個矩陣的乘積:a=u

dvta=udvt

。其中,u和v都定義為正交矩陣。d是對角矩陣,雖然不一定是方陣。

如果a是乙個mn的矩陣,那麼u是乙個mm的矩陣,v是乙個nn的矩陣,d與a一樣是mn的矩陣。

我們可以通過tf.svd函式來做奇異值分解,例:

>>> as =tf.constant( [[1,2,3],[4,5,6]], dtype=tf.float64)

>>> sess.run(as)

array([[1., 2., 3.],

[4., 5., 6.]])

>>> sess.run(tf.svd(as, full_matrices=true))

(array([9.508032 , 0.77286964]), array([[-0.3863177 , -0.92236578],

[-0.92236578, 0.3863177 ]]), array([[-0.42866713, 0.80596391, 0.40824829],

[-0.56630692, 0.11238241, -0.81649658],

[-0.7039467 , -0.58119908, 0.40824829]]))

as矩陣是23的矩陣。所以u是22的,而v是3*3的。第1個值是奇異值,[9.508032 , 0.77286964],它是d的對角線上值,其它位置為0.

d的完整值為:

array([[9.508032  , 0.        , 0.        ],

[0. , 0.77286964, 0. ]])

三個矩陣的完整值為:

#u

array([[-0.3863177 , -0.92236578],

[-0.92236578, 0.3863177 ]])

#darray([[9.508032 , 0. , 0. ],

[0. , 0.77286964, 0. ]])

#varray([[-0.42866713, 0.80596391, 0.40824829],

[-0.56630692, 0.11238241, -0.81649658],

[-0.7039467 , -0.58119908, 0.40824829]])

我們來驗算一下這個奇異值分解是不是正確的,別忘了v是要轉置的:

>>> sess.run(u @ d @ tf.transpose(v))

array([[0.99999997, 1.99999999, 2.99999997],

[3.99999997, 5.00000001, 5.99999996]])

雖然是有點浮點計算誤差,但是結果還確實是我們分解前的那個。關於計算誤差的問題,在機器學習中也自然是重要問題,後面會討論。

鋪墊了這麼多,其實我們是在為解線性方程組奮鬥。我們在第一節tensorflow的線性回歸例子,還有神經網路的例子都看到,求解線性方程組是重要的運算。

形如ax=b的線性方程組,如果a有逆矩陣就好辦了,兩邊分別右乘a逆就可以解出方程組。

但是問題是,機器學習中有很多方程是欠定的(underdetermined)。

這時候我們就需要一種類似於逆矩陣的工具 - moore-penrose廣義逆(pseudoinverse)。

moore-penrose廣義逆定義如下:a+

=lim

α→0(

ata+

αi)−

1ata+=limα→0(ata+αi)−1at

這個定義在計算時是沒法使用的,我們使用另乙個公式來算a+

=vd+

uta+=vd+ut

這個公式一看太熟悉了,就是剛才我們學習的奇異值分解嘛。

其中d+

d+,d的廣義逆的計算方法是所有非0值取倒數,然後矩陣轉置。

對於乙個ax=b方程組的最小二乘法解,一般來講不是唯一的。通常把它們中2-範數最小的乙個稱為極小最小二乘解,也叫最佳逼近解。

可以證明,ax=b必有唯一的極小最小二乘解,這個解就是x=a

+bx=a+b

首先複習一下逆陣的概念,如果乙個矩陣有逆陣,條件為:

必須是方陣

行列式不能為0

美國數學家moore於2023年逆矩陣的概念推廣到任意矩陣上,使用的方法是正交投影運算元來定義的。

2023年,英國數學家penrose用下面的方程組來定義廣義逆:ag

a=a,

gag=

g,(a

g)h=

ag(g

a)h=

gaaga=a,gag=g,(ag)h=ag(ga)h=ga

其中,h這個符號代表矩陣共軛的轉置,對於實數就相當於t。

不久之後,瑞典大地測量學家arne bjerhammer證明了moore廣義逆與penrose廣義逆的等價性。所以把它定義為moore-penrose廣義逆。除了a+a+

之外,還有a

− a−

廣義逆等。

Tensorflow快餐教程 5 範數

作為快餐教程,我們盡可能多上 多介紹工具,少講原理和公式。但是我也深知這樣是無法講清楚的,畢竟問題的複雜度擺在這裡呢。與大家一起在tensorflow探索一圈之後,我一定要寫乙個數學基礎比較紮實的進一步教程。一般大學本科的 線性代數 教材中是不講範數 廣義逆這些知識的,需要學習 矩陣論 課程。但是很...

雲棲社群 Tensorflow快餐教程

雲棲社群 tensorflow快餐教程 1 30行 搞定手寫識別 雲棲社群 tensorflow快餐教程 2 標量運算 雲棲社群 tensorflow快餐教程 3 向量 雲棲社群 tensorflow快餐教程 4 矩陣 雲棲社群 tensorflow快餐教程 5 範數 雲棲社群 tensorflow...

安裝TensorFlow教程

1.安裝anaconda 2.建立乙個conda環境,命名為tensorflow conda create n tensorflow3.用以下命令進入conda環境 source activate tensorflow tensorflow 進入tensorflow後的顯示符4.安裝tensorfl...