機器學習(三) 線性代數-矩陣
矩陣
矩陣是一個二維的資料集合。我們将矩陣表示為清單的清單,每個内部清單的大小都一樣,表示矩陣的一行。如果A是一個矩陣,那麼
A[i][j]
就表示第i行第j列的元素。
按照數學表達的慣例,我們通常用大寫字母表示矩陣。例:
A = [[1,2,3], # A有2行3列
[4,5,6]]
B = [[1,2], # B有3行2列
[3,4],
[5,6]]
數學中,矩陣的第一行通常稱為"第一行",第一列通常稱為"第一列"。我們需要将矩陣的形式和python的清單統一:python中的清單從0開始索引,是以,我們将矩陣第一行通常稱為"第0行",第一列通常稱為"第0列"。
基于清單的清單這種表達形式,矩陣A具有len(A)和len(A[0])列,這種稱為形狀。
def shape(A):
num_rows = len(A)
num_cols = len(A[0]) if A else 0 #第一行中元素的個數
return num_rows,num_cols
A = [[1,2],
[3,4],
[5,6]]
shape(A)
如果一個矩陣有n行k列,則可以記為n x k矩陣。我們可以把這個n x k矩陣的每一行都當作一個長度為k的向量,把每一列都當作一個長度為n的向量。
def get_row(A,i):
return A[i] # A[i]是第i行
def get_column(A,j):
return [A_i[j] for A_i in A] #每個A_[i]行的第j個元素
get_row(A,2)
[5,6]
get_column(A,1)
[2,4,6]
我們也可以根據形狀和用來生成元素的函數來建立矩陣,這裡舉個建立機關矩陣(對角線元素是1,其他元素是0)的例子:
def entry_fn(i,j):
return 1 if i==j else 0
def make_matrix(num_rows,num_cols,entry_fn):
return [[entry_fn(i,j) for j in range(num_cols)]for i in range(num_rows)]
make_matrix(5,5,entry_fn)
結果如下:
[[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 1, 0],
[0, 0, 0, 0, 1]]
矩陣很重要:
1.通過把每個向量看出是矩陣的一行,矩陣表示一個包含多元向量的資料集。
例如:有10萬人的身高、體重和年齡,就可以建立一個100000 x 3的矩陣,不會在markdown中輸入數學符号,點這裡:
[ 174 62 25 169 65 30 ⋮ ⋮ ⋮ 176 61 29 ] \begin{bmatrix}174&62&25\\169&65&30\\\vdots&\vdots&\vdots\\176&61&29\end{bmatrix} ⎣⎢⎢⎢⎡174169⋮1766265⋮612530⋮29⎦⎥⎥⎥⎤
2.可以用n x k矩陣表示一個線性函數,這個函數将一個k維的向量映射到一個n維的向量上。
{ Y 1 = β 1 X 11 + β 2 X 21 + β 3 X 31 + ⋯ + β k X k 1 Y 2 = β 1 X 12 + β 2 X 22 + β 3 X 32 + ⋯ + β k X k 2 ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ Y n = β 1 X 1 n + β 2 X 2 n + β 3 X 3 n + ⋯ + β k X k n \begin{cases}Y_1=\beta_1X_{11}+\beta_2X_{21}+\beta_3X_{31}+\cdots+\beta_kX_{k1}\\Y_2=\beta_1X_{12}+\beta_2X_{22}+\beta_3X_{32}+\cdots+\beta_kX_{k2}\\\cdots\cdots\cdots\cdots\cdots\cdots\cdots\cdots\cdots\cdots\cdots\cdots\cdots\cdots\\Y_n=\beta_1X_{1n}+\beta_2X_{2n}+\beta_3X_{3n}+\cdots+\beta_kX_{kn}\end{cases} ⎩⎪⎪⎪⎨⎪⎪⎪⎧Y1=β1X11+β2X21+β3X31+⋯+βkXk1Y2=β1X12+β2X22+β3X32+⋯+βkXk2⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯Yn=β1X1n+β2X2n+β3X3n+⋯+βkXkn
用矩陣表示為:
[ Y 1 Y 2 ⋮ Y n ] \begin{bmatrix}Y_1\\Y_2\\\vdots\\Y_n\end{bmatrix} ⎣⎢⎢⎢⎡Y1Y2⋮Yn⎦⎥⎥⎥⎤= [ X 11 X 21 X 31 ⋯ X k 1 X 12 X 22 X 32 ⋯ X k 2 ⋮ ⋮ ⋮ ⋱ ⋮ X 1 n X 2 n X 3 n ⋯ X k n ] \begin{bmatrix}X_{11}&X_{21}&X_{31}&\cdots&X_{k1}\\X_{12}&X_{22}&X_{32}&\cdots&X_{k2}\\\vdots&\vdots&\vdots&\ddots&\vdots\\X_{1n}&X_{2n}&X_{3n}&\cdots&X_{kn}\end{bmatrix} ⎣⎢⎢⎢⎡X11X12⋮X1nX21X22⋮X2nX31X32⋮X3n⋯⋯⋱⋯Xk1Xk2⋮Xkn⎦⎥⎥⎥⎤ [ β 1 β 2 ⋮ β n ] \begin{bmatrix}\beta_1\\\beta_2\\\vdots\\\beta_n\end{bmatrix} ⎣⎢⎢⎢⎡β1β2⋮βn⎦⎥⎥⎥⎤
簡化寫為:
Y = X β \beta β
3.可以用矩陣表示二維關系。
某個社交網站中會員的好友關系就可以用矩陣A來表示,如果會員i和會員j有關系,則用
A[i][j]=1
來表示,若會員i和會員j沒有關系,則用
A[i][j]=0
來表示。
使用者0到使用者9一共10位會員之間的關系:
之間的關系:
#使用者 0 1 2 3 4 5 6 7 8 9
friendships = [[0,1,1,0,0,0,0,0,0,0], #使用者0
[1,0,1,1,0,0,0,0,0,0], #使用者1
[1,1,0,1,0,0,0,0,0,0], #使用者2
[0,1,1,0,1,0,0,0,0,0], #使用者3
[0,0,0,1,0,1,0,0,0,0], #使用者4
[0,0,0,0,1,0,1,1,0,0], #使用者5
[0,0,0,0,0,1,0,0,1,0], #使用者6
[0,0,0,0,0,1,0,0,1,0], #使用者7
[0,0,0,0,0,0,1,1,0,1], #使用者8
[0,0,0,0,0,0,0,0,1,0]] #使用者9
通過矩陣形式再現:
[ 0 1 1 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 1 0 ] \begin{bmatrix}0&1&1&0&0&0&0&0&0&0\\1&0&1&1&0&0&0&0&0&0\\1&1&0&1&0&0&0&0&0&0\\0&1&1&0&1&0&0&0&0&0\\0&0&0&1&0&1&0&0&0&0\\0&0&0&0&1&0&1&1&0&0\\0&0&0&0&0&1&0&0&1&0\\0&0&0&0&0&1&0&0&1&0\\0&0&0&0&0&0&1&1&0&1\\0&0&0&0&0&0&0&0&1&0\\\end{bmatrix} ⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡0110000000101100000011010000000110100000000101000000001011000000010010000001001000000011010000000010⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤
如果關系很少,這種表示形式的效率就會很低,因為必須存儲很多零。但是通過矩陣可以快速地查找确認某2個節點是否連結(有關系),不用周遊每條邊。
friendships[0][2] == 1 #傳回True,使用者0和使用者2是朋友
friendships[0][8] == 1 #傳回False,使用者0和使用者8不是朋友
如果想找到一個使用者的所有朋友即找到一個節點的所有連接配接,隻要檢查這個節點所在的列或者行即可。
舉例,檢視使用者3的所有朋友:
fried_of_three = [i for i,is_friend in enumerate(friendships[3]) if is_friend]
fried_of_three