Linear Algebra for Machine Learning

My complete study notes and geometric intuition from Imperial College London's Mathematics for Machine Learning: Linear Algebra course - from vectors and projections to basis transformations and eigen vectors.

October 18, 202628 min read
Linear Algebra for Machine Learning

Part I - Foundations

1.1 What is a Vector, Really?

In programming, a vector is usually treated as a simple 1D array of numbers. Whereas in linear algebra, a vector is a geometric object in space with both magnitude and direction (or equivalently, a point in space relative to an origin).

To describe that geometric arrow using numbers, we need a coordinate system, which is defined by a set of reference vectors called a basis. The basis vectors define the fundamental directions and step sizes of our grid, while the numbers inside our vector simply tell us how many steps to take along each basis vector.

For example, in the standard 2D Cartesian grid where our basis vectors are i^=[10]\hat{i} = \begin{bmatrix} 1 \\ 0 \end{bmatrix} and j^=[01]\hat{j} = \begin{bmatrix} 0 \\ 1 \end{bmatrix}, writing a coordinate vector as v=[42]\mathbf{v} = \begin{bmatrix} 4 \\ 2 \end{bmatrix} is shorthand for:

v=4[10]+2[01]\mathbf{v} = 4\begin{bmatrix} 1 \\ 0 \end{bmatrix} + 2\begin{bmatrix} 0 \\ 1 \end{bmatrix}

What happens if we switch to a new coordinate system where each unit step on the axes is twice as long i.e. b1=[20]\mathbf{b}_1 = \begin{bmatrix} 2 \\ 0 \end{bmatrix} and b2=[02]\mathbf{b}_2 = \begin{bmatrix} 0 \\ 2 \end{bmatrix} ?

The underlying geometric arrow in space does not change in direction or physical length at all. However, its coordinate representation changes to [21]\begin{bmatrix} 2 \\ 1 \end{bmatrix}, because 1 step along our new axes covers 2 units of magnitude:

v=2[20]+1[02]=[42]\mathbf{v} = 2\begin{bmatrix} 2 \\ 0 \end{bmatrix} + 1\begin{bmatrix} 0 \\ 2 \end{bmatrix} = \begin{bmatrix} 4 \\ 2 \end{bmatrix}

Vector vs Coordinates

A vector is the underlying geometric object in space. The list of numbers we write down is merely its coordinate representation relative to a chosen basis. Change the basis, and the coordinates change even though the vector itself stays the same.

1.2 Scalars, Vectors, Matrices and Tensors

Before diving into operations, we should know the following terminology:

  • Scalar (x∈Rx \in \mathbb{R}): A single real number (like x=3.5x = 3.5). It has magnitude but no direction (00-dimensional).

  • Vector (x∈Rn\mathbf{x} \in \mathbb{R}^n): A 1D ordered collection of nn scalars, written by default as a column vector: x=[x1x2⋮xn]\mathbf{x} = \begin{bmatrix} x_1 \\ x_2 \\ \vdots \\ x_n \end{bmatrix}

  • Matrix (A∈Rm×nA \in \mathbb{R}^{m \times n}): A 2D rectangular grid of numbers with mm rows and nn columns. An individual entry at row ii, column jj is written as AijA_{ij} or aija_{ij}.


Part II - Operations & Their Meaning

We can understand every vector and matrix operation through two complementary lenses: data accounting (algebraic) and movements in space (geometric).

2.1 Vector Addition, Subtraction and Scalar Multiplication

Vector Addition (u+v\mathbf{u} + \mathbf{v})

Algebraically, adding two vectors means adding their matching components. Imagine a 2D vector as a receipt tracking two quantities: [applesdollars spent]\begin{bmatrix} \text{apples} \\ \text{dollars spent} \end{bmatrix}.

  • On your first trip to a fruit stand, you buy 2 apples for $1: u=[21]\mathbf{u} = \begin{bmatrix} 2 \\ 1 \end{bmatrix}.
  • On a second trip to a wholesale stall, you buy 6 apples for $2: v=[62]\mathbf{v} = \begin{bmatrix} 6 \\ 2 \end{bmatrix}.

To find your combined haul and total spend, you add apples to apples and dollars to dollars:

u+v=[21]+[62]=[2+61+2]=[83]\mathbf{u} + \mathbf{v} = \begin{bmatrix} 2 \\ 1 \end{bmatrix} + \begin{bmatrix} 6 \\ 2 \end{bmatrix} = \begin{bmatrix} 2 + 6 \\ 1 + 2 \end{bmatrix} = \begin{bmatrix} 8 \\ 3 \end{bmatrix}

Geometrically, if we plot Apples on the horizontal axis and Dollars on the vertical axis, this is the tip-to-tail rule: start at the origin (0,0)(0,0), walk along arrow u\mathbf{u} to (2,1)(2,1), and then place the tail of arrow v\mathbf{v} at the arrowhead of u\mathbf{u}. Drawing a straight line from the origin to the final arrowhead lands us at (8,3)(8,3).

Scalar Multiplication (cuc\mathbf{u})

Multiplying a vector by a scalar c∈Rc \in \mathbb{R} scales every component proportionally.

Using our first receipt u=[21]\mathbf{u} = \begin{bmatrix} 2 \\ 1 \end{bmatrix} (2 apples for $1), scaling linearly means the rate stays constant:

  • If I hand you $3 instead of $1 (c=3c = 3), you get 3[21]=[63]3\begin{bmatrix} 2 \\ 1 \end{bmatrix} = \begin{bmatrix} 6 \\ 3 \end{bmatrix} (6 apples for $3).
  • If I hand you $1.50 (c=1.5c = 1.5), you get 1.5[21]=[31.5]1.5\begin{bmatrix} 2 \\ 1 \end{bmatrix} = \begin{bmatrix} 3 \\ 1.5 \end{bmatrix} (3 apples for $1.50).

