# 线性代数的应用场景

## 机器学习与线性代数

### 代数的运算律

A B ≠ B A e x p : ( 2 x 3 ) × ( 3 x 2 ) = ( 2 x 2 ) b u t ( 3 x 2 ) × ( 2 x 3 ) = ( 3 x 3 ) AB \neq BA \qquad exp: (2x3)\times (3x2) = (2x2) \quad but \quad (3x2)\times (2x3) = (3x3)

( A B ) T = B T A T (AB)^T = B^TA^T

### 迹

T r ( A ) = ∑ i A i , i Tr(A) = \sum_iA_{i,i}

T r ( A B ) = T r ( B A ) Tr(AB) = Tr(BA)

### 范数

∣ ∣ x ∣ ∣ p = ( ∑ i ∣ x i ∣ p ) 1 p ||x||_p = (\sum_i|x_i|^p)^{\frac{1}{p}}

### 矩阵逆

A − 1 A = I A^{-1}A = I

### 特征值分解

B = P − 1 A P B = P^{-1}AP

d i a g ( A ) = { λ 1 , . . . , λ n } diag(A) = \{\lambda_1,...,\lambda_n\}
P T P = I P^TP = I

B = λ 1 p 1 p n T + . . . + λ n p n p n T B = \lambda_1 p_1p_n^T+...+\lambda_np_np_n^T

### SVD分解

M = A T A M = A^TA 为对称正定矩阵，因为
( A T A ) T = A T ( A T ) T = A T A (A^TA)^T = A^T(A^T)^T = A^TA
x T A T A x = ( x T A T ) ( A x ) = ( A x ) T ( A x ) ≥ 0 x^TA^TAx = (x^TA^T)(Ax) = (Ax)^T(Ax) \ge 0

( A T A ) n x n = U T D U (A^TA)_{nxn} = U^TDU
( A A T ) m x m = V T D V (AA^T)_{mxm} = V^TDV

A m x n = V m x m T d i a g ( { λ 1 1 2 , . . . λ n 1 2 } ) U n x n T A_{mxn}=V^T_{mxm}diag(\{\lambda_1^{\frac{1}{2}},...\lambda_n^{\frac{1}{2}}\})U^T_{nxn}
A m x n = λ 1 1 2 v 1 u 1 T + . . . + λ n 1 2 v n u n T A_{mxn}=\lambda_1^{\frac{1}{2}}v_1u_1^T+...+\lambda_n^{\frac{1}{2}}v_nu_n^T

SVD分解和特征值分解都常被用作矩阵的压缩保存，我们可以不保存所有特征向量，只保存一部分特征向量来重构原矩阵。

### 应用1:线性回归

L = ( A x − y ) T ( A x − y ) L = (Ax-y)^T(Ax-y)
∂ L ∂ x = 2 A T ( A x − y ) = 0 \frac{\partial L}{\partial x} = 2A^T(Ax-y)=0

x = ( A T A ) − 1 A T y x = (A^TA)^{-1}A^Ty

x = l i m α → 0 ( A T A + α I ) − 1 A T y x = lim_{\alpha \rightarrow 0}(A^TA+\alpha I)^{-1}A^Ty

### 实例:小车初速度与加速度测定

s = s 0 + v 0 t + a t 2 s = s_0+v_0 t+a t^2

import numpy as np

# 小车斜面下落实验, 加速度为4.9, 初速度2, 初始路程1
t = np.linspace(0, 5, 20)
s = 1 + 2*t + 4.9*t**2
# 加一些噪声,可以理解为实验中的测量误差
s += np.random.randn(*s.shape)*0.01

# 构造数据的三元矩阵
A = np.concatenate([np.ones(t.shape).reshape(1,-1),
t.reshape(1,-1),
(t**2).reshape(1,-1)]).T
# 计算线性回归的权值向量x
x = np.linalg.pinv(A).dot(s)
print("Displacement: %.4f"%(x[0]))
print("Initial velocity: %.4f"%(x[1]))
print("Acceleration: %.4f"%(x[2]))

Displacement: 0.9971
Initial velocity: 1.9972
Acceleration: 4.9009


### 应用2:主成分分析(PCA)

E ( W ) = ∑ i n ∣ ∣ x i W − μ ∣ ∣ 2 2 = ∑ i n ∣ ∣ x i W ∣ ∣ 2 2 E(W) = \sum_i^n||x_iW-\mu||_2^2= \sum_i^n||x_iW||_2^2

E ( W ) = t r [ ( X W ) ( X W ) T ] E(W) = tr[(XW)(XW)^T]

L ( W ) = E ( W ) + λ t r ( W T W − I ) = t r [ ( X W ) ( X W ) T ] − λ t r ( W T W − I ) L(W) = E(W)+\lambda tr(W^TW-I) = tr[(XW)(XW)^T] -\lambda tr(W^TW-I)
∂ L ∂ W = 2 X T ( X W ) − 2 λ W = 0 → X T X W = λ W \frac{\partial L}{\partial W} = 2X^T(XW)-2\lambda W = 0 \rightarrow X^TXW = \lambda W

