Vector decomposition and subspaces: what a matrix reads and erases

One of the most useful ways to view a vector is as a combination of component vectors. This perspective helps us understand matrix transformations. Instead of asking only what a matrix does to the whole input vector, we can ask what it does to each component. Because the transformation is linear, the transformed components add up to the same output as transforming the whole vector. Some components may strongly affect the output, some may be weakened or redirected, and some may be ignored completely.

For neural networks, this perspective is especially useful because activation vectors often contain many kinds of information at once. A particular weight matrix does not necessarily use all of that information. Understanding a transformation therefore becomes partly a question of identifying which directions in the activation space matter to the matrix and which do not.

One exact way to make this distinction is through the row space and null space of a matrix. They split the input space into directions that can influence the output and directions that the matrix completely erases. This explains how two different activation vectors can produce exactly the same result under the same weight matrix.

In the previous article, we explored how weight matrices transform vectors and why neural networks need nonlinear activations. In this article, we develop the linear algebra needed to look inside those transformations more closely.

We will first look at how vectors can be built from other vectors, why the same vector can be decomposed along different directions, and how linear combinations and dot products help us reason about a transformation. We will then study the four fundamental subspaces of a matrix—its row space, null space, column space, and left null space—and use them to understand which input components determine the output and which the matrix erases. The companion experiment puts this foundation into practice by constructing and testing a projection.

This provides the foundation for future articles, including our MNIST experiment: what a trained classifier reads. There, a hidden layer produces a vector of 128 activation values for each handwritten digit image. We identify 118 independent directions that the trained output layer ignores, remove the corresponding component of the activation vector, and preserve the classifier’s digit scores up to numerical roundoff.

Building a vector from components

A matrix defines a linear transformation from an input space to an output space. Its shape specifies the number of coordinates in those spaces; its entries determine where each input goes. In a neural network, the input space is the space in which activation vectors from the previous layer live. The output space is where the linearly transformed vectors live, before any nonlinear activation is applied.

To understand a matrix’s effect on a vector, we need to look at the vector components that it can be decomposed into. Each component is itself a vector in the input space, and the original vector is their sum. By linearity, the matrix transforms each component separately, and the resulting vectors add up to the same output as transforming the original vector directly. Some components may be stretched, shortened, or sent in a different direction, while others may map to zero and disappear entirely.

A vector has many possible decompositions, using coordinate axes or directions that cross several axes. In mechanistic interpretability and representation analysis, techniques such as PCA/SVD, linear probes, and sparse autoencoders help identify useful directions from data, revealing structure distributed across multiple entries of the activation vector.

Let’s now take a look at how to build a vector from components. Each option in the widget below builds the same blue vector h=(5,3,2)h=(5,3,2) using a linear combination of different component vectors: each colored arrow is a chosen vector scaled by a coefficient, and these component vectors add up to hh. The first option uses the three coordinate basis vectors e1=(1,0,0)e_1=(1,0,0), e2=(0,1,0)e_2=(0,1,0), and e3=(0,0,1)e_3=(0,0,1). Each points along its corresponding coordinate axis and is scaled by the corresponding coordinate of hh.

(5, 3, 2) = 5(1, 0, 0) + 3(0, 1, 0) + 2(0, 0, 1)

h₁h₂h₃h0

Let’s look more closely at the widget’s Coordinate basis option to distinguish a basis vector, its coefficient, and the resulting vector component. The basis vector e1e_1 is a unit vector representing a direction: it has length one. The scalar 55 tells us how much to scale it, and 5e1=(5,0,0)5e_1=(5,0,0) is the actual vector component. The three vector components add up to our input:

h=5e1+3e2+2e3=(5,0,0)+(0,3,0)+(0,0,2)=(5,3,2).h=5e_1+3e_2+2e_3=(5,0,0)+(0,3,0)+(0,0,2)=(5,3,2).

Coordinates such as 55 are often called scalar components. In this article, vector component means the whole scaled vector, such as (5,0,0)(5,0,0).

In a neural network layer, each neuron produces one of these scalar coordinates. The widget’s coefficients 55, 33, and 22 could therefore be the outputs of three neurons for a single input. Each activation scales its corresponding coordinate basis vector, giving a component vector along that axis. Together, these component vectors form the layer’s activation vector h=(5,3,2)h=(5,3,2), as shown below:

Three neuron outputs, h₁ = 5, h₂ = 3, and h₃ = 2, scale the coordinate basis vectors to form (5, 0, 0), (0, 3, 0), and (0, 0, 2). Their sum is the layer activation vector h = (5, 3, 2).

For example, neuron 2 outputs the scalar 33. We represent its contribution to the layer vector as 3e2=(0,3,0)3e_2=(0,3,0). Multiplying by e2e_2 and adding the component vectors is our mathematical description of assembling the coordinates; it does not require an extra layer. The same hh is this layer’s output and the next layer’s input.

The next layer’s weight matrix WW transforms these component vectors, and the results add up to a new vector: Wh=5We1+3We2+2We3Wh=5We_1+3We_2+2We_3. This is the linear part of the next layer’s computation, before adding any bias and applying its activation function.

The neuron outputs provide one way to decompose the layer’s activation vector. Much of representation analysis and mechanistic interpretability seeks a more informative decomposition—directions or subspaces that help explain what the network represents and how it uses that information. Infinitely many decompositions are mathematically possible, so we need criteria and experiments to identify useful ones.

Separating direction from magnitude

Separating direction from magnitude helps us reason about subspaces and transformations. Vectors such as (1,1,1)(1,1,1) and (2,2,2)(2,2,2) span the same line despite having different lengths. Representing their direction with a unit vector lets dot products measure signed projection lengths directly, and lets us examine how a matrix transforms that direction separately from how much of it is present in the input.

To make this separation explicit, we write a vector component as αd\alpha d: dd is a unit vector representing the chosen direction, and α\alpha is a signed scalar specifying how much of it to include. In our example, d=e1d=e_1 and α=5\alpha=5. Since length is never negative, we use the absolute value ∣α∣|\alpha| to express the component’s length. A negative sign in α\alpha means the component points in the opposite direction to dd.

How do we express a component as a scalar times a unit vector when we know only its coordinates? For any nonzero vector vv, calculate its length ∥v∥\|v\| and divide every coordinate by that length. This is normalization:

d=v∥v∥,α=∥v∥,v=αd.d=\frac{v}{\|v\|}, \qquad \alpha=\|v\|, \qquad v=\alpha d.

