linearly

Lecture 10

Orthogonality of the Four Subspaces

Row space and null space meet at a right angle, and so does the other pair. Nothing perpendicular is missing, every reachable b comes from exactly one x, and that is where the pseudoinverse comes from.

61 slides / MIT 18.06, Lecture 14 / Strang §4.1

Slide 1 of 61
1 / 61

The idea in one sentence

The four subspaces come in two perpendicular pairs, and each pair covers its whole space with nothing left over, which is why every reachable bb comes from one and only one xx.

The matrix and its four bases

Everything in this chapter happens inside one 3×43 \times 4 matrix, the same one Lecture 9 took apart. Its four bases are already in hand:

A=[122438616410820],r=2.A = \begin{bmatrix} 1 & 2 & 2 & 4 \\ 3 & 8 & 6 & 16 \\ 4 & 10 & 8 & 20 \end{bmatrix}, \qquad r = 2 .

In R4\R^4: the row space C(AT)C(A\T) has basis (1,0,2,0)(1, 0, 2, 0) and (0,1,0,2)(0, 1, 0, 2), and the null space N(A)N(A) has basis s1=(2,0,1,0)s_1 = (-2, 0, 1, 0) and s2=(0,2,0,1)s_2 = (0, -2, 0, 1).

In R3\R^3: the column space C(A)C(A) has basis (1,3,4)(1, 3, 4) and (2,8,10)(2, 8, 10), and the left null space N(AT)N(A\T) has basis (1,1,1)(-1, -1, 1).

Four sets of vectors, four dimensions that add to 4 and to 3. What the last chapter did not say is how they sit relative to each other. That is one line of algebra away.

The proof is one line

Take any xx in the null space. The statement Ax=0Ax = 0 looks like a fact about a matrix. Read it by rows and it is a fact about angles. Each entry of AxAx is a row of AA dotted with xx, so Ax=0Ax = 0 says every one of those dot products is zero:

row1x=0,row2x=0,row3x=0.\text{row}_1 \cdot x = 0, \qquad \text{row}_2 \cdot x = 0, \qquad \text{row}_3 \cdot x = 0 .

A zero dot product means a right angle. So xx is perpendicular to every row of AA. It is then perpendicular to every combination of the rows, because dotting distributes over sums and scalar multiples. The combinations of the rows are the row space. Done:

N(A)C(AT).N(A) \perp C(A\T) .
122438616410820−2010=000As₁1(−2) + 2(0) + 2(1) + 4(0) = 03(−2) + 8(0) + 6(1) + 16(0) = 04(−2) + 10(0) + 8(1) + 20(0) = 0row 1 ⊥ s₁row 2 ⊥ s₁row 3 ⊥ s₁
Fig. 1 

Every entry of AxAx is a row dotted with xx. Orange is the row space, cyan the null space. The single equation Ax=0Ax = 0 is three statements about right angles at once, and any combination of the rows inherits all three.

Now turn the whole argument around by writing ATA\T where AA was. Take any yy in the left null space. Then ATy=0A\T y = 0 says every row of ATA\T, which is to say every column of AA, is perpendicular to yy. So yy is perpendicular to every combination of the columns:

N(AT)C(A).N(A\T) \perp C(A) .

Check it on the numbers. The left null space vector is (1,1,1)(-1, -1, 1), and the two column space basis vectors give 13+4=0-1 - 3 + 4 = 0 and 28+10=0-2 - 8 + 10 = 0. Both zero, both right angles.

Two subspaces are called orthogonal when every vector in one is perpendicular to every vector in the other. That is a strong condition, and it has an immediate consequence. If some vector vv belonged to both, it would have to be perpendicular to itself, so vv=0v \cdot v = 0, so v=0v = 0. Orthogonal subspaces meet at the origin and nowhere else.

The right angle you can draw

Abstract right angles are easy to nod at and hard to feel. Here is one with numbers. Take x=(1,1,1,1)x = (1, 1, 1, 1) and split it into the row space piece and the null space piece from Lecture 9:

xr=(35,35,65,65),xn=(25,25,15,15).x_r = \left(\tfrac{3}{5}, \tfrac{3}{5}, \tfrac{6}{5}, \tfrac{6}{5}\right), \qquad x_n = \left(\tfrac{2}{5}, \tfrac{2}{5}, -\tfrac{1}{5}, -\tfrac{1}{5}\right).

