Skip to content
Work Practice Products Coding interviews Machine learning coding Quant developer HFT course Blog Method Why me About Enquire Book a call

ML coding · Embeddings and retrieval

Skip-gram with negative sampling: loss and gradients

Hard · Target 20 minutes · Python and NumPy

Given the centre-word vector v, the true context vector u and k negative vectors U_neg (k × d), with s = u·v and sj = uj·v, the loss is

L = −log σ(s) − Σj log σ(−sj).

Return [L, dL/dv, dL/du, dL/dU_neg], the last a k × d list. Dot products may reach ±1000.

Examples

Input v = [1, 0], u = [1, 0], U_neg = [[0, 1]]

Output [1.0064, [-0.2689, 0.5], [-0.2689, 0], [[0.5, 0]]]

s = 1, one negative orthogonal to v (s₁ = 0).

Input v = [10, 0], u = [-100, 0], U_neg = [[100, 0]]

Output [2000, [200, 0], [-10, 0], [[10, 0]]]

Dot products of −1000 and 1000: the naive log σ gives −inf.

Constraints

  • 1 ≤ d ≤ 300, 1 ≤ k ≤ 20
  • Checked to a relative tolerance of 10⁻⁹

Hints

Hint 1

d/dx [−log σ(x)] = σ(x) − 1 and d/dx [−log σ(−x)] = σ(x).

Hint 2

So dL/dv = (σ(s) − 1)u + Σ σ(s_j)u_j, dL/du = (σ(s) − 1)v and dL/du_j = σ(s_j)v.

Hint 3

log σ(x) = −softplus(−x), and softplus(y) = max(y, 0) + log1p(exp(−|y|)).

Where candidates go wrong

  • np.log(sigmoid(x)) for large negative x: σ rounds to 0 and the log is −inf.
  • Sign errors on the negative terms: their gradient pushes σ(s_j) towards 0, so it is +σ(s_j), not σ(s_j) − 1.
  • Forgetting that v receives gradient from every negative.
Console⌘/Ctrl + Enter runs

Python runs in your browser with NumPy. The first run downloads the runtime, which takes a few seconds.


Why interviewers ask it

Deriving and coding these gradients is a classic research-engineer question. It tests the derivative of the log-sigmoid, the direction of each term, and numerical care.

The theory behind it is in the lesson Cosine search, contrastive loss and negative sampling.


Keep going