Geometrically, scalar multiplication stretches or shrinks the vector along the exact same straight line passing through the origin:

  • ∣c∣>1\vert{}c\vert{} > 1 stretches the arrow.
  • 0<∣c∣<10 < \vert{}c\vert{} < 1 shrinks the arrow.
  • c<0c < 0 flips the arrow's direction by 180∘180^\circ (like returning the apples for a refund).

Vector Subtraction (u−v\mathbf{u} - \mathbf{v})

Subtraction is simply adding the opposite vector: u−v=u+(−1)v\mathbf{u} - \mathbf{v} = \mathbf{u} + (-1)\mathbf{v}.

Geometrically, there are two ways to visualize u−v\mathbf{u} - \mathbf{v}:

  1. Flip and add tip-to-tail: Reverse the direction of v\mathbf{v} and attach its tail to the tip of u\mathbf{u}.
  2. Tip-to-tip displacement: Draw both u\mathbf{u} and v\mathbf{v} starting from the origin. The vector u−v\mathbf{u} - \mathbf{v} is the arrow starting at the tip of v\mathbf{v} and pointing straight to the tip of u\mathbf{u} (because v+(u−v)=u\mathbf{v} + (\mathbf{u} - \mathbf{v}) = \mathbf{u}).

2.2 Modulus (Length) and the Dot Product

Modulus (Vector Length)

The modulus of a vector, written as ∥u∥\|\mathbf{u}\| or ∣u∣|\mathbf{u}|, is the straight-line distance from the origin to the vector's tip. It captures pure magnitude and ignores direction.

By the Pythagorean theorem in nn dimensions:

∥u∥=u12+u22+⋯+un2\left\|\mathbf{u}\right\| = \sqrt{u_1^2 + u_2^2 + \dots + u_n^2}

Because each component is squared, negative signs vanish meaning u\mathbf{u} and −u-\mathbf{u} have the exact same modulus.

The Dot Product (u⋅v\mathbf{u} \cdot \mathbf{v})

The dot product takes two vectors of the same dimension and collapses them into a single scalar.

Algebraically, we multiply matching coordinates and sum them up:

u⋅v=∑i=1nuivi=u1v1+u2v2+⋯+unvn\mathbf{u} \cdot \mathbf{v} = \sum_{i=1}^{n} u_i v_i = u_1v_1 + u_2v_2 + \dots + u_nv_n

Analogy: Suppose q=[43]\mathbf{q} = \begin{bmatrix} 4 \\ 3 \end{bmatrix} contains the quantities of apples and oranges in your bag (4 apples, 3 oranges), and p=[25]\mathbf{p} = \begin{bmatrix} 2 \\ 5 \end{bmatrix} contains the unit prices ($2 per apple, $5 per orange). Dotting them together computes your total bill:

q⋅p=(4×2)+(3×5)=8+15=23\mathbf{q} \cdot \mathbf{p} = (4 \times 2) + (3 \times 5) = 8 + 15 = 23

Because lengths ∥u∥\|\mathbf{u}\| and ∥v∥\|\mathbf{v}\| are always positive, the sign of the dot product is controlled entirely by cos⁡θ\cos\theta:

  • u⋅v>0\mathbf{u} \cdot \mathbf{v} > 0 (θ\theta is less than 90∘90^\circ): They point in generally the same direction.
  • u⋅v=0\mathbf{u} \cdot \mathbf{v} = 0 (θ=90∘\theta = 90^\circ): The vectors are orthogonal (perpendicular).
  • u⋅v<0\mathbf{u} \cdot \mathbf{v} < 0 (θ\theta is greater than 90∘90^\circ): They point in opposing directions.

2.3 Scalar and Vector Projections

Imagine shining a flashlight directly perpendicular to vector a\mathbf{a}. Vector b\mathbf{b} will cast a shadow onto the line of a\mathbf{a}. Finding that shadow is called projection.

ray prependicular to aabs

1. Scalar Projection (Length of the Shadow)

From basic right-triangle trigonometry, if θ\theta is the angle between a\mathbf{a} and b\mathbf{b}, the signed length ss of the shadow of b\mathbf{b} along a\mathbf{a} is:

s=∥b∥cos⁡θs = \|\mathbf{b}\| \cos\theta

Since we know a⋅b=∥a∥∥b∥cos⁡θ\mathbf{a} \cdot \mathbf{b} = \|\mathbf{a}\|\|\mathbf{b}\|\cos\theta, we can substitute cos⁡θ=a⋅b∥a∥∥b∥\cos\theta = \frac{\mathbf{a} \cdot \mathbf{b}}{\|\mathbf{a}\|\|\mathbf{b}\|} to eliminate the angle θ\theta completely:

compa(b)=∥b∥(a⋅b∥a∥∥b∥)=a⋅b∥a∥\text{comp}_{\mathbf{a}}(\mathbf{b}) = \|\mathbf{b}\| \left(\frac{\mathbf{a} \cdot \mathbf{b}}{\|\mathbf{a}\|\|\mathbf{b}\|}\right) = \frac{\mathbf{a} \cdot \mathbf{b}}{\|\mathbf{a}\|}

2. Vector Projection (The Shadow as an Arrow)

The scalar projection gives us a number (how long the shadow is). To turn that length into an actual vector pointing in the direction of a\mathbf{a}, we multiply the scalar length by the unit vector in the direction of a\mathbf{a} (which is a^=a∥a∥\hat{\mathbf{a}} = \frac{\mathbf{a}}{\|\mathbf{a}\|}):

