Subspaces, rank, and projection
Column spaces, null spaces, and what a linear map preserves and destroys.
What gets destroyed
In the previous post, we had a decoder matrix that mapped 3-dimensional neural activity to 2-dimensional hand velocity:
Three numbers go in. Two come out. That means something is being lost. Not just "some precision" or "some detail" — an entire dimension of information is being annihilated. There must be directions in the 3-dimensional input space that this matrix sends to zero, directions where the neural activity changes but the predicted velocity does not.
Can we find one? We need a vector such that . That means and . From the first equation, . Substituting into the second: , which simplifies to , giving . Setting : .
Let's check. Does ? First row: . Second row: . Yes. This vector is invisible to the decoder. A neuron can change its firing rate along this direction and the predicted velocity will not budge.
This post is about what a matrix preserves and what it destroys. Every matrix carries this structure: a set of directions that survive the map and a set that get annihilated. Understanding this split is what makes dimensionality reduction, least-squares fitting, and subspace identification precise.
The column space
Start with the output side. What are all the possible outputs of the decoder ?
From the column picture in the previous post, we know that is always a linear combination of the columns of . So the set of all possible outputs is the span of those columns. This set is the column space of .
Our decoder has columns , , . These are three vectors in . Can three 2-dimensional vectors be independent? No. In two dimensions, at most two vectors can be independent. The third must be a combination of the first two.
Let's check. Is a combination of and ? We need . First component: . Second: . From the first: . Substituting and solving: , . So yes, is in the span of and .
The column space is all of : this decoder can produce any velocity vector. Two independent columns in a 2-dimensional output space is enough to fill it. The third column adds no new reachable outputs.
Now consider a different situation. Suppose the decoder has columns , , . Every column is a multiple of . The column space is a single line through the origin. This decoder can only produce velocities along one direction, regardless of what the neural population does. The output is trapped on that line.
The rank of a matrix is the dimension of its column space: the number of independent columns. Our original decoder has rank 2 (two independent columns in a 2-dimensional output). The degenerate decoder has rank 1 (all columns lie along one line). Rank tells you the effective dimensionality of the map's output, not the nominal size of the matrix.For neural data, the useful notion is "effective rank." A 500-by-100 data matrix is nearly always full rank because of noise, but most of that rank is noise-driven. The useful rank is the number of dimensions carrying substantial variance, which is what PCA eigenvalues quantify. Cunningham and Yu [4] review methods for estimating effective dimensionality in neural populations.
The null space
We already found one vector that the decoder sends to zero: . Any scalar multiple of this vector also gets sent to zero (the map is linear: if , then ). The set of all inputs that the matrix kills is the null space.
For our decoder, the null space is a line in 3-dimensional space: all multiples of . Neural activity can vary freely along this line without changing the decoded velocity at all. The decoder is blind to it.
This is not just a mathematical curiosity. In neuroscience, the null space of a decoder has a specific interpretation: it is the set of neural activity patterns that produce no behavioral output. Kaufman et al. showed that preparatory activity in motor cortex lives largely in the null space of the neural-to-muscle map.Kaufman et al. [8] demonstrated that preparatory neural activity in motor cortex is largely confined to directions that do not drive muscles. The language of null spaces makes this finding precise: preparation involves large changes in neural state along directions that the motor output mapping annihilates. The population state changes significantly during planning, but those changes are confined to directions the downstream readout ignores. Large neural changes, zero behavioral effect.
The dimension of the null space is the nullity. For our 2-by-3 decoder, the null space is 1-dimensional (a line). If the matrix were 2-by-100 (a realistic decoder), the null space would be 98-dimensional. Out of 100 possible directions of neural activity, only 2 would affect the output. The other 98 would be invisible.
Rank and nullity
Look at the numbers. Our decoder is 2-by-3. It has rank 2 (two independent columns) and nullity 1 (a 1-dimensional null space). Notice: 2 + 1 = 3, the number of columns.
This is not a coincidence. It is a theorem:
where is the number of columns (the dimension of the input space). Directions preserved plus directions destroyed equals the total number of input dimensions. Nothing is unaccounted for. Every input direction either survives the map or gets annihilated; none falls through the cracks.
For a 2-by-100 neural decoder: rank at most 2, so nullity at least 98. The vast majority of neural activity patterns are invisible to the decoder. This is not a deficiency of the decoder. It is arithmetic: a 2-dimensional output simply cannot distinguish among 100-dimensional inputs. At most 2 directions survive.
For a 500-by-100 data matrix (500 time points, 100 neurons): if the rank is 10, then the nullity is 90. The population's activity is confined near a 10-dimensional subspace. The other 90 dimensions are the directions along which the data does not move (or moves only due to noise). Finding those 10 directions is what dimensionality reduction does.
The four subspaces
The column space lives in the output. The null space lives in the input. Is there a way to see both sides at once?
An matrix connects two spaces: the input and the output . Each of these spaces splits into two perpendicular pieces, giving four subspaces in all [6].
On the input side: the row space (the span of the rows of ) and the null space. These are perpendicular to each other and together they fill the entire input space. Every input vector splits uniquely into a row-space part and a null-space part.
On the output side: the column space and the left null space (vectors satisfying ). These are also perpendicular, and together they fill the output space.
The means "direct sum": every vector in the space can be written as one piece from each subspace, the decomposition is unique, and the two pieces are perpendicular.
Now watch what the matrix does. Take an input vector and split it into its row-space part and its null-space part. The matrix maps the row-space part to the column space and sends the null-space part to zero. That is the entire story. The row space is what the matrix reads; the null space is what it ignores; the column space is what it can produce; the left null space is what it cannot.
The rank appears everywhere in this picture. The row space and column space always have the same dimension: both equal the rank. This must be true because the matrix maps the row space onto the column space without crushing anything (the crushing happens only in the null space).The singular value decomposition, which we develop in a later post, finds orthonormal bases for the row space and column space such that the matrix maps one to the other by pure scaling. Each scale factor is a singular value. The number of nonzero singular values equals the rank.
For PSID, the four-subspace picture shows up directly. The cross-covariance between neural activity and behavior has a row space that identifies the behaviorally relevant directions in neural space. The null space of the same matrix captures everything the brain does that behavior does not reflect. PSID's two-stage algorithm is, at heart, a procedure for finding these two perpendicular pieces.
Projection and least squares
You record from 100 neurons over 500 time points and want to predict hand velocity from the neural state. You have a system , where is the 500-by-100 data matrix (each row is a time point, each column is a neuron), is the 100-dimensional weight vector you want, and is the 500-dimensional vector of velocity measurements.
You have 500 equations and 100 unknowns. In general, no exact solution exists: there is no that satisfies all 500 equations. The target does not lie in the column space of . You are asking the matrix to produce something outside its repertoire.
What do you do? You find the closest point in the column space. You project onto the column space of , and solve for the that produces that projection.
Think about what projection means geometrically. You have a target point floating somewhere in the 500-dimensional output space. The column space of is a 100-dimensional subspace within that space (assuming the columns are independent). The projection is the point in the column space that is closest to . The residual, the vector from the projection to , is perpendicular to the column space.
If the subspace is spanned by orthonormal columns , the projection formula is one we have seen before, from the basis post:
Two steps. computes dot products, giving the coordinates of the projection in the subspace. Then reconstructs the projected vector in the full space. The matrix is a projection matrix. Apply it twice and nothing changes: . Once you are in the subspace, projecting again leaves you there.
When the columns of are not orthonormal (they almost never are), the formula adjusts to account for the internal geometry:
This is the least-squares solution. Where does the formula come from? One geometric fact: the residual of the best approximation is perpendicular to the column space. Perpendicular to every column means . Expand: . These are the normal equations. If is invertible, solve for and the formula drops out. The entire derivation was perpendicularity.
And now something connects. Look at the structure: is the pseudoinverse of . The projection of onto the column space is .Compare with the orthonormal case: . When has orthonormal columns, , so the formula collapses to . Same formula, no correction needed. This is the payoff of orthonormality, again.
Two ideas from different posts turned out to be the same operation. Least-squares fitting, which seemed like an optimization problem (minimize squared error), is also projection onto the column space, which is a geometric operation (find the nearest point). The formula is the same. This is not a coincidence. The residual of the least- squares fit, , is perpendicular to the column space. Perpendicularity is what makes the approximation closest. Geometry and optimization are saying the same thing in different languages.The distinction between orthogonal and oblique projection matters for some neural data methods. PSID uses an oblique projection to separate behaviorally relevant and irrelevant subspaces, which need not be perpendicular. Van Overschee and De Moor [9] develop the theory of oblique projections for subspace identification, where they are essential for separating past and future information in time-series data.
What comes next
We now have a precise language for what a matrix does to a vector space. It reads the row-space component of the input, maps it to the column space, and ignores the rest. The rank tells you how many dimensions survive. The null space tells you what gets destroyed. When the target lies outside the column space, projection gives you the best approximation.
Projection chooses the nearest point in a fixed subspace. But we have not said how to choose the subspace itself. Which 10-dimensional subspace of a 100-dimensional neuron space should you project onto? The answer depends on the question. If you want to preserve variance, you want the subspace where the data spread out the most. If you want behavioral relevance, you want the subspace most predictive of a target variable.
Both questions lead to eigendecomposition. The directions of maximum variance turn out to be the eigenvectors of the covariance matrix. The directions of maximum behavioral relevance turn out to come from the eigenvectors of a cross-covariance matrix. In the next post, we will see what eigenvectors are, why they are the natural coordinates for symmetric matrices, and why every covariance matrix has a clean eigendecomposition that leads directly to PCA.
References
- Strang, G. Introduction to Linear Algebra, 6th ed. Wellesley-Cambridge Press, 2023.
- 3Blue1Brown. "Essence of Linear Algebra" video series, 2016.
- Churchland, M. M., Cunningham, J. P., Kaufman, M. T., et al. "Neural population dynamics during reaching," Nature, vol. 487, pp. 51-56, 2012.
- Cunningham, J. P. and Yu, B. M. "Dimensionality reduction for large-scale neural recordings," Nature Neuroscience, vol. 17, pp. 1500-1509, 2014.
- Axler, S. Linear Algebra Done Right, 4th ed. Springer, 2024.
- Strang, G. "The fundamental theorem of linear algebra," The American Mathematical Monthly, vol. 100, no. 9, pp. 848-855, 1993.
- Safaie, M., Chang, J. C., Park, J., et al. "Preserved neural dynamics across animals performing similar behaviour," Nature, vol. 623, pp. 765-771, 2023.
- Kaufman, M. T., Churchland, M. M., Ryu, S. I., and Shenoy, K. V. "Cortical activity in the null space: permitting preparation without movement," Nature Neuroscience, vol. 17, pp. 440-448, 2014.
- Van Overschee, P. and De Moor, B. Subspace Identification for Linear Systems. Kluwer Academic Publishers, 1996.