Hierarchical Softmax › Path Probability: The Mathematics

Michael BrenndoerferUpdated February 8, 20265 min read
Language AI HandbookAll chapters
Part 4 of 67Word Embeddings
Chapter 22Hierarchical Softmax › Path Probability: The Mathematics
Reading section 5 of 16 · Path Probability: The Mathematics · 5 minSection 5 of 16 · 5 min

Book contents

Section 5 of 16 · 5 min read

Hierarchical Softmax › Path Probability: The MathematicsOne section · Sections in this chapter5 / 16 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

With the tree structure defined, we can now write the probability formula precisely. The key insight is that the probability of a word equals the product of probabilities of all correct binary decisions along its path from root to leaf.

Binary Decisions with Learned Vectors

Each internal node nn has a learned vector vn\mathbf{v}_n of the same dimension as the word embeddings. To make the left-right decision at node nn, we compare this node vector with the current context embedding h\mathbf{h} using a dot product, then pass the result through the sigmoid function:

σ(vn⋅h)=11+exp⁡(−vn⋅h)\sigma(\mathbf{v}_n \cdot \mathbf{h}) = \frac{1}{1 + \exp(-\mathbf{v}_n \cdot \mathbf{h})}

where:

  • σ(⋅)\sigma(\cdot): the sigmoid function, mapping any real number to (0,1)(0, 1)
  • vn\mathbf{v}_n: the learned vector at internal node nn
  • h\mathbf{h}: the context embedding (center word's input embedding)

This output gives the probability of going left. The probability of going right is 1−σ(vn⋅h)=σ(−vn⋅h)1 - \sigma(\mathbf{v}_n \cdot \mathbf{h}) = \sigma(-\mathbf{v}_n \cdot \mathbf{h}). These two always sum to 1, which is what ensures the tree defines a valid probability distribution.

Why the sigmoid function specifically? The sigmoid maps real numbers to the interval (0,1)(0, 1), making it a natural candidate for probabilities. More importantly, the symmetry property σ(−x)=1−σ(x)\sigma(-x) = 1 - \sigma(x) means we can encode both the "go left" and "go right" probabilities using a single dot product and a sign flip. This symmetry is exploited compactly in the path probability formula.

The Path Probability Formula

The probability of word ww given context embedding h\mathbf{h} is the product of probabilities at each decision point along the root-to-leaf path:

P(w∣h)=∏j=1L(w)−1σ ⁣(dj⋅vn(w,j)⋅h)P(w | \mathbf{h}) = \prod_{j=1}^{L(w)-1} \sigma\!\left( d_j \cdot \mathbf{v}_{n(w,j)} \cdot \mathbf{h} \right)

where:

  • L(w)L(w): the total number of nodes along the path from root to word ww (including root and leaf)
  • n(w,j)n(w, j): the jj-th node along the path to ww, with n(w,1)n(w, 1) being the root
  • dj∈{+1,−1}d_j \in \{+1, -1\}: the direction code at step jj, equal to +1+1 if the next node is the left child and −1-1 if it is the right child
  • vn(w,j)\mathbf{v}_{n(w,j)}: the learned vector at the jj-th internal node
  • h\mathbf{h}: the context embedding

The direction encoding djd_j is the key mechanism. When dj=+1d_j = +1 (go left), we compute σ(v⋅h)\sigma(\mathbf{v} \cdot \mathbf{h}), which is high when the dot product is positive. When dj=−1d_j = -1 (go right), we compute σ(−v⋅h)\sigma(-\mathbf{v} \cdot \mathbf{h}), which is the complementary probability. This compact encoding lets a single formula handle both directions without needing two separate parameters per node.

Why This Defines a Valid Probability Distribution

For hierarchical softmax to be valid, all leaf probabilities must sum to 1. This holds because at each internal node, the probabilities of its two children are σ(v⋅h)\sigma(\mathbf{v} \cdot \mathbf{h}) and 1−σ(v⋅h)1 - \sigma(\mathbf{v} \cdot \mathbf{h}), which sum to 1. By induction starting from the root, the probability mass is conserved at every level and distributed exactly across all leaves.

Why Probabilities Can Be Small

For a vocabulary of 100,000 words, a Huffman tree assigns paths of roughly 15 to 20 nodes. The final probability is a product of 15 to 20 sigmoid values, each between 0 and 1. Even if each step has probability 0.8, the product of 17 steps is 0.817≈0.02250.8^{17} \approx 0.0225. This is expected behavior: 100,000 words share probability mass, so individual word probabilities must be small. The model is not failing; it is correctly distributing probability across a large vocabulary.

Working in log space helps numerically. Instead of multiplying probabilities (which can underflow to zero for long paths), we sum log-probabilities. This is numerically stable and is the natural form for the loss function we will derive below.

In[11]:
Code
import numpy as np


def sigmoid(x):
    """Numerically stable sigmoid."""
    return np.where(x >= 0, 1 / (1 + np.exp(-x)), np.exp(x) / (1 + np.exp(x)))


def compute_path_probability(h, path_vectors, path_directions):
    """
    Compute P(w | h) as the product of binary decisions along the path.

    Args:
        h: Context embedding (embedding_dim,)
        path_vectors: Internal node vectors along the path
        path_directions: +1 for left, -1 for right at each node

    Returns:
        Word probability and per-step probabilities
    """
    step_probs = []
    for v, d in zip(path_vectors, path_directions):
        step_prob = sigmoid(d * np.dot(v, h))
        step_probs.append(float(step_prob))

    word_prob = float(np.prod(step_probs))
    return word_prob, step_probs


np.random.seed(42)
dim = 50
h = np.random.randn(dim) * 0.3

# Simulate a path of length 4 (small vocabulary example)
path_vectors = [np.random.randn(dim) * 0.3 for _ in range(4)]
path_directions = [1, -1, -1, 1]  # left, right, right, left

word_prob, step_probs = compute_path_probability(
    h, path_vectors, path_directions
)
Out[12]:
Console
Path Probability Step-by-Step:
-----------------------------------------------------------------
 Step Direction  Dot Product  Step Prob   Cumulative
-----------------------------------------------------------------
    1      left       0.3782     0.5934     0.593443
    2     right      -0.4852     0.6190     0.367330
    3     right       0.3082     0.4235     0.155581
    4      left       1.3432     0.7930     0.123377
-----------------------------------------------------------------
Final P(word | h) = 0.123377

For comparison: 1 / vocab_size (8 words) = 0.125000

The output shows how each binary decision multiplies into the running probability. The final value is close to 1/8≈0.1251/8 \approx 0.125 for a perfectly balanced 8-leaf tree, which is the expected word probability when the model assigns equal mass to all words. As training proceeds, the model adjusts node vectors so that these probabilities increase for observed word pairs and decrease for unobserved ones.