Contextual Bandits

Contextual bandits extend multi-armed bandits by using features available at decision time. A stateless bandit asks, “Which arm is best on average?” A contextual bandit asks, “Which arm is best for this user, request, and situation?”

The bandit part remains the same: after choosing an action, the system observes reward only for the action it showed. The contextual part changes the decision rule: user segment, device, query, location, time, item age, price, or content embeddings can all influence the exploration decision. This is the bridge between simple bandit algorithms and personalized recommendation.

Decision loop

At round , a contextual bandit:

  1. observes context before choosing;
  2. builds the eligible action set ;
  3. scores each action using reward estimates and uncertainty;
  4. chooses one action ;
  5. observes reward only for ;
  6. logs the context, action, reward, policy version, and propensity when available.

A contextual bandit observes user and request features, scores only eligible candidate arms, serves one arm, observes only that arm's reward, and updates the policy state.

The diagram emphasizes two boundaries. Eligibility filtering happens before exploration, so the policy never explores unavailable or unsafe items. Logging happens after serving, because future offline versus online evaluation needs to know what context was visible, which action was eligible, which action was chosen, and what reward was observed.

Formal setup

Let be the context vector at round , the eligible arms, the chosen arm, and the observed reward. A contextual policy estimates the conditional reward:

The goal is not to learn one global per arm, as in the stateless page. The goal is to learn which arm works for which contexts while still handling partial feedback. For example, a finance article may perform well for desktop users reading market news, while a weather alert may perform well for mobile users in the morning.

Feature familyExamplesRisk
User featuressegment, locale, tenure, subscription tierprivacy, stale profiles, sensitive proxies
Request featuresquery, device, hour, surface, referrerseasonality and traffic shifts
Item featurestopic, freshness, price, creator, embeddingleakage if computed after exposure
Policy featureseligibility, inventory, fatigue stateaccidental exploration of ineligible items

Only use features known before the recommendation is shown. Post-click features, later conversions, updated popularity, or downstream rank positions leak information from the future and make evaluation invalid.

LinUCB

LinUCB is a common contextual bandit for continuous feature vectors. It assumes each arm has an approximately linear reward model:

Here is the feature vector visible before serving the recommendation, is an arm, is the reward, and is the unknown coefficient vector for arm . If has features, then also has entries. A common choice is to include an intercept feature, so the first coordinate of is always .

For each arm , LinUCB maintains a matrix and vector from past observations where that arm was chosen. With regularization strength , initialize:

for every arm . Here is the identity matrix and is the -dimensional zero vector. This initialization is the ridge-regression prior: before seeing data for an arm, the estimated coefficients are zero, but is invertible. In practice, is a common starting point; larger values make early estimates more conservative.

After several observations for arm , the estimate is:

This is the same shape as a ridge linear-regression solution. If arm has been chosen on contexts with rewards , then:

The matrix records where the algorithm has evidence for this arm. Repeatedly showing arm to users with similar feature vectors makes large in that feature direction. The vector records reward-weighted evidence: contexts that produced higher rewards pull toward predicting higher rewards for similar contexts.

For the current context , it chooses

The first term, , is exploitation. It is the predicted reward under the current fitted linear model for arm . If this term is high, the arm looks good based on observed rewards in similar contexts.

The second term, , is exploration. The quantity inside the square root is large when the current context points in a direction where arm has little data. It is small when the algorithm has already shown arm many times in similar contexts. Geometrically, describes the remaining uncertainty in the coefficient estimate, and projects that uncertainty onto the specific context being served now.

This is why LinUCB can choose an arm with a lower predicted reward: the upper confidence score asks, “How good could this arm plausibly be, given what we still do not know?” The parameter controls how much uncertainty is rewarded. Larger explores more aggressively; smaller behaves more greedily. Setting turns the policy into a greedy contextual linear model.

After observing reward for the chosen arm , the policy updates only that arm:

The unchosen arms are not updated, because their rewards were not observed. That partial-feedback discipline is the reason contextual bandits need different evaluation from ordinary supervised ranking.

An implementation usually stores one d x d matrix and one d-vector per arm:

State variableInitializationUpdate after choosing arm Interpretation
add only to feature directions where this arm has been observed
add only to reward-weighted evidence for this arm
recompute or solve fitted reward coefficients for this arm
uncertaintyshrinks in observed directionscontext-specific reason to explore

Worked example

Suppose a news homepage can choose one module for a returning user. The current context is:

FeatureValue
intercept1.0
market-news interest0.7
morning mobile session1.0

The eligible arms are:

ArmModule
Amarket briefing
Bpersonal finance tips
Clocal weather alert

A LinUCB policy evaluates each arm for this context:

ArmPredicted reward Uncertainty bonusLinUCB scoreInterpretation
A0.0710.0180.089good match to market interest, enough history
B0.0620.0340.096weaker prediction, but less certainty
C0.0550.0520.107uncertain in this context, so it gets explored

The policy chooses C even though A has the highest predicted reward. That is not random noise: C has enough plausible upside for this user context that the exploration bonus makes it worth trying. If C gets a click, the model updates C’s parameters toward this context. If C does not get a click, the uncertainty for similar contexts shrinks and future scores fall.

This is different from a non-contextual UCB policy. A stateless bandit would see only arm-level click rates. LinUCB can learn that weather alerts may be weak on average but strong for morning mobile sessions, while market briefings may be strong for market-news readers.

Algorithm families

FamilyDecision ideaTypical use
Contextual epsilon-greedytrain a reward model, usually choose the best predicted arm, sometimes explore randomlysimple deployments with bounded randomization
LinUCBchoose predicted reward plus a context-specific uncertainty bonussmall or medium arm sets with numeric features
Linear Thompson samplingsample plausible model parameters, then choose the arm with the largest sampled rewardbinary or continuous rewards with Bayesian uncertainty
Logistic contextual banditmodel click probability through a logistic reward modelbinary click or conversion rewards
Neural contextual bandituse a neural model for reward prediction plus an uncertainty or exploration layerhigh-dimensional text, image, or embedding features

The more flexible the model, the harder the uncertainty estimate becomes. A strong reward model without reliable exploration can become a greedy ranker with biased logs.

Logging and evaluation

Contextual bandit logs should include:

  • request context features or stable feature IDs;
  • eligible actions after filtering;
  • chosen action;
  • observed reward and reward timestamp;
  • policy version and model version;
  • action probability or propensity when the policy is randomized;
  • position, surface, and guardrail decisions that affected exposure.

This logging makes replay, inverse-propensity scoring, and online experiments possible. Without propensities or randomized traffic, historical logs mostly answer “what happened under the old policy,” not “what would happen under the new policy.” See Offline Versus Online Evaluation for the evaluation mechanics.

When to use contextual bandits

Use contextual bandits when the choice should adapt to request features and the reward is observed soon enough to update the policy. They are useful for homepage modules, notification templates, article slots, ad creatives, and candidate-source selection. They are less appropriate when rewards are very delayed, actions interact strongly with each other, or the product needs multi-step planning; those cases may need delayed attribution, slate methods, or reinforcement learning.

Caveats

Contextual bandits optimize the reward they observe, so reward design matters as much as the algorithm. Clicks can reward sensational or repetitive items. Conversion rewards can under-value exploration for early-funnel content. Repeated exposure creates fatigue, and users can influence each other’s rewards through popularity effects.

Feature leakage is a common failure mode. Do not train on popularity, position, or engagement features that were computed after the item was exposed unless the serving system will know those exact values at decision time. Also keep eligibility filters outside the model: a contextual bandit should rank allowed actions, not learn to bypass availability, policy, or safety rules.

References