SigmaField
Mathematical Foundations for Quant Finance
0 of 256 lessons
      1. 3.8.1 The singular value decompositionConcept · 35 min
      2. 3.8.2 Low-rank approximationConcept · 25 min
      3. 3.8.3 Practice set: the singular value decompositionPractice set · 20 min
      4. 3.8.4 Case study: compressing a factor modelCase study · 35 min

Level 3, Linear algebra 3.8 Singular value decomposition (optional) Lesson 2 of 4

ConceptLesson 3.8.2 in Level 3, Linear algebra. About 25 minutes.

Low-rank approximation

Keep the biggest pieces

Lesson 3.8.1 wrote every matrix as a sum of rank-one pieces, largest first:

A=σ1u1v1⊤+σ2u2v2⊤+⋯+σrurvr⊤\begin{gathered} A = \sigma_1\mathbf{u}_1\mathbf{v}_1^\top + \sigma_2\mathbf{u}_2\mathbf{v}_2^\top \\ + \cdots + \sigma_r\mathbf{u}_r\mathbf{v}_r^\top \end{gathered}

Here σ1≥σ2≥⋯\sigma_1 \ge \sigma_2 \ge \cdots are the singular values, ui\mathbf{u}_i and vi\mathbf{v}_i the left and right singular vectors, and rr the rank. Keep only the first kk pieces and you get a matrix of rank kk that is close to AA.

Rule: The rank-k copy

Ak=σ1u1v1⊤+⋯+σkukvk⊤=UkSkVk⊤\begin{gathered} A_k = \sigma_1\mathbf{u}_1\mathbf{v}_1^\top + \cdots + \sigma_k\mathbf{u}_k\mathbf{v}_k^\top \\[4pt] = U_k S_k V_k^\top \end{gathered}

UkU_k holds the first kk columns of UU, SkS_k the first kk singular values, and Vk⊤V_k^\top the first kk rows of V⊤V^\top. When σk>0\sigma_k > 0, AkA_k has rank kk.

Lesson 3.8.1's tall matrix has two pieces:

B=(201102)B1=(111111)B−B1=(1−100−11)\begin{gathered} B = \begin{pmatrix} 2 & 0 \\ 1 & 1 \\ 0 & 2 \end{pmatrix} \\[6pt] B_1 = \begin{pmatrix} 1 & 1 \\ 1 & 1 \\ 1 & 1 \end{pmatrix} \\[6pt] B - B_1 = \begin{pmatrix} 1 & -1 \\ 0 & 0 \\ -1 & 1 \end{pmatrix} \end{gathered}

B1=6 u1v1⊤B_1 = \sqrt 6\,\mathbf{u}_1\mathbf{v}_1^\top is the first piece, and the error B−B1B - B_1 is the piece left out, 2u2v2⊤2\mathbf{u}_2\mathbf{v}_2^\top. To say how good B1B_1 is, we need a way to measure the size of a matrix.

The size of a matrix

The Frobenius norm. Read the entries of AA as one long vector and take its length (lesson 3.1.2): the square root of the sum of the squares of all the entries. It is written ∥A∥F\lVert A \rVert_F.

For BB the squares are 4,0,1,1,0,44, 0, 1, 1, 0, 4, which add up to 10, so ∥B∥F=10≈3.1623\lVert B \rVert_F = \sqrt{10} \approx 3.1623. That is also σ12+σ22=6+4\sqrt{\sigma_1^2 + \sigma_2^2} = \sqrt{6 + 4}. The turns UU and V⊤V^\top keep lengths, so only the stretches in SS count.

The 2-norm. The largest stretch: the longest ∥Ax∥\lVert A\mathbf{x} \rVert for a unit vector x\mathbf{x}, written ∥A∥2\lVert A \rVert_2. Lesson 3.8.1 found it is the longest semi-axis of the ellipse, σ1\sigma_1. For BB it is 6≈2.4495\sqrt 6 \approx 2.4495.