Choosing dd to point in the same direction as vv makes α\alpha positive. If we instead fix a unit direction first, a component pointing opposite to it has a negative coefficient.

We can demonstrate normalization using a vector already in the widget. One of the vectors in the Other basis set is v=(1,1,1)v=(1,1,1), which points across all three coordinate axes. Initially, its coefficient is 22, so the green component is 2v=(2,2,2)2v=(2,2,2). These vectors have different lengths but the same direction.

To represent their shared direction with a unit vector, we could use L2 normalization. Normalization scales the vector to a total length of 11 while preserving its direction. First, we calculate vv‘s length by squaring its coordinates, adding them, and taking the square root. Then we divide every coordinate by that length. Scaling all coordinates by the same positive amount preserves the direction:

∥v∥=12+12+12=3,d=v∥v∥=13(1,1,1).\|v\|=\sqrt{1^2+1^2+1^2}=\sqrt{3}, \qquad d=\frac{v}{\|v\|}=\frac{1}{\sqrt{3}}(1,1,1).

The resulting vector has length ∥d∥=13+13+13=1\|d\|=\sqrt{\tfrac13+\tfrac13+\tfrac13}=1. We can normalize any nonzero vector this way; the zero vector has no direction and cannot be divided by its length.

Multiplying by the original length reconstructs the basis vector: v=3 d=(1,1,1)v=\sqrt{3}\,d=(1,1,1). The widget’s green component can therefore be written as:

2v=23 d=23(13,13,13)=(2,2,2).2v=2\sqrt{3}\,d =2\sqrt{3}\left(\frac{1}{\sqrt{3}},\frac{1}{\sqrt{3}},\frac{1}{\sqrt{3}}\right) =(2,2,2).

The coefficient is 22 when we scale vv, but 232\sqrt{3} when we scale the unit vector dd. The component itself stays unchanged. Moving the first slider scales that component along the same direction; a negative value reverses it.

From component vectors to subspaces

So far, we’ve chosen coefficients to build a single vector. Keeping the vectors we’re combining fixed, we can vary those coefficients over all real numbers to build an entire set of vectors. This set is their span, and it forms a subspace.

In the widget below, the fixed vectors (4,1,1)(4,1,1) and (1,2,1)(1,2,1) span a plane. The green and pink arrows show their scaled components, and the blue vector is their sum. As you change the coefficients, the blue vector moves within the plane, showing different members of the same subspace. It adds no independent direction because it is built entirely from the two fixed vectors.

1(4, 1, 1) + 1(1, 2, 1) = (5, 3, 2)

xyz(5, 3, 2)0

Try changing the two coefficients, labeled aa and bb, in the widget above. The blue vector moves within the shaded plane. Vectors outside this plane cannot be reached by combining our two fixed vectors, no matter which coefficients we choose. Select Show vector outside the plane to reveal one such example: the orange marker (0,0,3)(0,0,3).

The shaded patch shows part of the span of our two fixed vectors: the infinite plane containing all their possible linear combinations. The widget’s integer sliders show only some of these combinations; allowing aa and bb to take any real values reaches every vector in the plane. Each result has the form:

a(4,1,1)+b(1,2,1)=(4a+b,  a+2b,  a+b)a(4,1,1)+b(1,2,1)=(4a+b,\;a+2b,\;a+b)

More generally, for fixed vectors v1v_1 and v2v_2, we write:

S=span⁡{v1,v2}={av1+bv2:a,b∈R}S=\operatorname{span}\{v_1,v_2\} =\{av_1+bv_2:a,b\in\mathbb R\}

This entire span is a subspace of R3\mathbb R^3, the surrounding three-dimensional vector space. One decomposition chooses particular coefficients and produces one vector; the subspace contains every vector our fixed spanning vectors can build. It contains the zero vector, and scaling or adding vectors within it always gives another vector in the same set. In our example, the whole plane is the subspace, and each blue vector is one member of it.

Our two independent vectors span a plane through the origin. The vector h=(5,3,2)h=(5,3,2) lies in that plane because we can build it with a=b=1a=b=1. But (0,0,3)(0,0,3) is unreachable: making the first two coordinates zero forces a=b=0a=b=0, which also makes the third zero. To reach every vector in 3D, we would need a third vector outside the plane. The earlier widget’s Coordinate basis and Other basis each provide three independent vectors, so their spans fill all of R3\mathbb R^3.

The same vector can belong to different subspaces. For example, (1,0,0)(1,0,0) can be built as (1,1,0)+(0,−1,0)(1,1,0)+(0,-1,0), whose components span the xyxy-plane, or as (1,0,1)+(0,0,−1)(1,0,1)+(0,0,-1), whose components span the xzxz-plane. Infinitely many planes through the origin contain this same vector.

The vector (1, 0, 0) belongs to two planesThe green xy-plane and pink xz-plane intersect along the x-axis. A blue arrow from the origin to the point (1, 0, 0) lies along this intersection, so the entire vector belongs to both planes. The shaded patches show only part of each infinite plane.xz-planexy-planezyx0(1, 0, 0)

So a vector doesn’t determine a unique larger subspace. Once we fix the spanning vectors, however, their span is uniquely determined. In the widget above, both planes contain the xx-axis. The blue vector and its endpoint (1,0,0)(1,0,0) lie in both planes. Each shaded patch is part of an infinite plane.

Subspaces give us a way to study structure in neural network representations. A subspace can be associated with a feature or a group of related features: its spanning vectors provide directions along which the representation can vary, and changing their coefficients produces components that may encode different feature values. However, the vectors that span a subspace do not necessarily represent separate features, such as color or shape. We need experiments to find out what information, if any, they represent.

Researchers have tested such interpretations experimentally. An Othello study identified directions encoding board state and changed the model’s behavior by modifying activations along them. Another study found days and months arranged approximately in circles within two-dimensional activation subspaces; interventions changed predictions on day and month arithmetic tasks. The plane is the subspace, while positions around the circle represent feature values. These experiments provide evidence that the models use the identified representations, without implying that every point in a subspace has a meaningful interpretation.

In the examples above, we saw how two vectors span a plane and how a vector outside that plane remains unreachable, regardless of the coefficients we choose. Now, the interesting question is what determines the geometry of that span: why a plane rather than a line or all of 3D space, and what determines which plane we get? To answer that, we need to distinguish the number of coordinates from the number of independent directions.

Three coordinates do not require three independent directions

If we build a vector in R3\mathbb R^3 by adding component vectors, each component also has three coordinates. Having three coordinates tells us that the vectors live in three-dimensional space; it does not tell us the dimension of the subspace they span. The dimension of the span depends on how many of the chosen vectors are linearly independent.

