Skip to content
AI360Xpert
Beta

DeepWalk and Node2Vec

DeepWalk and Node2Vec simulate random walks across a network to turn graphs into sequences of nodes trained like sentences in language models.

Node2Vec guides random walks with return parameter p and in-out parameter q to feed simulated sequences into Skip-Gram with negative sampling
Node2Vec guides random walks with return parameter p and in-out parameter q to feed simulated sequences into Skip-Gram with negative sampling

Why Does This Exist?

In the early 2010s, natural language processing experienced a revolution when Word2Vec revealed that dense word representations could be learned efficiently by sliding context windows over text sentences. Graph practitioners wanted similar continuous embeddings for network nodes, but graphs lack a natural sequential ordering: there is no single "beginning", "middle", or "end" to a graph topology.

Computing global pairwise distances across millions of nodes using matrix factorization algorithms (like spectral decomposition of the Laplacian) incurs an intractable O(∣V∣3)\mathcal{O}(|V|^3) or O(∣V∣2)\mathcal{O}(|V|^2) computational cost and collapses when graph edges evolve. DeepWalk (Perozzi et al., 2014) solved this by realizing that truncated random walks on a network exhibit the exact same power-law frequency distribution as words in natural language corpora. Node2Vec (Grover & Leskovec, 2016) generalized DeepWalk by introducing parameterized, second-order random walks that allow practitioners to interpolate smoothly between local community clustering (homophily) and structural network roles (such as hubs or bridges).

Think of It Like This

A wandering tourist exploring a foreign city

Imagine a tourist landing in an unfamiliar historic city with narrow alleys, ring roads, and town squares. If the tourist strolls by flipping a fair coin at every crossroad, taking 40 steps before stopping, their trip diary records a sequence of street corners. Two corners that sit along the same bustling avenue will frequently appear adjacent in those diary entries.

Now give the tourist a guidebook with two dial knobs:

  • The Return knob (pp) controls homesickness. Set it low, and the tourist loves looping back to where they just came from, thoroughly mapping out the tiny alleys of their immediate neighborhood (Breadth-First Search).
  • The Exploration knob (qq) controls adventurousness. Set it low, and the tourist avoids turning around, charging straight outward across major avenues into foreign districts to discover how far the city reaches (Depth-First Search).

Feeding thousands of these tourist journals into a text model teaches it which landmarks share a local neighborhood and which act as structural city gates.

How It Actually Works

2nd-Order Biased Walks and Skip-Gram Objective

Node2Vec defines a flexible neighborhood NS(u)\mathcal{N}_S(u) for every node uu by simulating second-order random walks. Suppose a walk just traversed edge (t,v)(t, v) and is currently positioned at node vv. The probability of taking the next step to a neighbor x∈N(v)x \in \mathcal{N}(v) is:

P(ci=x∣ci−1=v,ci−2=t)=πvx∑y∈N(v)πvyP(c_i = x \mid c_{i-1} = v, c_{i-2} = t) = \frac{\pi_{vx}}{\sum_{y \in \mathcal{N}(v)} \pi_{vy}}

The unnormalized transition probability πvx\pi_{vx} is the product of the edge weight wvxw_{vx} and a search bias αpq(t,x)\alpha_{pq}(t, x):

πvx=αpq(t,x)⋅wvx\pi_{vx} = \alpha_{pq}(t, x) \cdot w_{vx}

The search bias αpq(t,x)\alpha_{pq}(t, x) depends on the shortest-path distance dtx∈{0,1,2}d_{tx} \in \{0, 1, 2\} between the previous node tt and candidate neighbor xx:

αpq(t,x)={1pif dtx=0(return to previous node t)1if dtx=1(visit mutual neighbor of t and v)1qif dtx=2(explore outward to unseen node)\alpha_{pq}(t, x) = \begin{cases} \frac{1}{p} & \text{if } d_{tx} = 0 \quad (\text{return to previous node } t) \\ 1 & \text{if } d_{tx} = 1 \quad (\text{visit mutual neighbor of } t \text{ and } v) \\ \frac{1}{q} & \text{if } d_{tx} = 2 \quad (\text{explore outward to unseen node}) \end{cases}

  • Return parameter pp: High pp (>1> 1) discourages revisiting recent nodes, reducing 2-hop redundancy. Low pp (<1< 1) forces the walk to stay local, emulating Breadth-First Search (BFS) to capture homophily (nodes in the same community get similar embeddings).
  • In-out parameter qq: Low qq (<1< 1) encourages the walk to venture outward, emulating Depth-First Search (DFS) to capture structural equivalence (nodes serving identical topological roles, like hubs or peripheral leaves, get similar embeddings regardless of distance).
  • DeepWalk Equivalence: Setting p=1.0p = 1.0 and q=1.0q = 1.0 recovers the uniform random walk of DeepWalk.

Once a corpus of random walks W\mathcal{W} is generated, the embeddings are optimized using the Skip-Gram architecture with Negative Sampling:

max⁡f∑u∈V∑c∈NS(u)[log⁡σ(zc⊤zu)+∑k=1KEnk∼Pn(V)[log⁡σ(−znk⊤zu)]]\max_f \sum_{u \in V} \sum_{c \in \mathcal{N}_S(u)} \left[ \log \sigma(\mathbf{z}_c^\top \mathbf{z}_u) + \sum_{k=1}^K \mathbb{E}_{n_k \sim P_n(V)} \left[ \log \sigma(-\mathbf{z}_{n_k}^\top \mathbf{z}_u) \right] \right]

where zu∈Rd\mathbf{z}_u \in \mathbb{R}^d is the center representation of node uu, zc∈Rd\mathbf{z}_c \in \mathbb{R}^d is the context representation of neighbor cc, σ(x)=11+e−x\sigma(x) = \frac{1}{1 + e^{-x}}, and KK is the number of negative samples drawn from noise distribution Pn(V)∝(deg(v))3/4P_n(V) \propto (\text{deg}(v))^{3/4}.

Worked Example

Let a walk transition from tt to vv. The neighbors of vv are {t,a,b}\{t, a, b\}:

  • tt: distance dtx=0d_{tx} = 0.
  • aa: edge (t,a)(t, a) exists in the graph, so distance dta=1d_{ta} = 1.
  • bb: no edge between tt and bb, so distance dtb=2d_{tb} = 2.

Assume unweighted edges (w=1.0w = 1.0), return parameter p=0.5p = 0.5, and in-out parameter q=2.0q = 2.0:

  1. Calculate unnormalized biases αpq(t,x)\alpha_{pq}(t, x): α(t,t)=1p=10.5=2.0\alpha(t, t) = \frac{1}{p} = \frac{1}{0.5} = 2.0 α(t,a)=1.0\alpha(t, a) = 1.0 α(t,b)=1q=12.0=0.5\alpha(t, b) = \frac{1}{q} = \frac{1}{2.0} = 0.5

  2. Compute normalization denominator ZZ: Z=πvt+πva+πvb=2.0+1.0+0.5=3.5Z = \pi_{vt} + \pi_{va} + \pi_{vb} = 2.0 + 1.0 + 0.5 = 3.5

  3. Compute exact transition probabilities: P(t∣v,t)=2.03.5≈0.5714(57.1%)P(t \mid v, t) = \frac{2.0}{3.5} \approx 0.5714 \quad (57.1\%) P(a∣v,t)=1.03.5≈0.2857(28.6%)P(a \mid v, t) = \frac{1.0}{3.5} \approx 0.2857 \quad (28.6\%) P(b∣v,t)=0.53.5≈0.1429(14.3%)P(b \mid v, t) = \frac{0.5}{3.5} \approx 0.1429 \quad (14.3\%)

Because p<1p < 1 and q>1q > 1, the walker is 4×4\times more likely to double back to tt than to step out toward distant node bb, heavily favoring local community clustering.

Code

import randomfrom typing import Dict, List

def sample_node2vec_step(    prev_node: int,    curr_node: int,    adjacency: Dict[int, List[int]],    p: float,    q: float,) -> int:    """Sample next node in 2nd-order biased random walk given (prev_node, curr_node)."""    neighbors = adjacency[curr_node]    prev_neighbors = set(adjacency[prev_node])
    weights: List[float] = []    for nbr in neighbors:        if nbr == prev_node:            # d(prev, nbr) == 0            weights.append(1.0 / p)        elif nbr in prev_neighbors:            # d(prev, nbr) == 1 (mutual neighbor)            weights.append(1.0)        else:            # d(prev, nbr) == 2 (outward step)            weights.append(1.0 / q)
    # Weighted random sampling    chosen: int = random.choices(neighbors, weights=weights, k=1)[0]    return chosen

# Test with graph: 0-1, 1-2 (with edge 0-2), 1-3 (no edge 0-3)adj: Dict[int, List[int]] = {    0: [1, 2],    1: [0, 2, 3],    2: [0, 1],    3: [1],}
# Fix seed for reproducible checkrandom.seed(42)counts: Dict[int, int] = {0: 0, 2: 0, 3: 0}for _ in range(10_000):    nxt = sample_node2vec_step(prev_node=0, curr_node=1, adjacency=adj, p=0.5, q=2.0)    counts[nxt] += 1
# Node 0 (return) ~57%, Node 2 (mutual) ~28%, Node 3 (outward) ~14%print(f"Empirical distribution: 0: {counts[0]/10000:.3f}, 2: {counts[2]/10000:.3f}, 3: {counts[3]/10000:.3f}")# -> Empirical distribution: 0: 0.573, 2: 0.285, 3: 0.142

Watch Out For

Second-order transition memory explosion

In standard first-order random walks (DeepWalk), transition probabilities only depend on the current node vv, needing O(∣E∣)\mathcal{O}(|E|) total probability storage. In Node2Vec, the next step depends on the ordered edge pair (t,v)(t, v), which expands memory requirements to O(∣V∣⋅davg2)\mathcal{O}(|V| \cdot d_{\text{avg}}^2) where davgd_{\text{avg}} is the average degree.

On large-scale graphs with power-law hubs (where a single celebrity or payment router has 100,000100{,}000 edges), precomputing and storing alias tables for every incoming edge will trigger Out-Of-Memory (OOM) errors. For graphs exceeding 10710^7 edges, compute transition weights dynamically on the fly during the random walk or clip maximum neighborhood degrees before preprocessing.

The Quick Version

  • DeepWalk transforms graphs into text sequences by generating uniform random walks, applying Skip-Gram with Negative Sampling to learn continuous node vectors.
  • Node2Vec introduces second-order walk biases controlled by two hyperparameters: return parameter pp and exploration parameter qq.
  • Setting p<1p < 1 prioritizes Breadth-First Search (BFS) to preserve local community homophily, while q<1q < 1 prioritizes Depth-First Search (DFS) to learn structural network roles.