Rule: Two sizes of a matrix

∥A∥F=∑i,jaij2=σ12+⋯+σr2∥A∥2=max⁡∥x∥=1∥Ax∥=σ1\begin{gathered} \lVert A \rVert_F = \sqrt{\textstyle\sum_{i,j} a_{ij}^2} \\ = \sqrt{\sigma_1^2 + \cdots + \sigma_r^2} \\[4pt] \lVert A \rVert_2 = \max_{\lVert \mathbf{x} \rVert = 1} \lVert A\mathbf{x} \rVert = \sigma_1 \end{gathered}

Both are in the units of the entries, and both are 0 only for the zero matrix. The Frobenius norm counts every entry; the 2-norm only the worst direction, so ∥A∥2≤∥A∥F\lVert A \rVert_2 \le \lVert A \rVert_F.

Try it

np.linalg.norm(B) is the Frobenius norm; np.linalg.norm(B, 2) is the 2-norm. The first line prints both, then σ12+σ22\sqrt{\sigma_1^2 + \sigma_2^2} from the singular values.

The next lines build B1B_1 from the first piece and measure the error both ways.

⌘/Ctrl + Enter runs the cell

The best copy, and its error

No matrix of rank kk is closer to AA than AkA_k, in either norm. This result is the Eckart–Young theorem, stated here without proof. The error is made of the pieces left out, so its size comes straight from the singular values.

Rule: The error of the rank-k copy

∥A−Ak∥2=σk+1∥A−Ak∥F=σk+12+⋯+σr2\begin{gathered} \lVert A - A_k \rVert_2 = \sigma_{k+1} \\[4pt] \lVert A - A_k \rVert_F = \sqrt{\sigma_{k+1}^2 + \cdots + \sigma_r^2} \end{gathered}

In the 2-norm the error is the first singular value left out. In the Frobenius norm it is the root of the sum of the squares of all those left out. For k≥rk \ge r there is nothing left out and Ak=AA_k = A.

For B1B_1 only σ2=2\sigma_2 = 2 is left out, so both errors are 2. The cell above agrees: the four entries ±1\pm 1 of B−B1B - B_1 give 4=2\sqrt 4 = 2.

Other rank-1 copies do worse. Keeping only the first column of BB, (201000)\begin{pmatrix} 2 & 0 \\ 1 & 0 \\ 0 & 0 \end{pmatrix}, leaves an error of 5≈2.2361\sqrt 5 \approx 2.2361. Even 1.11.1 times the table of ones, a small change to B1B_1, leaves 2.0149.

The share kept

The squared Frobenius norm splits exactly between the copy and the error, like the two sides of a right angle: ∥A∥F2=∥Ak∥F2+∥A−Ak∥F2\lVert A \rVert_F^2 = \lVert A_k \rVert_F^2 + \lVert A - A_k \rVert_F^2. For BB, 10=6+410 = 6 + 4. So the copy keeps a share of the squared size.

Rule: Share kept by the rank-k copy

share=∥Ak∥F2∥A∥F2=σ12+⋯+σk2σ12+⋯+σr2\begin{gathered} \text{share} = \frac{\lVert A_k \rVert_F^2}{\lVert A \rVert_F^2} \\[4pt] = \frac{\sigma_1^2 + \cdots + \sigma_k^2}{\sigma_1^2 + \cdots + \sigma_r^2} \end{gathered}

A number between 0 and 1, often quoted in percent. The share left out is 1 minus it, and the error relative to the size, ∥A−Ak∥F/∥A∥F\lVert A - A_k \rVert_F / \lVert A \rVert_F, is the square root of the share left out.

B1B_1 keeps 6/10=60%6/10 = 60\% of the squared size of BB. Its relative error is 0.4≈0.6325\sqrt{0.4} \approx 0.6325, which is 2/102 / \sqrt{10}.

Try it

The two other rank-1 copies and their errors, then the split 10=6+410 = 6 + 4 and the share kept by B1B_1.