Consider two independent vectors, v1=(1,0,0)v_1=(1,0,0) and v2=(0,1,0)v_2=(0,1,0). Their combinations have the form (a,b,0)(a,b,0). Since the third coordinate is always zero, these vectors fill the xyxy-plane. They can build (3,5,0)(3,5,0), but not (3,5,2)(3,5,2). Now replace the second vector with (0,1,2)(0,1,2):

a(1,0,0)+b(0,1,2)=(a,b,2b)a(1,0,0)+b(0,1,2)=(a,b,2b)

The span is still a plane, now tilted so that z=2yz=2y. For example, 3(1,0,0)+5(0,1,2)=(3,5,10)3(1,0,0)+5(0,1,2)=(3,5,10) lies in it. A two-dimensional subspace in three-dimensional space does not require one coordinate to be zero. A vector can have three nonzero coordinates and still lie in this plane: the third coordinate is tied to the second, leaving only two independent choices.

Compare the flat and tilted planes below. Changing the coefficients moves the blue vectors within their planes; neither construction can reach its marked red target.

Flat plane · 2D
v₁ = (1, 0, 0)v₂ = (0, 1, 0)
xyz(3, 5, 0)(3, 5, 2)0
3(1, 0, 0) + 5(0, 1, 0)
= (3, 5, 0)
Tilted plane · 2D
v₁ = (1, 0, 0)v₂ = (0, 1, 2)
xyz(3, 5, 10)(3, 5, 9)0
3(1, 0, 0) + 5(0, 1, 2)
= (3, 5, 10)

Adding a third vector outside that plane, such as (0,0,1)(0,0,1), lets us build any vector in R3\mathbb{R}^3 by choosing suitable coefficients:

a(1,0,0)+b(0,1,2)+c(0,0,1)=(a,b,2b+c)a(1,0,0)+b(0,1,2)+c(0,0,1)=(a,b,2b+c)

We can now build any target vector (x,y,z)(x,y,z). Our combination produces (a,b,2b+c)(a,b,2b+c), so we choose a=xa=x and b=yb=y to match the first two coordinates, then c=z−2yc=z-2y to match the third. For example, to build (3,5,2)(3,5,2), choose a=3a=3, b=5b=5, and c=−8c=-8. A third vector already in the plane would add no independent direction.

The next widget shows this expansion starting with the flat plane: adding (0,0,1)(0,0,1) gives the right-hand construction a third independent direction. With three freely chosen coefficients, this construction can reach any vector in R3\mathbb R^3. The initial values a=3a=3, b=5b=5, and c=2c=2 reach the target (3,5,2)(3,5,2). Move cc to change its third coordinate without changing the first two.

Flat plane · 2D
v₁ = (1, 0, 0)v₂ = (0, 1, 0)
xyz(3, 5, 0)(3, 5, 2)0
3(1, 0, 0) + 5(0, 1, 0)
= (3, 5, 0)
Full space · 3D
v₁ = (1, 0, 0)v₂ = (0, 1, 0)v₃ = (0, 0, 1)
xyz(3, 5, 2)0
3(1, 0, 0) + 5(0, 1, 0) + 2(0, 0, 1)
= (3, 5, 2)

From the perspective of representation analysis, a shared subspace, in this case a plane, can tell us something about the collection of representations. To connect this geometry to a neural network, consider what happens when it processes several different inputs. We can collect activation vectors from the same layer into an activation matrix, with one input per row and one neuron per column. Analyzing this matrix can reveal whether the collected activations lie in a shared lower-dimensional subspace.

Suppose three images produce the activation vectors (1,1,0)(1,1,0), (2,0,2)(2,0,2), and (3,1,2)(3,1,2). All three can be built from the same two fixed vectors, v1=(1,1,0)v_1=(1,1,0) and v2=(1,−1,2)v_2=(1,-1,2):

(1,1,0)=v1,(2,0,2)=v1+v2,(3,1,2)=2v1+v2.\begin{aligned} (1,1,0)&=v_1,\\ (2,0,2)&=v_1+v_2,\\ (3,1,2)&=2v_1+v_2. \end{aligned}

All three activations therefore lie in the same plane, despite each having three coordinates. The spanning vectors stay fixed; only their coefficients change from image to image.

When we pass different images through the same layer, each image produces its own activation vector. To check whether these vectors share a plane, we ask whether the same two spanning vectors can build every one of them. Finding a plane that contains one image’s activation vector does not tell us whether the activation vectors from other images also lie in it.

Next, let’s see what happens when we organize our construction vectors as matrix columns.

Linear combinations: building the output from columns

Imagine two sets of possible vectors. We call them the input space and the output space. The matrix WW defines a mapping function between them: it takes an input vector xx and produces an output vector WxWx. This mapping is a linear transformation.

If we look at how WW builds the output, we can see how each column contributes a component vector. Each column lies in the output space and is scaled by the corresponding coordinate of xx—the output of one neuron in the previous layer. We saw earlier how neuron activations scale coordinate basis vectors to form a layer’s activation vector. When passed to the next layer, those same activations scale the columns of WW, which serve as the vectors we combine to build the output. These scaled columns add up to WxWx, making the output a linear combination of the matrix’s columns.

Writing the columns as w1,…,wnw_1,\ldots,w_n and the input coordinates as x1,…,xnx_1,\ldots,x_n, we can express this construction as:

Wx=x1w1+x2w2+⋯+xnwn.Wx=x_1w_1+x_2w_2+\cdots+x_nw_n.

In a neural network, WW is the layer’s weight matrix, and xx is the activation vector supplied by the previous layer. Each coordinate xix_i scales the corresponding column wiw_i, producing a component vector xiwix_iw_i of the output.

The widget below follows this construction one column at a time. Each coordinate of the input x=(5,3,2)x=(5,3,2) scales its corresponding column to produce a component vector. Select Next column to follow how each input coordinate scales its column. The matching arrow highlights this step, while all three contributions add up to the transformed output Wx=(19,8,2)Wx=(19,8,2).

Scale the matrix columns, then add themInput coordinate x₁ = 5 scales column 1, (2, 1, 0), producing the contribution (10, 5, 0). The three column contributions sum to (19, 8, 2).Component vectorsResultWxInput vector xWeight matrix W5x₁3x₂2x₃w₁210x₁w₁1050w₂110x₂w₂330w₃301x₃w₃602Scale byx₁ = 5Addcolumns1982