proja(b)=(a⋅b∥a∥)a∥a∥=(a⋅b∥a∥2)a=(a⋅ba⋅a)a\text{proj}_{\mathbf{a}}(\mathbf{b}) = \left(\frac{\mathbf{a} \cdot \mathbf{b}}{\|\mathbf{a}\|}\right) \frac{\mathbf{a}}{\|\mathbf{a}\|} = \left(\frac{\mathbf{a} \cdot \mathbf{b}}{\|\mathbf{a}\|^2}\right)\mathbf{a} = \left(\frac{\mathbf{a} \cdot \mathbf{b}}{\mathbf{a} \cdot \mathbf{a}}\right)\mathbf{a}

Notice that the fraction a⋅ba⋅a\frac{\mathbf{a} \cdot \mathbf{b}}{\mathbf{a} \cdot \mathbf{a}} is just a single scalar that scales vector a\mathbf{a}.


2.4 Matrix Multiplication, Transpose, Identity and Inverses

Matrix Multiplication

Earlier, we dotted a quantity vector q=[43]\mathbf{q} = \begin{bmatrix} 4 & 3 \end{bmatrix} with a price vector p=[25]\mathbf{p} = \begin{bmatrix} 2 \\ 5 \end{bmatrix} to get a single bill.

Now suppose two people go shopping for apples and oranges, and they want to compare their total bills across two different stores (Store 1 and Store 2):

  • Quantities Matrix (QQ): Each row is a person's shopping list [applesoranges]\begin{bmatrix} \text{apples} & \text{oranges} \end{bmatrix}. Q=[4326]←Person A←Person BQ = \begin{bmatrix} 4 & 3 \\ 2 & 6 \end{bmatrix} \begin{matrix} \leftarrow \text{Person A} \\ \leftarrow \text{Person B} \end{matrix}
  • Prices Matrix (PP): Each column is a store's price list [apple priceorange price]\begin{bmatrix} \text{apple price} \\ \text{orange price} \end{bmatrix}. P=[2354](Col 1: Store 1, Col 2: Store 2)P = \begin{bmatrix} 2 & 3 \\ 5 & 4 \end{bmatrix} \begin{matrix} \text{(Col 1: Store 1, Col 2: Store 2)} \end{matrix}

To find every person's bill at every store, we compute QPQP by taking the dot product of each row of QQ with each column of PP:

QP=[4326][2354]=[(4⋅2+3⋅5)(4⋅3+3⋅4)(2⋅2+6⋅5)(2⋅3+6⋅4)]=[23243430]QP = \begin{bmatrix} 4 & 3 \\ 2 & 6 \end{bmatrix} \begin{bmatrix} 2 & 3 \\ 5 & 4 \end{bmatrix} = \begin{bmatrix} (4\cdot 2 + 3\cdot 5) & (4\cdot 3 + 3\cdot 4) \\ (2\cdot 2 + 6\cdot 5) & (2\cdot 3 + 6\cdot 4) \end{bmatrix} = \begin{bmatrix} 23 & 24 \\ 34 & 30 \end{bmatrix}

Dimensional Compatibility & Non-Commutativity

To multiply matrix AA (m×nm \times n) by matrix BB (n×pn \times p), the inner dimensions must match (n=nn = n), because we are dotting rows of length nn with columns of length nn. The output has the outer dimensions (m×pm \times p). Furthermore, order matters i.e. AB≠BAAB \not= BA.

Transpose (ATA^T)

The transpose of a matrix AA, written ATA^T, flips the matrix over its main diagonal - turning rows into columns and columns into rows: (AT)ij=Aji(A^T)_{ij} = A_{ji}.

  • It also connects dot products to matrix multiplication: for column vectors a,b∈Rn\mathbf{a}, \mathbf{b} \in \mathbb{R}^n, turning a\mathbf{a} into a row vector aT\mathbf{a}^T lets us write the dot product as a⋅b=aTb\mathbf{a} \cdot \mathbf{b} = \mathbf{a}^T \mathbf{b}.
  • Reversal rule: When transposing a product, the order reverses: (AB)T=BTAT(AB)^T = B^T A^T.

Identity Matrix (II) and Matrix Inverse (A−1A^{-1})

  • Identity Matrix (InI_n): A square n×nn \times n matrix with 11s on the main diagonal and 00s everywhere else. It acts like the number 11 in multiplication: for any vector x\mathbf{x}, Ix=xI\mathbf{x} = \mathbf{x} (it leaves space untouched). I2=[1001]I_2 = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix}
  • Inverse Matrix (A−1A^{-1}): If a matrix AA transforms vector x\mathbf{x} into y\mathbf{y} (Ax=yA\mathbf{x} = \mathbf{y}), the inverse matrix A−1A^{-1} is the "undo button" that takes y\mathbf{y} back to x\mathbf{x}: A−1A=AA−1=IA^{-1}A = AA^{-1} = I Not all matrices have an inverse! As we will see in Part IV, if a matrix squashes 2D space flat onto a 1D line, you cannot "un-squash" it uniquely.

Part III - Vector Spaces, Basis and Transformations

3.1 Linear Combinations and Span

Given a set of vectors {v1,v2,…,vk}\{\mathbf{v}_1, \mathbf{v}_2, \dots, \mathbf{v}_k\}, any expression where we scale each vector by a scalar and add them together is called a linear combination:

w=c1v1+c2v2+⋯+ckvk\mathbf{w} = c_1\mathbf{v}_1 + c_2\mathbf{v}_2 + \dots + c_k\mathbf{v}_k

The span of those vectors is the set of all possible vectors you can reach by trying every possible combination of scalars c1,…,ck∈Rc_1, \dots, c_k \in \mathbb{R}:

  • The span of a single non-zero vector in R3\mathbb{R}^3 is a straight line through the origin.
  • The span of two non-collinear vectors in R3\mathbb{R}^3 is a flat 2D plane (a subspace) slicing through the origin.
  • The span of three vectors that don't lie on the same plane fills the entire 3D space R3\mathbb{R}^3.