Their dot product is 625+625625625=0\tfrac{6}{25} + \tfrac{6}{25} - \tfrac{6}{25} - \tfrac{6}{25} = 0. So the two pieces of xx sit at a right angle, and the three vectors xrx_r, xnx_n and xx form a right triangle inside R4\R^4. That triangle lives in an ordinary flat plane, so you can draw it exactly, and Pythagoras has to hold:

xr2+xn2  =  3.6+0.4  =  4  =  x2.\norm{x_r}^2 + \norm{x_n}^2 \;=\; 3.6 + 0.4 \;=\; 4 \;=\; \norm{x}^2 .
xᵣxₙxx = (1, 1, 1, 1)xᵣ = (3/5, 3/5, 6/5, 6/5)xₙ = (2/5, 2/5, −1/5, −1/5)‖xᵣ‖² + ‖xₙ‖² = 3.6 + 0.4 = 4 = ‖x‖²
Fig. 2 

The split of a vector into its row space part and its null space part, drawn to scale. Blue is xx, green is the part that survives AA, orange the part that dies. The legs are perpendicular because the row space is perpendicular to the null space, so the triangle obeys Pythagoras and the numbers close exactly.

Move xx around and the triangle changes shape, but the corner at the origin stays square. Try it.

Try it. Move x and watch the right angle hold
xᵣxₙx

xᵣ = (0.60, 0.60, 1.20, 1.20)
xₙ = (0.40, 0.40, −0.20, −0.20)
xᵣ dot xₙ = 0.00
Ax = (9, 33, 42)
Axᵣ = (9, 33, 42)

The drawing rescales to fit, so watch the shape and not the size. The corner at the origin never opens, and the last two lines never disagree.

Nothing perpendicular is missing

Perpendicular is less than it sounds. In R3\R^3 the xx axis and the yy axis are perpendicular, yet together they reach only a plane. Everything in the zz direction is missing. Two subspaces can meet at right angles and still leave most of the space uncovered.

two perpendicular lines1 + 1 = 2, and 2 < 3the dashed direction has nowhere to livea plane and its normal line2 + 1 = 3nothing perpendicular is missingxyzn
Fig. 3 

Orthogonal is not the same as complementary. Orange marks the subspaces being added up, blue the direction that finishes the job. Both pictures show subspaces meeting at a right angle, and only the right one covers R3\R^3. The four subspaces always behave like the right picture, and the dimension count is what proves it.

The four subspaces do better than that. Nothing is left over, and the proof runs both ways in two short steps.

If xx is in N(A)N(A) then Ax=0Ax = 0, so xx is perpendicular to every row, so xx is perpendicular to the row space. That is the direction already proved. Now the other one. Suppose xx is perpendicular to every row of AA. Then every entry of AxAx, being a row dotted with xx, is zero, so Ax=0Ax = 0 and xx is in N(A)N(A).

Put those together and the null space holds every vector perpendicular to the row space, and nothing else. The name for that is the orthogonal complement, and the dimensions are the receipt:

r+(nr)=n,r+(mr)=m.r + (n - r) = n, \qquad r + (m - r) = m .

For our matrix, 2+2=42 + 2 = 4 in R4\R^4 and 2+1=32 + 1 = 3 in R3\R^3. If the null space had come out one dimension short, some direction perpendicular to the row space would have had nowhere to live, and the count would have caught it.

The R3\R^3 side is small enough to draw honestly. The column space is a plane through the origin. The left null space is the single line through (1,1,1)(-1, -1, 1). The plane and the line are perpendicular, and a plane plus its normal line is all of R3\R^3.

N(Aᵀ) = span{(−1, −1, 1)}a line, dim m − r = 1C(A)a plane, dim r = 20every b that A canproduce lies here
Fig. 4 

The output side of the picture, drawn in full. Every direction inside the green plane is a reachable bb. The one direction perpendicular to it is the left null space. A plane and its normal line fill R3\R^3 between them, and 2+1=32 + 1 = 3 says so in numbers.

Every reachable b comes from exactly one x

Here is the payoff.

Take any bb in the column space. Since bb is a combination of columns, there is some xx with Ax=bAx = b. Split it: x=xr+xnx = x_r + x_n, and Axn=0Ax_n = 0, so Axr=bAx_r = b as well. So bb comes from at least one vector in the row space.