5 × (2, 1, 0) = (5 × 2, 5 × 1, 5 × 0) = (10, 5, 0)

These components let us track how individual input coordinates contribute to the result. To study a feature distributed across several coordinates, we may instead decompose the input along directions associated with that feature and examine how WW transforms those components.

Column space: which outputs can the matrix reach?

The matrix does not necessarily reach every vector in the output space; it may map all input vectors into a smaller subspace, such as a plane within three-dimensional space. Earlier, we saw how a fixed set of component vectors can build only vectors lying within their span, which forms a subspace. For a matrix, that subspace of reachable outputs is called its column space.

The name comes from the fact that the matrix’s columns are the fixed vectors spanning the subspace of possible outputs.

In the earlier widget, we built the same vector h=(5,3,2)h=(5,3,2) using three different sets of component vectors. Let’s now view each construction as a matrix transformation: the vectors we chose become the columns of WW, their coefficients become the input vector xx, and hh is the output WxWx.

All three constructions produce hh with the chosen coefficients, but they cannot all produce the same range of other outputs. By keeping each matrix fixed and varying its input, we can see which vectors belong to its column space.

First, let’s start with the vector under the Coordinate basis option. We built hh as 5(1,0,0)+3(0,1,0)+2(0,0,1)5(1,0,0)+3(0,1,0)+2(0,0,1). The three coordinate vectors become the columns of WW, and the scaling coefficients 5,3,25,3,2 become the entries of xx:

W=(100010001),x=(532),Wx=(532)W=\begin{pmatrix}1&0&0\\0&1&0\\0&0&1\end{pmatrix}, \qquad x=\begin{pmatrix}5\\3\\2\end{pmatrix}, \qquad Wx=\begin{pmatrix}5\\3\\2\end{pmatrix}

Since WW is the identity matrix, it leaves the input unchanged: Wx=x=(5,3,2)Wx=x=(5,3,2).

The input vector xx has three coordinates, so the input space is R3\mathbb R^3. Each coordinate scales one column of WW. These three columns span all of R3\mathbb R^3, so this matrix can reach every vector in the output space.

Let’s now look at the Other basis option. We build the same vector as h=2(1,1,1)+1(1,−1,1)+1(2,2,−1)=(5,3,2)h=2(1,1,1)+1(1,-1,1)+1(2,2,-1)=(5,3,2). The columns are now (1,1,1)(1,1,1), (1,−1,1)(1,-1,1), and (2,2,−1)(2,2,-1), with input coefficients 2,1,12,1,1:

W=(1121−1211−1),x=(211),Wx=(532)W=\begin{pmatrix}1&1&2\\1&-1&2\\1&1&-1\end{pmatrix}, \qquad x=\begin{pmatrix}2\\1\\1\end{pmatrix}, \qquad Wx=\begin{pmatrix}5\\3\\2\end{pmatrix}

The input space and output space are both still R3\mathbb R^3. These three columns are also independent, so their linear combinations can produce every output vector. We changed the construction vectors and input coefficients, but can still reach all of R3\mathbb R^3.

Something interesting emerges when we try the Two vectors option. The same vector hh is now built using only two construction vectors: h=1(4,1,1)+1(1,2,1)=(5,3,2)h=1(4,1,1)+1(1,2,1)=(5,3,2). This means that our transformation matrix has only two columns. Its input contains the two coefficients 1,11,1:

W=(411211),x=(11),Wx=(532)W=\begin{pmatrix}4&1\\1&2\\1&1\end{pmatrix}, \qquad x=\begin{pmatrix}1\\1\end{pmatrix}, \qquad Wx=\begin{pmatrix}5\\3\\2\end{pmatrix}

The input space is now R2\mathbb R^2, because we supply only two coefficients. The output space remains R3\mathbb R^3 because every output still has three coordinates: (4a+b,  a+2b,  a+b)(4a+b,\;a+2b,\;a+b). However, there are only two independent choices, aa and bb, even though the result has three coordinates. The matrix’s shape limits the reachable subspace within the output space to at most two dimensions.

The two construction vectors we chose, and therefore the corresponding matrix columns, are independent, so they span a plane through the origin, while their values determine which plane it is. In the previous examples, the columns spanned the entire three-dimensional output space. In this case, with just two vectors, we can still reach the same vector h=(5,3,2)h=(5,3,2), but only because it lies in the plane they span—the matrix’s column space. Vectors outside that plane remain unreachable.

The table below compares the three constructions: which input vectors each matrix accepts and which output vectors it can produce. All three have the same three-dimensional output space, but only some of the matrices can produce every vector in that space.

Widget optionInput space: coefficients xxColumn space: reachable outputs
Coordinate basisR3\mathbb R^3All of R3\mathbb R^3
Other basisR3\mathbb R^3All of R3\mathbb R^3
Two vectorsR2\mathbb R^2A plane inside R3\mathbb R^3

We saw how having only two columns limits the reachable outputs to at most a plane. Interestingly, having three columns does not guarantee that a matrix can reach the entire three-dimensional output space. The columns must also be linearly independent.

In the following matrix, the first two columns are identical, so the second column adds no new direction. The columns c1c_1 and c3c_3 are independent and form a basis for the plane of reachable outputs:

W=(110001111),c1=(101),c2=(101),c3=(011)W=\begin{pmatrix}1&1&0\\0&0&1\\1&1&1\end{pmatrix}, \qquad c_1=\begin{pmatrix}1\\0\\1\end{pmatrix},\quad c_2=\begin{pmatrix}1\\0\\1\end{pmatrix},\quad c_3=\begin{pmatrix}0\\1\\1\end{pmatrix}

We can see mathematically why these three columns produce outputs in only two independent directions. Let’s write the input as hh and the output as z=Whz=Wh. Since c2=c1c_2=c_1, the first two input coordinates scale the same column vector:

z=Wh=h1c1+h2c2+h3c3=(h1+h2)(1,0,1)+h3(0,1,1)z=Wh=h_1c_1+h_2c_2+h_3c_3 =(h_1+h_2)(1,0,1)+h_3(0,1,1)

If we let s=h1+h2s=h_1+h_2 and t=h3t=h_3, every possible output has the form:

s(1,0,1)+t(0,1,1)=(s,t,s+t)s(1,0,1)+t(0,1,1)=(s,t,s+t)

We can see that every output is determined by two values, s=h1+h2s=h_1+h_2 and t=h3t=h_3, with the third coordinate always equal to the sum of the first two. All vectors with this relationship form a plane, which is the matrix’s column space. The dimension depends on the number of independent directions, not the number of columns.