3.2 Linear Independence vs Dependence

Suppose you are in 2D space with two vectors: v1=[10]\mathbf{v}_1 = \begin{bmatrix} 1 \\ 0 \end{bmatrix} and v2=[01]\mathbf{v}_2 = \begin{bmatrix} 0 \\ 1 \end{bmatrix}. With these two arrows, you can already reach every single point in R2\mathbb{R}^2.

What if someone hands you a third vector v3=[32]\mathbf{v}_3 = \begin{bmatrix} 3 \\ 2 \end{bmatrix}? Does v3\mathbf{v}_3 allow you to reach any new territory? No, because you could already build v3\mathbf{v}_3 using v1\mathbf{v}_1 and v2\mathbf{v}_2:

v3=3v1+2v2\mathbf{v}_3 = 3\mathbf{v}_1 + 2\mathbf{v}_2

When one vector in a set can be written as a linear combination of the others, the set is linearly dependent. It contains redundant information.

Formally, a set of vectors {v1,…,vk}\{\mathbf{v}_1, \dots, \mathbf{v}_k\} is linearly independent if no vector in the set can be built from the others or equivalently, the only way to combine them to get the zero vector is to set every weight to zero:

c1v1+c2v2+⋯+ckvk=0  ⟺  c1=c2=⋯=ck=0c_1\mathbf{v}_1 + c_2\mathbf{v}_2 + \dots + c_k\mathbf{v}_k = \mathbf{0} \iff c_1 = c_2 = \dots = c_k = 0

3.3 Basis, Dimension and Matrices as Transformations

A basis of a vector space is a set of vectors that satisfies two strict conditions simultaneously:

  1. They span the space (enough vectors to reach everywhere).
  2. They are linearly independent (no redundant vectors).

The number of vectors in a basis is the dimension of the space.

Matrices as Linear Transformations

Why do we care so much about basis vectors? Because multiplying a matrix AA by a vector x\mathbf{x} is actually a change of basis / space transformation.

Consider multiplying a 2×22 \times 2 matrix A=[abcd]A = \begin{bmatrix} a & b \\ c & d \end{bmatrix} by our standard basis vectors i^=[10]\hat{i} = \begin{bmatrix} 1 \\ 0 \end{bmatrix} and j^=[01]\hat{j} = \begin{bmatrix} 0 \\ 1 \end{bmatrix}:

Ai^=[abcd][10]=[ac](Column 1 of A)A\hat{i} = \begin{bmatrix} a & b \\ c & d \end{bmatrix}\begin{bmatrix} 1 \\ 0 \end{bmatrix} = \begin{bmatrix} a \\ c \end{bmatrix} \quad (\text{Column 1 of } A)

Aj^=[abcd][01]=[bd](Column 2 of A)A\hat{j} = \begin{bmatrix} a & b \\ c & d \end{bmatrix}\begin{bmatrix} 0 \\ 1 \end{bmatrix} = \begin{bmatrix} b \\ d \end{bmatrix} \quad (\text{Column 2 of } A)

The Golden Rule of Reading Matrices

The columns of any transformation matrix AA literally tell you where the original basis vectors i^\hat{i} and j^\hat{j} land after the transformation!

Consequently, for any vector x=[x1x2]=x1i^+x2j^\mathbf{x} = \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} = x_1\hat{i} + x_2\hat{j}, multiplying AxA\mathbf{x} just takes that exact same recipe (x1x_1 steps of the first column, plus x2x_2 steps of the second column) using the new landed basis vectors:

Ax=x1[ac]+x2[bd]A\mathbf{x} = x_1 \begin{bmatrix} a \\ c \end{bmatrix} + x_2 \begin{bmatrix} b \\ d \end{bmatrix}

