牛客题解 | 奇异值分解 (SVD)

题目

题目链接

奇异值分解是一种将矩阵分解为三个矩阵的方法,它通过将矩阵分解为三个矩阵,来得到矩阵的奇异值和奇异向量。其数学表达式为:

\[A = U \times \Sigma \times V^T \]

其中,\(A\) 是输入矩阵,\(U\) 是左奇异向量,\(\Sigma\) 是奇异值,\(V^T\) 是右奇异向量。
通过\(\Sigma\)的维度选择,可以实现矩阵的降维。

Jacobi方法是一种计算奇异值分解的方法,常用于小矩阵,其具体步骤如下:

1. 初始化矩阵

  • 创建一个与输入矩阵 \(A\) 相关的矩阵 \(a\)\(a_2\)
  • 数学表达式为:

\[a = A \]

\[a_2 = a^T \times a \]

2. 计算旋转角度

  • 计算旋转角度 \(\theta\)
  • 数学表达式为:

\[\theta = \frac{\pi}{4} \]

更一般地说,Jacobi方法的计算公式为:

\[\theta = \frac{1}{2} \arctan\left(\frac{2a_{12}}{a_{11} - a_{22}}\right) \]

3. 计算旋转矩阵

  • 计算旋转矩阵 \(r\)
  • 数学表达式为:

\[r = \begin{bmatrix} \cos(\theta) & -\sin(\theta) \\ \sin(\theta) & \cos(\theta) \end{bmatrix} \]

4. 计算旋转后的矩阵

  • 计算旋转后的矩阵 \(d\)
  • 数学表达式为:

\[d = r^T \times a \times r \]

5. 更新矩阵

  • 更新矩阵 \(a_2\)
  • 数学表达式为:

\[a_2 = d \]

6. 计算奇异值

  • 计算奇异值 \(s\)
  • 数学表达式为:

\[s = \sqrt{[d[0,0], d[1,1]]} \]

7. 计算右奇异向量矩阵 \(V\)

  • 数学表达式为:

\[V = r \]

8. 计算奇异值矩阵 \(S\)

  • 数学表达式为:

\[S = \text{diag}(s) \]

9. 计算左奇异向量矩阵

  • 计算左奇异向量矩阵 \(U\)
  • 数学表达式为:

\[U = a \times v \times \text{inv}(S) \]

标准代码如下

def svd_2x2_singular_values(A):
   a = A
   a_t = np.transpose(a)
   a_2 = a_t @ a
   v = np.eye(2)
   for _ in range(1):
       if a_2[0,0] == a_2[1,1]:
           theta = np.pi/4
       else:
           theta = 0.5 * np.arctan2(2 * a_2[0,1], a_2[0,0] - a_2[1,1])
       r = np.array(
           [
               [np.cos(theta), -np.sin(theta)],
               [np.sin(theta), np.cos(theta)]
               ]
           )
       d = np.transpose(r) @ a_2 @ r
       a_2 = d
       v = v @ r
   s = np.sqrt([d[0,0], d[1,1]])
   s_inv = np.array([[1/s[0], 0], [0, 1/s[1]]])
   
   u = a @ v @ s_inv
   return (u, s, v.T)
posted @ 2025-03-12 12:50  wangxiaoxiao  阅读(40)  评论(0)    收藏  举报