Dot products: building the output one row at a time

In the previous section, we saw how a matrix’s columns build its output from scaled vectors. Let’s now look at the same transformation through the matrix’s rows, and examine how the input’s component vectors contribute to each output coordinate. As explained in how neurons work together to transform a vector, each row of the weight matrix takes a dot product with the whole input vector, producing one output coordinate.

The widget below follows the calculation one row at a time. Select each row to see its weights take a dot product with the whole input h=(5,3,2)h=(5,3,2), producing one coordinate of the output Wh=(19,8,2)Wh=(19,8,2).

Each row reads the whole inputRow 1, (2, 1, 3), takes a dot product with the whole input (5, 3, 2) to produce output coordinate z₁ = 19.InputhWeight matrixWOutputz = Wh2131100015h₁3h₂2h₃19z₁8z₂2z₃Each row reads the whole inputRow 1, (2, 1, 3), takes a dot product with the whole input (5, 3, 2) to produce output coordinate z₁ = 19.InputhWeight matrixWOutputz = Wh2131100015h₁3h₂2h₃19z₁8z₂2z₃

z₁ = 2 × 5 + 1 × 3 + 3 × 2 = 19

Let’s focus on the first row. Its dot product with the whole input produces the scalar 1919:

(2,1,3)⋅(5,3,2)=10+3+6=19.(2,1,3)\cdot(5,3,2)=10+3+6=19.

Linearity lets us express this dot product as the sum of contributions from the input’s component vectors. To see where 1010, 33, and 66 come from, split the input into its coordinate components:

h=c1+c2+c3,c1=(5,0,0),c2=(0,3,0),c3=(0,0,2).h=c_1+c_2+c_3, \qquad c_1=(5,0,0),\quad c_2=(0,3,0),\quad c_3=(0,0,2).

For the first row, r=(2,1,3)r=(2,1,3), linearity gives:

r⋅h=r⋅(c1+c2+c3)=r⋅c1+r⋅c2+r⋅c3.r\cdot h=r\cdot(c_1+c_2+c_3)=r\cdot c_1+r\cdot c_2+r\cdot c_3.

Each component supplies one scalar contribution to this output coordinate:

r⋅c1=(2,1,3)⋅(5,0,0)=10,r⋅c2=(2,1,3)⋅(0,3,0)=3,r⋅c3=(2,1,3)⋅(0,0,2)=6.\begin{aligned} r\cdot c_1&=(2,1,3)\cdot(5,0,0)=10,\\ r\cdot c_2&=(2,1,3)\cdot(0,3,0)=3,\\ r\cdot c_3&=(2,1,3)\cdot(0,0,2)=6. \end{aligned}

Adding them gives r⋅h=10+3+6=19r\cdot h=10+3+6=19, exactly the same result as computing (2,1,3)⋅(5,3,2)(2,1,3)\cdot(5,3,2) directly.

Repeating this calculation for every row gives one scalar result per row. Collecting those results produces the output vector Wh=(19,8,2)Wh=(19,8,2). For each row, taking the dot product with the whole input gives the same result as adding the dot products with its components.

This works for any decomposition of the input: if h=v1+v2h=v_1+v_2, then r⋅h=r⋅v1+r⋅v2r\cdot h=r\cdot v_1+r\cdot v_2, even when the components point in other directions.

Geometrically, we can project each component onto the same line—the direction of the row vector rr—and add those signed projections. Their sum equals the projection of the whole input. A component pointing partly along rr contributes positively, one pointing partly against it contributes negatively, and a perpendicular component contributes zero.

To see these projections clearly, the next widget uses a two-dimensional example with the unit row r=(1,0)r=(1,0) pointing along the horizontal axis. The green vector c1c_1 and pink vector c2c_2 are the two component vectors. The blue vector h=c1+c2h=c_1+c_2 is the combined vector they build.

The dashed lines connect each vector’s endpoint to its projection on the horizontal axis. The matching colored arrows along that axis show the projected vectors: green for c1c_1, pink for c2c_2, and blue for their sum hh. These projection arrows can overlap. A projection pointing right contributes positively, one pointing left contributes negatively, and a zero projection contributes nothing. Because rr has length one, each signed projection length equals the corresponding dot product with rr.

Drag either component’s endpoint or change its coordinates to see both the combined vector and their projections update. Try Opposite signs, Perpendicular, and Cancelling to see negative, zero, and cancelling contributions.

h = (3, 2) + (1, -1) = (4, 1)

Component projections add to the projection of the whole vectorThe fixed unit row r = (1, 0) points along the horizontal line. Components c1 = (3, 2) and c2 = (1, -1) add to h = (4, 1). Their signed projections are 3 and 1, adding to 4. Drag the green or pink endpoint, or focus it and use the arrow keys.-8-6-4-202468yc₁ = (3, 2)c₂ = (1, -1)h = (4, 1)
c₁ = (3, 2)
c₂ = (1, -1)

The widget used a unit row, so each component’s signed projection length was its contribution to the output. A weight-matrix row need not have length one: its length scales every contribution. To understand how much each component contributes, we therefore need to consider both its length and its alignment with the row.

For the unit row direction u=r/∥r∥u=r/\|r\|, the dot product u⋅cu\cdot c is the signed projection length of a component cc. Using rr itself multiplies that length by ∥r∥\|r\|:

u⋅c=∥c∥cos⁡θ,r⋅c=∥r∥ (u⋅c)=∥r∥ ∥c∥cos⁡θ,u\cdot c=\|c\|\cos\theta, \qquad r\cdot c=\|r\|\,(u\cdot c)=\|r\|\,\|c\|\cos\theta,

where θ\theta is the angle between the component and the row’s direction. For our row r=(2,1,3)r=(2,1,3), whose length is 14\sqrt{14}:

  • c1=(5,0,0)c_1=(5,0,0) has length 55 and alignment cos⁡θ1=2/14\cos\theta_1=2/\sqrt{14}, giving a contribution of 1010.
  • c2=(0,3,0)c_2=(0,3,0) has length 33 and alignment cos⁡θ2=1/14\cos\theta_2=1/\sqrt{14}, giving a contribution of 33.
  • c3=(0,0,2)c_3=(0,0,2) has length 22 and alignment cos⁡θ3=3/14\cos\theta_3=3/\sqrt{14}, giving a contribution of 66.