Common 2×22 \times 2 geometric transformations include:

  • Scaling by kk along xx: [k001]\begin{bmatrix} k & 0 \\ 0 & 1 \end{bmatrix}
  • Horizontal Shear: [1k01]\begin{bmatrix} 1 & k \\ 0 & 1 \end{bmatrix} (i^\hat{i} stays put, j^\hat{j} tilts to [k1]\begin{bmatrix} k \\ 1 \end{bmatrix})
  • Counterclockwise Rotation by angle θ\theta: [cos⁡θ−sin⁡θsin⁡θcos⁡θ]\begin{bmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{bmatrix}

3.4 Changing Basis (B−1B^{-1})

Suppose a friend uses a custom coordinate grid with basis vectors b1=[31]\mathbf{b}_1 = \begin{bmatrix} 3 \\ 1 \end{bmatrix} and b2=[12]\mathbf{b}_2 = \begin{bmatrix} 1 \\ 2 \end{bmatrix} (measured in our standard grid). We pack their basis vectors into the columns of a basis matrix BB:

B=[3112]B = \begin{bmatrix} 3 & 1 \\ 1 & 2 \end{bmatrix}

  1. From their grid to our standard grid: If a vector has coordinates [v]B=[21][\mathbf{v}]_B = \begin{bmatrix} 2 \\ 1 \end{bmatrix} in their grid, what is it in our standard grid? It's 2b1+1b22\mathbf{b}_1 + 1\mathbf{b}_2, which is simply matrix multiplication by BB:
vstd=B[v]B=[3112][21]=[74]\mathbf{v}_{\text{std}} = B [\mathbf{v}]_B = \begin{bmatrix} 3 & 1 \\ 1 & 2 \end{bmatrix}\begin{bmatrix} 2 \\ 1 \end{bmatrix} = \begin{bmatrix} 7 \\ 4 \end{bmatrix}
  1. From our standard grid to their grid: What if we have vstd=[74]\mathbf{v}_{\text{std}} = \begin{bmatrix} 7 \\ 4 \end{bmatrix} in standard coordinates and want to find its coordinates in their basis BB? We multiply by the inverse B−1B^{-1} to run the translation backward:
[v]B=B−1vstd[\mathbf{v}]_B = B^{-1} \mathbf{v}_{\text{std}}

3.5 Orthogonal Matrices & The Gram-Schmidt Process

Changing basis with B−1B^{-1} requires computing a matrix inverse, which is computationally expensive when dimensions get huge.

Is there a "dream basis" where we never have to compute a messy inverse? Yes: an orthonormal basis, where every basis vector qi\mathbf{q}_i has unit length (∥qi∥=1\Vert{}\mathbf{q}_i\Vert{} = 1) and is mutually orthogonal (perpendicular) to every other basis vector (qi⋅qj=0\mathbf{q}_i \cdot \mathbf{q}_j = 0 for i≠ji \neq j).

When we pack orthonormal basis vectors into the columns of a matrix QQ, we get an orthogonal matrix. Look what happens when we multiply QTQQ^T Q:

  • Diagonal entries are qiTqi=qi⋅qi=1\mathbf{q}_i^T \mathbf{q}_i = \mathbf{q}_i \cdot \mathbf{q}_i = 1.
  • Off-diagonal entries are qiTqj=qi⋅qj=0\mathbf{q}_i^T \mathbf{q}_j = \mathbf{q}_i \cdot \mathbf{q}_j = 0.

Therefore:

QTQ=I  ⟹  Q−1=QTQ^T Q = I \implies Q^{-1} = Q^T

For an orthogonal matrix, inverting it is as effortless as taking its transpose! Geometrically, orthogonal matrices represent pure rigid rotations and reflections i.e. they preserve all vector lengths (∥Qx∥=∥x∥\Vert{}Q\mathbf{x}\Vert{} = \Vert{}\mathbf{x}\Vert{}) and angles.

The Gram-Schmidt Process

If we are given a set of linearly independent vectors {v1,v2,v3}\{\mathbf{v}_1, \mathbf{v}_2, \mathbf{v}_3\} that are tilted at awkward angles, the Gram-Schmidt process constructs a clean orthonormal basis {e1,e2,e3}\{\mathbf{e}_1, \mathbf{e}_2, \mathbf{e}_3\} one vector at a time using projections:

  1. First vector: Just normalize v1\mathbf{v}_1 to unit length: u1=v1,e1=u1∥u1∥\mathbf{u}_1 = \mathbf{v}_1, \quad \mathbf{e}_1 = \frac{\mathbf{u}_1}{\Vert{}\mathbf{u}_1\Vert{}}
  2. Second vector: Take v2\mathbf{v}_2 and subtract off its shadow (projection) onto e1\mathbf{e}_1. Whatever is left over is guaranteed to be strictly perpendicular to e1\mathbf{e}_1! Then normalize it: u2=v2−(v2⋅e1)e1,e2=u2∥u2∥\mathbf{u}_2 = \mathbf{v}_2 - (\mathbf{v}_2 \cdot \mathbf{e}_1)\mathbf{e}_1, \quad \mathbf{e}_2 = \frac{\mathbf{u}_2}{\Vert{}\mathbf{u}_2\Vert{}}
  3. Third vector: Take v3\mathbf{v}_3 and subtract off its shadows onto both e1\mathbf{e}_1 and e2\mathbf{e}_2, then normalize:
u3=v3−(v3⋅e1)e1−(v3⋅e2)e2,e3=u3∥u3∥\mathbf{u}_3 = \mathbf{v}_3 - (\mathbf{v}_3 \cdot \mathbf{e}_1)\mathbf{e}_1 - (\mathbf{v}_3 \cdot \mathbf{e}_2)\mathbf{e}_2, \quad \mathbf{e}_3 = \frac{\mathbf{u}_3}{\Vert{}\mathbf{u}_3\Vert{}}

Part IV - Solving Linear Systems

4.1 Two Ways to Read Ax=bA\mathbf{x} = \mathbf{b}

Consider a system of linear equations:

2x1+x2=5x1+3x2=5  ⟺  [2113][x1x2]=[55]\begin{aligned} 2x_1 + x_2 &= 5 \\ x_1 + 3x_2 &= 5 \end{aligned} \iff \begin{bmatrix} 2 & 1 \\ 1 & 3 \end{bmatrix} \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} = \begin{bmatrix} 5 \\ 5 \end{bmatrix}

We can interpret Ax=bA\mathbf{x} = \mathbf{b} in two ways:

  1. The Row Picture (Intersecting Lines/Planes): Each row is the equation of a line (in 2D) or a plane (in 3D). Solving the system means finding the intersection point (x1,x2)(x_1, x_2) that satisfies all equations at once.
  2. The Column Picture (Linear Combination of Columns): We are looking for the weights x1,x2x_1, x_2 to combine the column vectors of AA to land on target b\mathbf{b}:
x1[21]+x2[13]=[55]x_1 \begin{bmatrix} 2 \\ 1 \end{bmatrix} + x_2 \begin{bmatrix} 1 \\ 3 \end{bmatrix} = \begin{bmatrix} 5 \\ 5 \end{bmatrix}

Here, x1=2,x2=1x_1 = 2, x_2 = 1 works!

4.2 Gaussian Elimination & Row Echelon Form

For larger systems, we solve Ax=bA\mathbf{x} = \mathbf{b} systematically using Gaussian Elimination. We write an augmented matrix [A∣b][A \mid \mathbf{b}] and apply valid row operations (swapping rows, scaling a row, or subtracting a multiple of one row from another) until the matrix is in Row Echelon Form (staircase of zeros below the diagonal).