⌘/Ctrl + Enter runs the cell

A larger example: choosing k

Here is a 5×45 \times 4 matrix of whole numbers. Its rows run from falling, (6,4,2,1)(6, 4, 2, 1), through flat to rising, (0,1,2,5)(0, 1, 2, 5):

M=(64214321222211240125)M = \begin{pmatrix} 6 & 4 & 2 & 1 \\ 4 & 3 & 2 & 1 \\ 2 & 2 & 2 & 2 \\ 1 & 1 & 2 & 4 \\ 0 & 1 & 2 & 5 \end{pmatrix}

Its singular values are 10.876, 6.016, 0.649 and 0.320, and the squares of its entries add up to 155. The squares of the singular values add up to 155 too: 118.28, 36.19, 0.42 and 0.10.

The singular values of MM drop sharply after the second. The rank-2 copy already keeps 99.66% of the squared size; the last two pieces add only 0.34%.

kk01234
share kept0%76.31%99.66%99.93%100%
∥M−Mk∥2\lVert M - M_k \rVert_210.87586.01620.64880.31950
∥M−Mk∥F\lVert M - M_k \rVert_F12.44996.05950.72320.31950

The rank-2 copy M2M_2 differs from MM by at most 0.34 in any entry. Its first row, for example, is (5.87,4.07,2.27,0.87)(5.87, 4.07, 2.27, 0.87) against (6,4,2,1)(6, 4, 2, 1).

The two pieces it keeps have a meaning: v1≈(0.63,0.50,0.40,0.44)\mathbf{v}_1 \approx (0.63, 0.50, 0.40, 0.44) has every entry positive, a common level. v2≈(−0.52,−0.21,0.18,0.81)\mathbf{v}_2 \approx (-0.52, -0.21, 0.18, 0.81) runs from negative to positive: a tilt from the first column to the last. Each row of MM is close to some amount of the level plus some amount of the tilt.

How to choose k

  • A target share. Pick the smallest kk whose share reaches a target, such as 90% or 99%. Here 90% needs k=2k = 2, and so does 99%.
  • A gap. Look for a sharp drop in the singular values. From 6.016 to 0.649 is a fall by a factor of more than 9, so k=2k = 2.
  • What the small pieces are. If the entries carry measurement or rounding errors, the smallest pieces are often just those errors. Dropping them can make the copy closer to the truth, not further from it.

The choice is a judgement, and the error rules say what it costs. With k=2k = 2 the worst direction is off by σ3=0.6488\sigma_3 = 0.6488.

Try it

The loop builds MkM_k for each kk as (U[:, :k] * s[:k]) @ Vt[:k]: the first kk columns, values and rows. It prints the share kept and both errors, which match the rules; then the gap σ2/σ3\sigma_2/\sigma_3, and σ1/∑σi\sigma_1 / \sum \sigma_i in percent, a wrong share (see the common mistakes).

Then M2M_2 to two decimals and its largest entry error. The signs of the vi\mathbf{v}_i are fixed so their last entries are positive.

⌘/Ctrl + Enter runs the cell

Storage

A rank-kk copy of an m×nm \times n matrix is stored as UkU_k, SkS_k and Vk⊤V_k^\top: k(m+n+1)k(m + n + 1) numbers instead of mnmn.

For MM that is no saving: 2×(5+4+1)=202 \times (5 + 4 + 1) = 20, the same as its 20 entries. The saving comes with size. A 1,000×5001{,}000 \times 500 matrix holds 500,000 numbers, and a rank-10 copy needs 15,010, about 3%.

Try it

The counts for MM and for the large matrix, and the large copy's share of the full storage.

⌘/Ctrl + Enter runs the cell