From that, we can see that the third component is most closely aligned with rr: it has the largest cosine and therefore the smallest angle to the row’s direction. But the first component contributes more because it is longer. Each input component contributes according to its length and alignment with the row’s direction, and linearity lets us add these signed contributions to obtain the row’s response to the whole input vector.

Rows and columns give two ways to calculate the same transformation:

ColumnsRows
Where the vectors liveOutput spaceInput space
Role in multiplicationScale and add to build the outputEach takes a dot product to compute one output coordinate

Row space and null space: what the matrix reads and ignores

Let’s start with two vectors (1,0,0)(1,0,0) and (0,1,0)(0,1,0). They are independent, and their linear combinations have the form

a(1,0,0)+b(0,1,0)=(a,b,0)a(1,0,0)+b(0,1,0)=(a,b,0)

Their span is the xyxy-plane, with all its vectors having the form (a,b,0)(a,b,0), as shown in the widget below.

Now imagine we have a blue vector h=(3,5,2)h=(3,5,2) and want to see whether it lies in this subspace. One way to decompose it is into the green component (1,1,0)(1,1,0) and the pink component (2,4,2)(2,4,2).

The rows build vectors within a planeThe input (3, 5, 2) is the sum of (1, 1, 0) in the row space and (2, 4, 2) outside it. The pink component is not perpendicular to the plane and still contributes to the output. The pink component is drawn from the green arrow's tip to the blue arrow's tip. The blue input cannot be built from these rows alone.h₁h₂h₃h = (3, 5, 2)(1, 1, 0)(2, 4, 2)0

Notice how the green component lies in the plane, while the pink component and the blue vector lie outside it. The green component lies in the plane because it can be built from the two vectors (1,0,0)(1,0,0) and (0,1,0)(0,1,0) that span it.

Now suppose we use the two fixed vectors (1,0,0)(1,0,0) and (0,1,0)(0,1,0) as the rows of a matrix:

W=(100010)W=\begin{pmatrix}1&0&0\\0&1&0\end{pmatrix}

In this case, each row provides a vector we can use in a linear combination. Together, these vectors span a subspace of the input space known as the row space. The plane in the widget is therefore this matrix’s row space.

Let’s now try a different decomposition of the same blue vector, using the green component (3,5,0)(3,5,0) and the pink component (0,0,2)(0,0,2). Green still lies in the row-space plane, but pink now points perpendicular to it, as shown in the widget below.

The rows build vectors within a planeThe input (3, 5, 2) is the sum of (3, 5, 0) in the row space and (0, 0, 2) outside it. The pink component is perpendicular to the plane and contributes zero to the output. The pink component is drawn from the green arrow's tip to the blue arrow's tip. The blue input cannot be built from these rows alone.h₁h₂h₃h = (3, 5, 2)(3, 5, 0)(0, 0, 2)0

Let’s treat the blue vector hh as an input and examine how its components contribute to the output in each decomposition. The matrix produces the same output in both cases, but the components in each decomposition make different contributions to it.

In the first decomposition, we can calculate each component’s contribution by taking its dot product with each row of WW. Each result gives one coordinate of that component’s contribution to the output.

Green component (1,1,0)(1,1,0)Pink component (2,4,2)(2,4,2)
Dot product with row 1(1,0,0)⋅(1,1,0)=1(1,0,0)\cdot(1,1,0)=1(1,0,0)⋅(2,4,2)=2(1,0,0)\cdot(2,4,2)=2
Dot product with row 2(0,1,0)⋅(1,1,0)=1(0,1,0)\cdot(1,1,0)=1(0,1,0)⋅(2,4,2)=4(0,1,0)\cdot(2,4,2)=4
Contribution to the output(1,1)(1,1)(2,4)(2,4)

Neither component’s third coordinate contributes to the output, because both matrix rows have a zero third coordinate. By linearity, the green and pink contributions add up to the output:

Wh=W(1,1,0)+W(2,4,2)=(1,1)+(2,4)=(3,5)Wh=W(1,1,0)+W(2,4,2)=(1,1)+(2,4)=(3,5)

In the second decomposition, green (3,5,0)(3,5,0) contributes the entire output, while pink (0,0,2)(0,0,2) contributes nothing:

Green component (3,5,0)(3,5,0)Pink component (0,0,2)(0,0,2)
Dot product with row 1(1,0,0)⋅(3,5,0)=3(1,0,0)\cdot(3,5,0)=3(1,0,0)⋅(0,0,2)=0(1,0,0)\cdot(0,0,2)=0
Dot product with row 2(0,1,0)⋅(3,5,0)=5(0,1,0)\cdot(3,5,0)=5(0,1,0)⋅(0,0,2)=0(0,1,0)\cdot(0,0,2)=0
Contribution to the output(3,5)(3,5)(0,0)(0,0)

Just as in the first decomposition, neither component’s third coordinate contributes to the output, because both matrix rows have a zero third coordinate. By linearity, the green and pink contributions add up to the output:

Wh=W(3,5,0)+W(0,0,2)=(3,5)+(0,0)=(3,5)Wh=W(3,5,0)+W(0,0,2)=(3,5)+(0,0)=(3,5)

Notice the difference between the two decompositions: the first pink component still contributes to the output, while the second contributes nothing. This happens because the second pink component is perpendicular to both rows, and consequently to the entire row space. We can see this in the widgets and in the dot-product calculations in the tables. In the first case, the pink component has dot products of 22 and 44 with the two rows, whereas in the second case, both dot products are zero. This shows that lying outside the row space does not mean a vector is completely ignored; being perpendicular to every row does.

Null space: the inputs that contribute nothing

We’ve seen that the second pink component, (0,0,2)(0,0,2), contributes nothing because it is perpendicular to every row. The same is true of every vector (0,0,z)(0,0,z) along the zz-axis: changing its length or reversing its direction still leaves both dot products at zero.

The set of all input vectors a matrix maps to zero is called its null space. For the matrix we used in the previous sections, that set is the entire zz-axis. The first pink component has a part in the null space; the second lies entirely in it.

The input’s null-space component is (0,0,2)(0,0,2) in both cases. The second decomposition isolates it explicitly, putting the entire row-space component in green. An input has many possible decompositions, but its split into a row-space component and a null-space component is unique.

So we can take any matrix and an input it accepts, and work out which part of that input the matrix ignores and which part affects the output. There is only one way to split the input so that one part lies entirely in the row space and the other entirely in the null space.

For our matrix and input, this is exactly the second decomposition shown in our widgets and tables:

(3,5,2)=(3,5,0)⏟row-space component+(0,0,2)⏟null-space component(3,5,2)=\underbrace{(3,5,0)}_{\text{row-space component}}+\underbrace{(0,0,2)}_{\text{null-space component}}

The alternative decomposition (1,1,0)+(2,4,2)(1,1,0)+(2,4,2) builds the same input, but its second component is not entirely in the null space. The calculation is straightforward for this example; for a general matrix, methods such as SVD let us compute the split systematically.

A vector maps to zero when it is perpendicular to every row—and therefore to every vector in the row space. The null space is the perpendicular complement of the row space, which we write as:

Null⁡(W)=Row⁡(W)⊥\operatorname{Null}(W)=\operatorname{Row}(W)^\perp

The symbol ⊥\perp denotes all vectors that are perpendicular to every vector in this space. Splitting an input into these two parts gives:

h=hrow+hnull,Wh=Whrowh=h_{\mathrm{row}}+h_{\mathrm{null}}, \qquad Wh=Wh_{\mathrm{row}}

So Wh=WhrowWh=Wh_{\mathrm{row}} shows that only the row-space component affects the output. The matrix can still change its length and direction, or map it into an output space with a different number of coordinates.

Left null space: perpendicular to every possible output

Suppose a layer’s weight matrix has a third row equal to the sum of its first two rows. This leads to a constraint on the output: the third coordinate always equals the sum of the first two. No matter what input we give it, it cannot produce (1,2,4)(1,2,4), because the first two coordinates would require the third to be 33. The left null space helps us identify constraints like this on a layer’s output.

As we saw earlier, the column space contains all possible outputs. The left null space describes the directions perpendicular to all of them. Just as the null space is perpendicular to the row space in the input space, the left null space is perpendicular to the column space in the output space.

In our earlier column-space example, every output has the form (s,t,s+t)(s,t,s+t). The third coordinate always equals the sum of the first two. The vector q=(−1,−1,1)q=(-1,-1,1) captures this constraint:

q⋅(s,t,s+t)=−s−t+(s+t)=0q\cdot(s,t,s+t)=-s-t+(s+t)=0

It lies in the left null space because it is perpendicular to every possible output. A target such as (0,0,1)(0,0,1) breaks this constraint, so no input can make this matrix produce it. Changing the input alone cannot fix that mismatch.

This gives the left null space a practical role: it reveals constraints on what a fixed weight matrix can produce. For a linear prediction layer, it can tell us that some target outputs are unreachable even before we try to find an input that produces them. These constraints apply to the linear output WhWh; adding a bias shifts them to q⋅z=q⋅bq\cdot z=q\cdot b for z=Wh+bz=Wh+b, and a following nonlinear activation can change them further.

It’s important to stress that the left null space is not where erased inputs go; those inputs map to the origin. It describes restrictions on the output side.

Putting the four subspaces together

We can now connect the four spaces in one picture. The row space and null space split the input into perpendicular components. The matrix sends the null-space component to zero and transforms the row-space component into an output in the column space. The left null space is perpendicular to every vector in that output subspace.

The four fundamental subspaces: the input h splits into row-space and null-space components. W maps h and its row-space component to the same output Wh, while mapping the null-space component to zero.

The image shows how the four subspaces relate, but its flat patches are schematic: a subspace could be a line or a plane, depending on the matrix. The two widgets below make those relationships concrete. You can change the input and see how it splits into row-space and null-space components, and how each component contributes to the output.

Let’s now explore these relationships in the widget below. It uses the input vector h=(5,3,2)h=(5,3,2) and the matrix:

W=(110001111)W=\begin{pmatrix}1&1&0\\0&0&1\\1&1&1\end{pmatrix}

The starting input h=(5,3,2)h=(5,3,2) lies outside both the row-space plane and the null-space line. It has a component in each. The three sliders control the input coordinates h1h_1, h2h_2, and h3h_3. Changing them changes the vector the matrix transforms, while the matrix itself stays fixed.

Input space · ℝ³

h₁h₂h₃hhrowhnull0

Row space is a plane, Null space is a line

Output space · ℝ³

z₁z₂z₃Wh = Whrow0Whnull = (0, 0, 0)

Column space is a plane, Left null space is a line

Drag either plot to rotate; scroll to zoom. With a plot focused, use the arrow keys to rotate, + and − to zoom, or 0 to reset zoom.

Whole input h(5, 3, 2)→(8, 2, 10)
Row-space component hrow(4, 4, 2)→(8, 2, 10)
Null-space component hnull(1, −1, 0)→(0, 0, 0)

Here is what defines each of the four subspaces. The parameters aa, bb, dd, ss, and tt can be any real numbers.

SubspaceShapeVectors it containsWhat this means
Row spacePlane(a,a,b)(a,a,b)The first two input coordinates are equal (h1=h2h_1=h_2); the third is unrestricted.
Null spaceLine(d,−d,0)(d,-d,0)The first two input coordinates cancel, and the third is zero. These vectors map to zero.
Column spacePlane(s,t,s+t)(s,t,s+t)The third output coordinate is the sum of the first two (z3=z1+z2z_3=z_1+z_2).
Left null spaceLine(−d,−d,d)(-d,-d,d)The first two coordinates are equal, and the third is their negative. These vectors are perpendicular to every vector in the column space.

The three cards show the whole input and its two components. Applying WW to the row-space component gives the same output as applying it to the whole input. The null-space component contributes zero, so adding or removing it leaves the output unchanged.

The image’s hrh_r and hnh_n correspond to the widget’s hrowh_{\mathrm{row}} and hnullh_{\mathrm{null}}. Initially, the blue input splits into green and pink components:

(5,3,2)⏟h=(4,4,2)⏟hrow+(1,−1,0)⏟hnull.\underbrace{(5,3,2)}_{h} =\underbrace{(4,4,2)}_{h_{\mathrm{row}}} +\underbrace{(1,-1,0)}_{h_{\mathrm{null}}}.

The arrows crossing the image represent applying WW. In the widget, both the whole input and its green component produce (8,2,10)(8,2,10), so their output arrows overlap in the orange plane. The pink component maps to zero. The purple left-null-space line is perpendicular to the output plane; it is not where erased inputs go.

Changing the input leaves the four subspaces fixed.

Let’s now use the same input vector h=(5,3,2)h=(5,3,2) with this alternative matrix:

W=(110220330)W=\begin{pmatrix}1&1&0\\2&2&0\\3&3&0\end{pmatrix}