Let's solve our 2×22 \times 2 system step by step:

[215135]\left[\begin{array}{cc|c} 2 & 1 & 5 \\ 1 & 3 & 5 \end{array}\right]
  1. Subtract 12×Row 1\frac{1}{2} \times \text{Row 1} from Row 2\text{Row 2} to eliminate the bottom-left entry: [21502.52.5]\left[\begin{array}{cc|c} 2 & 1 & 5 \\ 0 & 2.5 & 2.5 \end{array}\right]
  2. Divide Row 2\text{Row 2} by 2.52.5 to get a leading 11 (pivot): [215011]  ⟹  x2=1\left[\begin{array}{cc|c} 2 & 1 & 5 \\ 0 & 1 & 1 \end{array}\right] \implies x_2 = 1
  3. Back-substitute x2=1x_2 = 1 into Row 1 (2x1+1=5  ⟹  x1=22x_1 + 1 = 5 \implies x_1 = 2).

(If we continue eliminating entries above the diagonal until the left side becomes the Identity matrix II, we get Reduced Row Echelon Form. Performing the exact same steps on [A∣I][A \mid I] until it becomes [I∣A−1][I \mid A^{-1}] is how we compute the inverse matrix A−1A^{-1})

4.3 Determinants, Rank and Existence of Solutions

What is the Determinant (det⁡(A)\det(A) or ∣A∣\vert{}A\vert{})?

Geometrically, the determinant of a transformation matrix AA measures the factor by which the transformation scales area (in 2D) or volume (in 3D).

  • Start with a 1×11 \times 1 unit square formed by i^=[10]\hat{i} = \begin{bmatrix} 1 \\ 0 \end{bmatrix} and j^=[01]\hat{j} = \begin{bmatrix} 0 \\ 1 \end{bmatrix} (Area =1= 1).
  • After transforming by A=[abcd]A = \begin{bmatrix} a & b \\ c & d \end{bmatrix}, that unit square becomes a parallelogram spanned by [ac]\begin{bmatrix} a \\ c \end{bmatrix} and [bd]\begin{bmatrix} b \\ d \end{bmatrix}, whose signed area is: det⁡(A)=ad−bc\det(A) = ad - bc
  • If det⁡(A)<0\det(A) < 0, space was flipped inside-out (like a mirror reflection reversing the orientation of the axes).
  • Crucial Case (det⁡(A)=0\det(A) = 0): If the area of the transformed parallelogram is zero, it means the two columns of AA are collinear (linearly dependent)! The transformation has squashed 2D space flat onto a 1D line (or a single point). Once space is flattened, information is permanently lost i.e you cannot reverse the transformation. Such a matrix is called singular (non-invertible).

Rank and Solution Cases

The rank of a matrix is the number of linearly independent columns (or rows) which equals the number of non-zero pivot rows after Gaussian elimination. Geometrically, rank is the true dimension of the output space after transformation.

For an n×nn \times n system Ax=bA\mathbf{x} = \mathbf{b}:

  1. Full Rank (rank(A)=n\text{rank}(A) = n, det⁡(A)≠0\det(A) \neq 0): The columns span the entire space. There is exactly one unique solution x=A−1b\mathbf{x} = A^{-1}\mathbf{b} for every target b\mathbf{b}.
  2. Rank Deficient (rank(A)<n\text{rank}(A) < n, det⁡(A)=0\det(A) = 0): Space collapses onto a lower-dimensional subspace (like a plane collapsing into a line):
    • No solution (Inconsistent): Target b\mathbf{b} lies outside the collapsed line/plane that AA can reach.
    • Infinitely many solutions: Target b\mathbf{b} happens to lie on the collapsed line/plane, so an entire line or plane of input vectors all get squashed onto b\mathbf{b}.

Part V - Eigenvalues and Eigenvectors

5.1 The Eigenvalue Equation & Geometric Meaning

When you apply a linear transformation matrix AA to space, almost every vector gets knocked off its original line of action changing both its direction and its length.

However, certain special vectors refuse to get knocked off their line. When AA multiplies one of these special vectors v\mathbf{v}, the output AvA\mathbf{v} points along the exact same line as v\mathbf{v} it only gets stretched, shrunk or flipped by a scalar factor λ\lambda:

Av=λvA\mathbf{v} = \lambda\mathbf{v}

  • v\mathbf{v} (any non-zero vector satisfying this) is called an eigenvector ("characteristic vector").
  • λ\lambda is its corresponding eigenvalue (the scaling factor along that invariant direction).

Geometric Intuition:

  • Pure Scaling along xx and yy: The eigenvectors are simply the xx-axis and yy-axis themselves.
  • Horizontal Shear [1k01]\begin{bmatrix} 1 & k \\ 0 & 1 \end{bmatrix}: Every vector with a vertical component gets tilted sideways. Only vectors lying strictly along the horizontal xx-axis stay on their own line (λ=1\lambda = 1).
  • 3D Rotation: If you spin a globe in 3D space, almost every vector moves to a new direction except vectors lying along the axis of rotation, which stay completely fixed (λ=1\lambda = 1)!

5.2 Deriving the Characteristic Polynomial