E ( W ) = t r [ ( X W ) T ( X W ) ] = t r [ W T X T X W ] = t r [ W T λ W ] = t r [ λ W T W ] = t r [ λ I ] = ∏ i d λ i E(W) = tr[(XW)^T(XW)] = tr[W^TX^TXW] = tr[W^T\lambda W]=tr[\lambda W^TW]=tr[\lambda I] = \prod_i^d \lambda_i

### 实例:数据可视化

def PCA(X, dim):
'''
X, size(n,m), n个m维的数据点构成的数据集矩阵
dim, 目标降维维度, dim<m
'''
# 归一化处理
means = np.mean(X,axis = 0)
X = X.copy()-means
# 计算要特征值分解的协方差矩阵
Covs = X.T.dot(X)
# 特征值分解
lamda,V = np.linalg.eigh(Covs)
index = np.argsort(-lamda)[:dim]
W = V[:,index]
return X.dot(W)

# 导入数据集
from sklearn import datasets

X_2dim = PCA(X, 2)
import matplotlib.pyplot as plt
import matplotlib
plt.figure(figsize=(8,6))
ec_list = ['b' if n==0 else 'r' for n in y]
plt.scatter(X_2dim[:,0],X_2dim[:,1],c = 'w', edgecolor = ec_list)
plt.show()


### 应用3:PageRank

page rank是google在世纪初使用的搜索引擎技术, 它是一种结合了线性代数, 图论和数值计算的高效机器学习算法. 但究其原理其实并不复杂, 我们先构思一个图模型, 它的每个顶点是一个独立的网页. 这些网页之间被超链接互联, 从而让这个图模型是一个有向图. 这时我们就能给出一个假设, 网络中的用户流在顶点V时, 有等概率流向它的所有其他子顶点. 这样的假设建立了网页间的影响力关系线性方程组, 举个例子, 下面的网页图模型.

1. 初始化x为一个 ∣ ∣ x ∣ ∣ 1 = 1 ||x||_1 = 1 的向量
2. 迭代计算 x ← M x x\leftarrow Mx
3. x不再变化时, 停止迭代

这是不动点迭代的思想, 因为M的每一列的所有元素和为1, 迭代计算可以保证 ∣ ∣ x ∣ ∣ 1 = 1 ||x||_1 = 1 始终成立, 而这样的迭代计算会让x向真正的解不断靠近直至收敛. 这个迭代次数一般不会太多, 所以这种解法能适用于有一定特殊性的本问题, 而且效率比RREF的方法高效得多

1. 等级泄露（Rank Leak）：如果一个网页没有出链，就像是一个黑洞一样，吸收了其他网页的影响力而不释放，最终会导致其他网页的 PR 值为 0。
2. 等级沉没（Rank Sink）：如果一个网页只有出链，没有入链（如下图所示），计算的过程迭代下来，会导致这个网页的 PR 值为 0

为此我们可以引入一个合理的另一个假设, 我们假设在浏览网页时, 用户不会老老实实跟着超链接走下去, 很有可能看到一半感觉无聊了, 就随机跳到了一个另外的界面. 也就是, 我们引入这样的随机浏览因素, 把原来的M矩阵写成新的PR矩阵
P R = ( 1 − d ) M + d O n e s n PR = (1-d)M+d \frac{Ones}{n}
这样的变化会让我们的计算收敛到一个有意义的解, 避免了无效解的产生

### 实例: 网页推荐

hyperlinks = [
(3, 0),
(3, 1),
(4, 3),
(4, 1),
(1, 2),
(2, 1),
(5, 1),
(4, 5),
(5, 4),
(6, 1),
(6, 4),
(7, 1),
(7, 4),
(8, 1),
(8, 4),
(9, 4),
(10, 4)
]
n = 11
M = np.zeros((n,n))
for i in range(n):
if np.sum(M[:,i])>0:
M[:,i] /= np.sum(M[:,i])

d = 0.175
PR = (1-d)*M + d*np.ones((n,n))/n
x = np.ones((n,1))/n
for iter in range(50):
x = PR.dot(x)
x /= np.sum(x)

x = x[:,0]
x *= 100
sorted_indices = np.argsort(-x)

for i in sorted_indices:
name = chr(ord('A')+i)
print("Page "+name+": Score: %5.3f"%(x[i]))

Page B: Score: 38.322
Page C: Score: 34.143
Page E: Score: 8.163
Page D: Score: 3.943
Page F: Score: 3.943
Page A: Score: 3.308
Page G: Score: 1.636
Page H: Score: 1.636
Page I: Score: 1.636
Page J: Score: 1.636
Page K: Score: 1.636


06-27

01-22 1016
08-04 1171
12-05 1万+
01-06 4593
12-19 5919
05-20 2687
12-14 842
04-19 1万+
03-05 569
11-27