Skip to content

Angles and Orthogonality

The inner product doesn’t just measure length — it measures angle. That gives us cosine similarity (how ML compares embeddings) and orthogonality (the “right angle” that underlies PCA, whitening, and rotations). This page turns the inner product into an angle-meter.

A real-life example: document similarity

Represent two documents as vectors of word counts. Their angle tells you how similar they are regardless of length: a short tweet and a long article about the same topic point in nearly the same direction (small angle) even though one vector is much longer. That angle — via its cosine — is the standard “cosine similarity” behind search and recommendation.

The angle between two vectors

For nonzero x,y\mathbf{x}, \mathbf{y}, Cauchy-Schwarz guarantees

1x,yxy1,-1 \le \frac{\langle \mathbf{x}, \mathbf{y}\rangle}{\lVert \mathbf{x}\rVert\,\lVert \mathbf{y}\rVert} \le 1,

so there’s a unique angle ω[0,π]\omega \in [0, \pi] with

cosω=x,yxy.\cos\omega = \frac{\langle \mathbf{x}, \mathbf{y}\rangle}{\lVert \mathbf{x}\rVert\,\lVert \mathbf{y}\rVert}.

The quantity on the right is cosine similarity: +1+1 means same direction, 00 means perpendicular, 1-1 means opposite.

Watch the angle

Rotate the blue vector and watch ω\omega and its cosine. The angle is largest when the vectors oppose, zero when aligned, and the vectors turn orthogonal the instant cosω=0\cos\omega = 0:

sketch Angle and cosine similarity p5.js
A fixed amber vector and a rotating blue vector. The arc shows the angle ω between them; the readout shows cos ω = ⟨x,y⟩/(‖x‖‖y‖). At 90° the cosine is 0 and the vectors are orthogonal.

Orthogonality

Two vectors are orthogonal — written xy\mathbf{x} \perp \mathbf{y} — exactly when

x,y=0.\langle \mathbf{x}, \mathbf{y}\rangle = 0.

If they are also unit length (x=y=1\lVert\mathbf{x}\rVert = \lVert\mathbf{y}\rVert = 1), they are orthonormal. Orthogonality is the generalization of “perpendicular” to any inner product — and the 0\mathbf{0} vector is orthogonal to everything.

Orthogonal matrices

A square matrix AA is orthogonal if its columns are orthonormal, which is equivalent to

AA=I=AAA1=A.A A^\top = I = A^\top A \quad\Longleftrightarrow\quad A^{-1} = A^\top.

The inverse is just the transpose — no elimination needed. Orthogonal matrices are special because they preserve lengths and angles: Ax=x\lVert A\mathbf{x}\rVert = \lVert \mathbf{x}\rVert and the angle between AxA\mathbf{x} and AyA\mathbf{y} equals the angle between x\mathbf{x} and y\mathbf{y}. Geometrically they are rotations (possibly with a flip) — the subject of a later page.

diagram Diagram mermaid

NumPy

angles_orthogonality.py
import numpy as np
 
def angle_deg(x, y):
    cos = (x @ y) / (np.linalg.norm(x) * np.linalg.norm(y))
    return np.degrees(np.arccos(np.clip(cos, -1, 1)))
 
x = np.array([1.0, 1.0])
y = np.array([1.0, 2.0])
print("angle:", round(angle_deg(x, y), 2), "degrees")   # ~18.43
 
# Orthogonal pair
a = np.array([1.0, 0.0])
b = np.array([0.0, 1.0])
print("⟨a, b⟩ =", a @ b, "-> orthogonal:", np.isclose(a @ b, 0))
 
# An orthogonal matrix (45° rotation): Q.T @ Q = I
t = np.pi / 4
Q = np.array([[np.cos(t), -np.sin(t)],
              [np.sin(t),  np.cos(t)]])
print("QᵀQ = I:", np.allclose(Q.T @ Q, np.eye(2)))
print("length preserved:", np.allclose(np.linalg.norm(Q @ x), np.linalg.norm(x)))
angles_orthogonality.py
import numpy as np
 
def angle_deg(x, y):
    cos = (x @ y) / (np.linalg.norm(x) * np.linalg.norm(y))
    return np.degrees(np.arccos(np.clip(cos, -1, 1)))
 
x = np.array([1.0, 1.0])
y = np.array([1.0, 2.0])
print("angle:", round(angle_deg(x, y), 2), "degrees")   # ~18.43
 
# Orthogonal pair
a = np.array([1.0, 0.0])
b = np.array([0.0, 1.0])
print("⟨a, b⟩ =", a @ b, "-> orthogonal:", np.isclose(a @ b, 0))
 
# An orthogonal matrix (45° rotation): Q.T @ Q = I
t = np.pi / 4
Q = np.array([[np.cos(t), -np.sin(t)],
              [np.sin(t),  np.cos(t)]])
print("QᵀQ = I:", np.allclose(Q.T @ Q, np.eye(2)))
print("length preserved:", np.allclose(np.linalg.norm(Q @ x), np.linalg.norm(x)))
text
angle: 18.43 degrees
⟨a, b⟩ = 0.0 -> orthogonal: True
QᵀQ = I: True
length preserved: True
text
angle: 18.43 degrees
⟨a, b⟩ = 0.0 -> orthogonal: True
QᵀQ = I: True
length preserved: True

Why this matters for ML

  • Cosine similarity is the default metric for comparing text/image embeddings — it ignores magnitude and compares direction.
  • Orthogonal features are uncorrelated, which stabilizes training and interpretation (whitening decorrelates them).
  • Orthogonal matrices are used in stable numerical routines (QR, SVD) and as weight constraints that prevent exploding/vanishing signals in deep nets.

🧪 Try It Yourself

Exercise 1 – Cosine similarity

Exercise 2 – Test orthogonality

Exercise 3 – Orthogonal matrices preserve length

Recap

  • The inner product gives the angle: cosω=x,y/(xy)\cos\omega = \langle\mathbf{x},\mathbf{y}\rangle / (\lVert\mathbf{x}\rVert\lVert\mathbf{y}\rVert) — this is cosine similarity.
  • Orthogonal means x,y=0\langle\mathbf{x},\mathbf{y}\rangle = 0; orthonormal adds unit length.
  • Orthogonal matrices (A1=AA^{-1} = A^\top) preserve lengths and angles — they’re rotations.

Next: a basis made entirely of orthonormal vectors — the orthonormal basis.

If this helped you, consider buying me a coffee ☕

Buy me a coffee

Was this page helpful?

Let us know how we did