How do we algebraically solve Av=λvA\mathbf{v} = \lambda\mathbf{v} when both λ\lambda and v\mathbf{v} are unknown?

  1. First, insert the identity matrix II so we can subtract the right side from the left (since you cannot subtract a scalar λ\lambda directly from a matrix AA, we write λv=λIv\lambda\mathbf{v} = \lambda I \mathbf{v}): Av−λIv=0A\mathbf{v} - \lambda I \mathbf{v} = \mathbf{0}
  2. Factor out v\mathbf{v}: (A−λI)v=0(A - \lambda I)\mathbf{v} = \mathbf{0}
  3. Look closely at (A−λI)v=0(A - \lambda I)\mathbf{v} = \mathbf{0}. Obviously, v=0\mathbf{v} = \mathbf{0} works, but the zero vector has no direction, so we ban v=0\mathbf{v} = \mathbf{0} by definition. For a matrix (A−λI)(A - \lambda I) to squash a non-zero vector v\mathbf{v} onto the origin 0\mathbf{0}, that matrix must collapse space meaning it must be singular!
  4. A matrix is singular if and only if its determinant is zero: det⁡(A−λI)=0\det(A - \lambda I) = 0

This equation, det⁡(A−λI)=0\det(A - \lambda I) = 0, is called the characteristic equation.

Worked Numerical Example

Let's find the eigenvalues and eigenvectors of:

A=[4123]A = \begin{bmatrix} 4 & 1 \\ 2 & 3 \end{bmatrix}

Step 1: Solve det⁡(A−λI)=0\det(A - \lambda I) = 0 for λ\lambda.

A−λI=[4−λ123−λ]A - \lambda I = \begin{bmatrix} 4 - \lambda & 1 \\ 2 & 3 - \lambda \end{bmatrix}

det⁡(A−λI)=(4−λ)(3−λ)−(1)(2)=λ2−7λ+12−2=λ2−7λ+10=0\det(A - \lambda I) = (4 - \lambda)(3 - \lambda) - (1)(2) = \lambda^2 - 7\lambda + 12 - 2 = \lambda^2 - 7\lambda + 10 = 0

Factoring the quadratic:

(λ−5)(λ−2)=0  ⟹  λ1=5,λ2=2(\lambda - 5)(\lambda - 2) = 0 \implies \lambda_1 = 5, \quad \lambda_2 = 2

Trace and Determinant

You can always verify your eigenvalues instantly using two identities:

  1. Sum of eigenvalues == Trace of AA (sum of diagonal entries): λ1+λ2=5+2=7\lambda_1 + \lambda_2 = 5 + 2 = 7, and Tr(A)=4+3=7\text{Tr}(A) = 4 + 3 = 7.
  2. Product of eigenvalues == Determinant of AA: λ1λ2=5×2=10\lambda_1 \lambda_2 = 5 \times 2 = 10 and det⁡(A)=(4)(3)−(1)(2)=10\det(A) = (4)(3) - (1)(2) = 10.

Step 2: Substitute each λ\lambda back into (A−λI)v=0(A - \lambda I)\mathbf{v} = \mathbf{0} to find the eigenvectors.

  • For λ1=5\lambda_1 = 5: [4−5123−5][v1v2]=[−112−2][v1v2]=[00]\begin{bmatrix} 4 - 5 & 1 \\ 2 & 3 - 5 \end{bmatrix}\begin{bmatrix} v_1 \\ v_2 \end{bmatrix} = \begin{bmatrix} -1 & 1 \\ 2 & -2 \end{bmatrix}\begin{bmatrix} v_1 \\ v_2 \end{bmatrix} = \begin{bmatrix} 0 \\ 0 \end{bmatrix} Both rows state that −v1+v2=0  ⟹  v1=v2-v_1 + v_2 = 0 \implies v_1 = v_2. Picking v1=1v_1 = 1 gives our first eigenvector: v1=[11]\mathbf{v}_1 = \begin{bmatrix} 1 \\ 1 \end{bmatrix} (Any non-zero multiple of [11]\begin{bmatrix} 1 \\ 1 \end{bmatrix} lies on the same line and is an equally valid eigenvector).

  • For λ2=2\lambda_2 = 2: [4−2123−2][v1v2]=[2121][v1v2]=[00]\begin{bmatrix} 4 - 2 & 1 \\ 2 & 3 - 2 \end{bmatrix}\begin{bmatrix} v_1 \\ v_2 \end{bmatrix} = \begin{bmatrix} 2 & 1 \\ 2 & 1 \end{bmatrix}\begin{bmatrix} v_1 \\ v_2 \end{bmatrix} = \begin{bmatrix} 0 \\ 0 \end{bmatrix} This states 2v1+v2=0  ⟹  v2=−2v12v_1 + v_2 = 0 \implies v_2 = -2v_1. Picking v1=1v_1 = 1 gives our second eigenvector: v2=[1−2]\mathbf{v}_2 = \begin{bmatrix} 1 \\ -2 \end{bmatrix}


5.3 Diagonalization (A=PDP−1A = PDP^{-1}) and Matrix Powers

Why are eigenvectors the crown jewel of this course? Because if an n×nn \times n matrix AA has nn linearly independent eigenvectors, we can use those eigenvectors as our new coordinate basis!

Let PP be the basis matrix whose columns are the eigenvectors [v1∣v2][\mathbf{v}_1 \mid \mathbf{v}_2], and let DD be the diagonal matrix containing the eigenvalues on the diagonal:

P=[111−2],D=[5002]P = \begin{bmatrix} 1 & 1 \\ 1 & -2 \end{bmatrix}, \quad D = \begin{bmatrix} 5 & 0 \\ 0 & 2 \end{bmatrix}

In the eigenvector basis, the matrix AA doesn't rotate or shear anything it just scales along the axes by λ1\lambda_1 and λ2\lambda_2. Therefore, applying AA is equivalent to:

  1. P−1P^{-1}: Change coordinates from the standard basis into the eigenvector basis.
  2. DD: Scale each coordinate directly by λi\lambda_i.
  3. PP: Convert coordinates back from the eigenvector basis to the standard basis.

Written as an equation, this is Eigendecomposition (Diagonalization):

A=PDP−1A = P D P^{-1}

The Superpower: Computing AkA^k Instantly