Cases to know

  • k=0k = 0 keeps nothing: A0A_0 is the zero matrix and the error is all of AA.
  • kk equal to the rank keeps everything. The table (123246369)\begin{pmatrix} 1 & 2 & 3 \\ 2 & 4 & 6 \\ 3 & 6 & 9 \end{pmatrix} has singular values 14, 0 and 0, so A1A_1 is the table itself, stored as 7 numbers instead of 9.
  • Ties. If σk=σk+1\sigma_k = \sigma_{k+1}, the best copy is not unique. The identity I2I_2 has singular values 1 and 1, and every direction gives an equally good rank-1 copy.
  • Scaling. Multiplying AA by cc multiplies every singular value by ∣c∣\lvert c \rvert. The errors scale too, but the shares do not change: −3M-3M keeps 76.31% at k=1k = 1, like MM.

Case study 3.8.4 uses this to compress a table of asset returns into a few factors.

Try it

The rank-1 table: its singular values (adding 0.0 turns a -0. into 0.), and its rank-1 copy, which is the table. Then the tie for I2I_2, and the shares of −3M-3M.

⌘/Ctrl + Enter runs the cell

Common mistakes

  1. Shares use squares. The share kept is ∑σi2\sum \sigma_i^2 over the top kk against the total. For MM, σ1/∑σi\sigma_1 / \sum \sigma_i is 60.89%, but the true share is 76.31%.
  2. The 2-norm error is the first value left out, σk+1\sigma_{k+1}, not the last one kept, σk\sigma_k.
  3. The Frobenius error is a root of a sum of squares, not the sum of the singular values left out.
  4. Keep matching parts. Take the first kk columns of UU, the first kk singular values and the first kk rows of V⊤V^\top.
  5. Low rank is not small entries. Setting the smallest entries of AA to 0, or dropping a row or column, does not give the best copy: keeping BB's first column leaves 2.2361 against 2.
  6. Small matrices save nothing. k(m+n+1)k(m + n + 1) can equal or pass mnmn.

Low-rank approximation

0 of 12 correct

  1. 1.
  2. 2.
  3. 3.
  4. 4.
  5. 5.
  6. 6.
  7. 7.
  8. 8.
  9. 9.
  10. 10.
  11. 11.
  12. 12.
How to type answers
  • Powers with ^: x^7, 2^(1/3), a^-2.
  • Multiply with * or by writing side by side: 3x^2, 2(x+1).
  • ln(x) is the natural log, log(x, 2) is log base 2, e is Euler's number, sqrt(x) is a square root.
  • sin(x), cos(x) and tan(x) take radians; write pi for π and sin(x)^2 for sin²x.
  • Your first answer to each question is saved: it counts towards your score and brings the question back for review.
  • Exact answers like ln(20)/ln(3) are best. Decimals need about 4 significant figures.

Summary card

  • The rank-kk copy keeps the first kk pieces: Ak=∑i≤kσiuivi⊤=UkSkVk⊤A_k = \sum_{i \le k} \sigma_i\mathbf{u}_i\mathbf{v}_i^\top = U_kS_kV_k^\top.
  • Sizes: ∥A∥F=∑aij2=∑σi2\lVert A \rVert_F = \sqrt{\sum a_{ij}^2} = \sqrt{\sum \sigma_i^2} counts every entry; ∥A∥2=σ1\lVert A \rVert_2 = \sigma_1 is the largest stretch.
  • AkA_k is the best copy of rank kk (Eckart–Young): ∥A−Ak∥2=σk+1\lVert A - A_k \rVert_2 = \sigma_{k+1} and ∥A−Ak∥F=σk+12+⋯+σr2\lVert A - A_k \rVert_F = \sqrt{\sigma_{k+1}^2 + \cdots + \sigma_r^2}.
  • It keeps the share ∑i≤kσi2/∑iσi2\sum_{i \le k}\sigma_i^2 / \sum_i \sigma_i^2 of the squared size. Choose kk by a target share, a gap in the singular values, or the size of the errors in the data.
  • Storage: k(m+n+1)k(m + n + 1) numbers instead of mnmn, a saving only for large matrices and small kk.

Free further reading

Optional. This lesson covers what you need; these add more examples and practice. All are free to read.