Could it come from two? Suppose xrx_r and xrx_r' both sit in the row space and both satisfy Axr=Axr=bAx_r = Ax_r' = b. Then A(xrxr)=0A(x_r - x_r') = 0, so the difference is in the null space. It is also in the row space, since the row space is closed under subtraction. A vector in both spaces is perpendicular to itself, and the only such vector is zero. So xr=xrx_r = x_r'.

every bC(A) comes from one and only one xrC(AT).\text{every } b \in C(A) \text{ comes from one and only one } x_r \in C(A\T).

The matrix may crush a whole two-dimensional null space to zero. Underneath the crushing there is still a perfect one-to-one correspondence between two spaces of dimension rr, and AA restricted to the row space is invertible.

Watch it happen. The vectors x=(1,1,1,1)x = (1, 1, 1, 1) and x=(1,1,2,1)x' = (-1, 1, 2, 1) differ by the null space vector s1s_1, so both give the same output:

Ax=Ax=(9,33,42).Ax = Ax' = (9, 33, 42).

Feed each through the split and both hand back the same row space vector, xr=(35,35,65,65)x_r = \left(\tfrac{3}{5}, \tfrac{3}{5}, \tfrac{6}{5}, \tfrac{6}{5}\right). Two inputs, one output, one row space representative. And that representative is the shortest of all the solutions, since xr1.897\norm{x_r} \approx 1.897 while x=2\norm{x} = 2 and x2.646\norm{x'} \approx 2.646. Pythagoras again: any other solution carries an extra perpendicular leg, and a leg can only make a vector longer.

the row space C(Aᵀ)0xᵣxx′xᵣ + N(A)1.8972Every solution sits on the dashed line. Only its foot lies in the rowspace, and the foot is the closest point of that line to the origin.
Fig. 5 

The full solution set of Ax=bAx = b is the dashed line, which is xrx_r plus the null space. It crosses the row space once, at xrx_r, and it crosses at a right angle. Every other solution is the hypotenuse of a triangle with xrx_r as one leg, so every other solution is longer. The null space here is two-dimensional; only one of its directions fits on a page.

row space C(Aᵀ)column space C(A)null space N(A)left null space N(Aᵀ)A, one to oneA, everything to 00
Fig. 6 

The whole of AA in one picture, in the chapter’s colors. The blue pairings across the top never collide: distinct points of the row space land on distinct points of the column space. Below, an entire two-dimensional null space collapses onto the single point 00.

The four rank cases, seen through the right angle

Lecture 8 sorted every matrix into four cases by comparing the rank rr with the shape mm and nn, and gave a worked example of each. The Big Picture says what those four cases really are: which of the two null spaces has collapsed to a point.

1. square and invertible, r = m = nAx = b: exactly one solutionC(Aᵀ)dim rC(A)dim rN(A) = 0N(Aᵀ) = 02. short and wide, r = m < nAx = b: always solvable, infinitely manyC(Aᵀ)dim rC(A)dim rN(A)dim n − rN(Aᵀ) = 03. tall and thin, r = n < mAx = b: zero or one solutionC(Aᵀ)dim rC(A)dim rN(A) = 0N(Aᵀ)dim m − r4. not full rank, r < m and r < nAx = b: zero or infinitely manyC(Aᵀ)dim rC(A)dim rN(A)dim n − rN(Aᵀ)dim m − r
Fig. 7 

The four cases are four answers to one question: which null space is a single point? The colors are the same four rooms throughout. In every panel the two solid regions on the left and right have the same dimension rr and are linked one to one, which is the part that never changes. A fat null space on the left means many xx for each bb. A fat left null space on the right means some bb are out of reach.

Read the panels off the two null spaces. A null space that is only the zero vector means no two inputs collide, so a solution is unique when it exists. A left null space that is only the zero vector means the column space fills Rm\R^m, so every bb is reachable. Case 1 has both, which is what invertible means. Case 4 has neither, and every unpleasant thing that can happen to a linear system happens there.

The part that survives all four cases is the one-to-one link across the middle. Even in case 4, where AA crushes a null space and misses part of Rm\R^m, the row space and the column space are still perfectly matched.

The pseudoinverse, defined honestly

A matrix with a nonzero null space has no inverse. There is no undoing the crush: once s1s_1 and 00 have both been sent to 00, nothing downstream can tell them apart. That looks like the end of the story. The one-to-one link says otherwise.

Here is what A+A^{+}, the pseudoinverse, does with a vector bb in Rm\R^m.

  1. Split bb into the part inside C(A)C(A) and the part inside N(AT)N(A\T). Those two spaces are complements, so the split exists and is unique.
  2. Throw away the N(AT)N(A\T) part. It was never reachable, so no xx was ever going to produce it.
  3. Undo the one-to-one link on what is left, landing on the single xrx_r in the row space with AxrA x_r equal to the kept part.

In one line: invert the part that is invertible and ignore the null spaces. Every property of A+A^{+} follows from those three steps. A+AA^{+}A is the projection onto the row space, because it sends xx to xrx_r. AA+AA^{+} is the projection onto the column space, because it sends bb to its reachable part. And AA+A=AAA^{+}A = A, since AA ignores the discarded pieces anyway.

row space C(Aᵀ)column space C(A)null space N(A)left null space N(Aᵀ)AA⁺A⁺ never lands hereA⁺ throws this part awayxᵣ = A⁺bbA⁺(9, 33, 42) = (3/5, 3/5, 6/5, 6/5)
Fig. 8 

The pseudoinverse is the return trip along the one-to-one link: blue out, green back. It reaches only the row space, and it listens only to the column space. The two faded rooms are exactly the information AA destroyed, and no inverse of any kind can bring them back.

On the running matrix, numpy.linalg.pinv reproduces all of this exactly. Feeding it b=(9,33,42)b = (9, 33, 42) returns (35,35,65,65)\left(\tfrac{3}{5}, \tfrac{3}{5}, \tfrac{6}{5}, \tfrac{6}{5}\right), the row space representative. Feed it the unreachable b=(8,32,43)b' = (8, 32, 43), which is bb plus the left null space vector, and it returns the same answer, because step 2 discarded the difference.

python
import numpy as np
np.set_printoptions(precision=4, suppress=True)

A = np.array([[1., 2., 2., 4.], [3., 8., 6., 16.], [4., 10., 8., 20.]])
row = np.array([[1., 0., 2., 0.], [0., 1., 0., 2.]])     # row space basis
nul = np.array([[-2., 0., 1., 0.], [0., -2., 0., 1.]])   # null space basis
lnul = np.array([[-1., -1., 1.]])                        # left null basis

print(row @ nul.T)          # [[0. 0.] [0. 0.]]   every pair perpendicular
print(A[:, :2].T @ lnul.T)  # [[0.] [0.]]         and on the other side too

x = np.array([1., 1., 1., 1.])
xr = (x @ row[0]) / 5 * row[0] + (x @ row[1]) / 5 * row[1]
xn = x - xr
print(xr, xn)               # [0.6 0.6 1.2 1.2] [ 0.4  0.4 -0.2 -0.2]
print(xr @ xn)              # 1.1102230246251565e-16   zero, in floating point
print(np.array([xr @ xr, xn @ xn, x @ x]))     # [3.6 0.4 4. ]  Pythagoras
print(A @ x, A @ xr, A @ xn)  # [ 9. 33. 42.] [ 9. 33. 42.] [0. 0. 0.]

The second block is the pseudoinverse doing the three steps.

python
import numpy as np
np.set_printoptions(precision=4, suppress=True)

A = np.array([[1., 2., 2., 4.], [3., 8., 6., 16.], [4., 10., 8., 20.]])
Aplus = np.linalg.pinv(A)

b = np.array([9., 33., 42.])          # reachable: b is in C(A)
print(Aplus @ b)                      # [0.6 0.6 1.2 1.2]   the row space x
print(A @ (Aplus @ b))                # [ 9. 33. 42.]       reached exactly

x = np.array([1., 1., 1., 1.])
s1 = np.array([-2., 0., 1., 0.])
print(Aplus @ A @ x)                  # [0.6 0.6 1.2 1.2]   x projected onto the row space
print(Aplus @ A @ s1)                 # [0. 0. 0. 0.]       the null part dies

b_off = np.array([8., 32., 43.])      # b plus the left null space vector
print(Aplus @ b_off)                  # [0.6 0.6 1.2 1.2]   same answer
print(A @ (Aplus @ b_off) - b_off)    # [ 1.  1. -1.]  the part it threw away
print(np.allclose(A @ Aplus @ A, A))  # True

Where this is going

Two things in this chapter were used before they were earned. The split x=xr+xnx = x_r + x_n was described as though computing it were easy, and step 1 of the pseudoinverse asked for the part of bb that lies inside the column space. Both are the same operation: dropping a vector perpendicularly onto a subspace. That operation is called projection, it has a short formula, and it is the next chapter. Once you can project, the whole of least squares is one substitution away, and least squares is how every linear model in machine learning gets fitted.