Suppose we need to apply transformation AA 100100 times (A100A^{100}) for example, simulating a system over 100100 time steps or running Google's PageRank web-surfer algorithm to steady state. Multiplying a dense matrix 100100 times is slow and messy, but in diagonalized form, the interior P−1PP^{-1}P terms cancel out like dominoes:

A2=(PDP−1)(PDP−1)=PD(P−1P)DP−1=PD2P−1A^2 = (PDP^{-1})(PDP^{-1}) = PD(P^{-1}P)DP^{-1} = PD^2P^{-1}

Ak=PDkP−1=P[λ1k00λ2k]P−1A^k = P D^k P^{-1} = P \begin{bmatrix} \lambda_1^k & 0 \\ 0 & \lambda_2^k \end{bmatrix} P^{-1}

Raising a diagonal matrix DD to the kk-th power simply raises its individual diagonal numbers to the kk-th power!

(Note: When a matrix AA is symmetric (A=ATA = A^T), its eigenvectors are guaranteed to be mutually orthogonal, meaning our eigenvector basis matrix becomes an orthogonal matrix QQ where Q−1=QTQ^{-1} = Q^T, giving A=QDQTA = QDQ^T known as the Spectral Theorem).


5.4 Verifying Everything in Python (NumPy)

Here is a brief, self-contained script verifying our projections, Gram-Schmidt orthogonalization and eigendecomposition from the examples above:

import numpy as np

np.set_printoptions(precision=4, suppress=True)

A = np.array([[4.0, 1.0],
              [2.0, 3.0]])

eigenvalues, P = np.linalg.eig(A)

# Sort descending so the order matches the hand calculation (5, then 2)
order = np.argsort(eigenvalues)[::-1]
eigenvalues, P = eigenvalues[order], P[:, order]

D = np.diag(eigenvalues)
P_inv = np.linalg.inv(P)

print("Eigenvalues:", eigenvalues)  # [5. 2.]
print("A = P D P^-1 holds:", np.allclose(A, P @ D @ P_inv))

# Trace / determinant sanity check
print("Sum of eigenvalues == trace:", np.isclose(eigenvalues.sum(), np.trace(A)))
print("Product of eigenvalues == det:", np.isclose(eigenvalues.prod(), np.linalg.det(A)))

# Compare with hand-computed eigenvectors [1, 1] and [1, -2].
# NumPy normalises to unit length (and may flip sign), so compare directions only.
P_hand = np.array([[1.0, 1.0],
                   [1.0, -2.0]])
for i in range(2):
    v = P_hand[:, i]
    is_eigvec = np.allclose(A @ v, eigenvalues[i] * v)
    same_dir = np.allclose(np.abs(v / np.linalg.norm(v)), np.abs(P[:, i]))
    print(f"Hand eigenvector {v}: A v = lambda v -> {is_eigvec}, same direction as NumPy's -> {same_dir}")

# Fast matrix powers: A^k = P D^k P^-1
k = 5
A_direct = np.linalg.matrix_power(A, k)
A_eigen = P @ np.diag(eigenvalues**k) @ P_inv
print(f"\nDirect A^{k}:\n{A_direct}")
print(f"Eigen-based A^{k}:\n{A_eigen}")
print("Match:", np.allclose(A_direct, A_eigen))

# Special cases
print("\n--- Special cases ---")

# Uniform scaling: every vector is an eigenvector
S = 2 * np.eye(2)
vals, vecs = np.linalg.eig(S)
print("Uniform scaling 2I -> eigenvalues:", vals)  # [2. 2.]

# 90-degree rotation: no real eigenvectors (complex eigenvalues)
R = np.array([[0.0, -1.0],
              [1.0,  0.0]])
vals, _ = np.linalg.eig(R)
print("Rotation 90° -> eigenvalues:", vals)  # [0.+1.j 0.-1.j]

# Shear: repeated eigenvalue, only one eigenvector direction
Sh = np.array([[1.0, 1.0],
               [0.0, 1.0]])
vals, vecs = np.linalg.eig(Sh)
print("Shear -> eigenvalues:", vals)  # [1. 1.]
print("Shear -> eigenvector matrix:\n", vecs)
print("|det(P)| ≈ 0 (columns are parallel, so NOT diagonalizable):",
      abs(np.linalg.det(vecs)) < 1e-10)

# PageRank via the power method
print("\n--- PageRank ---")

# 4 pages A, B, C, D. Column j = where page j sends its "vote".
# A -> B, C, D | B -> C, D | C -> A | D -> A, C
L = np.array([
    [0,   0,   1, 1/2],
    [1/3, 0,   0, 0  ],
    [1/3, 1/2, 0, 1/2],
    [1/3, 1/2, 0, 0  ],
])
print("Columns sum to 1:", np.allclose(L.sum(axis=0), 1))

n = L.shape[0]

# Power method: start with equal rank, repeatedly apply L
r = np.ones(n) / n
for _ in range(100):
    r_next = L @ r
    if np.linalg.norm(r_next - r) < 1e-10:
        break
    r = r_next
print("Power method ranks:", r)

# Same answer as the eigenvector with eigenvalue 1 (normalised to sum to 1)
vals, vecs = np.linalg.eig(L)
idx = np.argmin(np.abs(vals - 1))
r_eig = np.real(vecs[:, idx])
r_eig = r_eig / r_eig.sum()
print("Eigenvector (lambda=1):", r_eig)
print("Match:", np.allclose(r, r_eig, atol=1e-6))

# With damping factor d = 0.85
d = 0.85
M = d * L + (1 - d) / n * np.ones((n, n))
r = np.ones(n) / n
for _ in range(100):
    r = M @ r
print("With damping (d=0.85):", r)
Back to all postsWritten by Harshit Gulati

Built with by Harshit Gulati