It has the same 3×33\times3 shape but rank 1: all its rows are multiples of (1,1,0)(1,1,0). Its row and column spaces are lines, and both null spaces are planes. The starting input lies outside both the row-space line and the null-space plane, with a component in each. The sliders change the input while this matrix stays fixed.

Input space · ℝ³

h₁h₂h₃hhrowhnull0

Row space is a line, Null space is a plane

Output space · ℝ³

z₁z₂z₃Wh = Whrow0Whnull = (0, 0, 0)

Column space is a line, Left null space is a plane

Drag either plot to rotate; scroll to zoom. With a plot focused, use the arrow keys to rotate, + and − to zoom, or 0 to reset zoom.

Whole input h(5, 3, 2)→(8, 16, 24)
Row-space component hrow(4, 4, 0)→(8, 16, 24)
Null-space component hnull(1, −1, 2)→(0, 0, 0)

For this matrix, the four subspaces contain the following vectors. Again, the parameters can be any real numbers.

SubspaceShapeVectors it containsWhat this means
Row spaceLine(a,a,0)(a,a,0)The first two input coordinates are equal, and the third is zero.
Null spacePlane(d,−d,b)(d,-d,b)The first two input coordinates cancel (h1+h2=0h_1+h_2=0); the third is unrestricted. These vectors map to zero.
Column spaceLine(s,2s,3s)(s,2s,3s)The second and third output coordinates are twice and three times the first.
Left null spacePlane(−2a−3b,a,b)(-2a-3b,a,b)The coordinates satisfy z1+2z2+3z3=0z_1+2z_2+3z_3=0. These vectors are perpendicular to the column-space direction (1,2,3)(1,2,3).

Here, changing h3h_3 leaves the output unchanged: the third coordinate direction lies in the null space. Only the component along the green row-space line contributes to the output; every output lies on the orange column-space line.

Matrix rank and the dimensions of the four subspaces

The last concept we need to look at is matrix rank. We’ve seen that matrices with the same shape can have different subspace dimensions. Rank tells us how many independent directions the matrix preserves and, together with its shape, determines the dimensions of all four subspaces.

For a matrix with mm rows and nn columns, the nn columns define an input space of Rn\mathbb R^n, and the mm rows define an output space of Rm\mathbb R^m. These are the dimensions of the full input and output spaces, determined by the matrix’s shape.

Each matrix has a property called rank rr that defines the shared dimension of its row and column spaces: how many independent directions the rows and columns span. These two spaces always have the same dimension, even when the full input and output spaces have different dimensions.

Equivalently, the maximum number of linearly independent rows always equals the maximum number of linearly independent columns. The rank cannot exceed either the number of rows or the number of columns, formally r≤min⁡(m,n)r\leq\min(m,n).

Consider our earlier 2×32\times3 matrix:

W=(100010)W=\begin{pmatrix}1&0&0\\0&1&0\end{pmatrix}

Its shape describes a transformation from three input coordinates to two output coordinates: 3→23\to2. Its two rows are independent, so its rank is 2. The row space is the xyxy-plane inside R3\mathbb R^3, consisting of vectors (a,b,0)(a,b,0). The column space is all of R2\mathbb R^2, consisting of vectors (a,b)(a,b).

Hence, the row and column spaces share a dimension of two, even though the full input and output spaces have different dimensions. The row space still contains three-coordinate vectors; only two coordinates can vary independently. In the column space, those two independent coordinates fill the entire output space.

Two independent directions on each side → rank(W) = 2
Input space · ℝ³
The row space is a plane inside 3D.
Two independent rows span a plane in three dimensionsThe rows (1, 0, 0) and (0, 1, 0) span the horizontal h1 h2 plane. The vertical h3 axis is the null space. The row space has dimension two, although the input has three coordinates.h₃ · null spaceerased by W0r₁r₂h₁h₂
Row-space dimension: 2
Null-space dimension: 3 − 2 = 1
Output space · ℝ²
The column space fills all of 2D.
Two independent columns span the entire two-dimensional output spaceThe columns (1, 0) and (0, 1) span all of R2. The third column is (0, 0), marked at the origin, and adds no direction. The column space has dimension two. Its perpendicular complement, the left null space, contains only zero.c₁c₂c₃ = 0z₁z₂
Column-space dimension: 2
Left-null-space dimension: 2 − 2 = 0

The shaded planes have the same dimension but live in different ambient spaces. The labels r1,r2r_1,r_2 denote rows in the input space R3\mathbb R^3; c1,c2,c3c_1,c_2,c_3 denote columns in the output space R2\mathbb R^2, with c3=0c_3=0 at the origin. Shading shows a portion of each infinite plane.

The table compares the full input and output spaces with the row and column spaces for this matrix:

SpaceWhere it livesIts dimension
Input spaceR3\mathbb R^33
Row spaceA plane inside R3\mathbb R^3: vectors (a,b,0)(a,b,0)2
Output spaceR2\mathbb R^22
Column spaceAll of R2\mathbb R^2: vectors (a,b)(a,b)2

This matrix keeps the first two coordinates and drops the third:

(100010)⏟W(h1h2h3)=(h1h2).\underbrace{\begin{pmatrix}1&0&0\\0&1&0\end{pmatrix}}_{W} \begin{pmatrix}h_1\\h_2\\h_3\end{pmatrix} =\begin{pmatrix}h_1\\h_2\end{pmatrix}.

We can write this as W(h1,h2,h3)=(h1,h2)W(h_1,h_2,h_3)=(h_1,h_2), using the tuple as shorthand for a column vector. For example, both (5,3,2)(5,3,2) and (5,3,99)(5,3,99) map to (5,3)(5,3). The row-space component (a,b,0)(a,b,0) maps to (a,b)(a,b), while the null-space component (0,0,c)(0,0,c) maps to zero.

That leaves one null-space direction in the input: the third coordinate axis. On the output side, the column space already fills all of R2\mathbb R^2, so its perpendicular complement—the left null space—contains only the zero vector and has dimension zero.

The same dimension accounting works for any m×nm\times n matrix of rank rr: the row and column spaces each have dimension rr, the null space has dimension n−rn-r, and the left null space has dimension m−rm-r.

Shape sets the limit; the entries determine the rank. A different 2×32\times3 matrix could have rank 1. Its full input and output spaces would still be R3\mathbb R^3 and R2\mathbb R^2, but its row and column spaces would both be lines. Its null space would then have dimension 3−1=23-1=2, and its left null space would have dimension 2−1=12-1=1.

Image viewer

Pinch or use + / − to zoom. Drag or use arrow keys to move. Esc to close.