Adaptive Weight System: How Signal Importance Evolves
Not all risk signals matter equally for everyone. Whistl's Adaptive Weight System learns which signals best predict YOUR impulses and adjusts their importance over time. What's a strong predictor for one user may be weak for another—and Whistl discovers the difference.
Why Adaptive Weights Matter
Individual differences in trigger patterns require personalised weighting:
Example: Different Users, Different Triggers
| User | Strongest Predictor | Weakest Predictor |
|---|---|---|
| Marcus | Venue proximity (physical triggers) | Weather (unaffected by conditions) |
| Sarah | Sleep quality (biometric triggers) | Day of week (consistent across week) |
| Jake | Time of day (late night vulnerability) | Calendar stress (not event-driven) |
The Problem with Fixed Weights
- Population averages miss individual patterns: What's true on average may not be true for you
- Static weights can't adapt: Your patterns may change over time
- Reduced prediction accuracy: Wrong weights = wrong predictions
How Weight Adaptation Works
The Adaptive Weight System continuously learns from outcomes:
Weight Update Algorithm
# Exponential Moving Average weight update
def update_signal_weight(signal_name, current_weight, signal_value, outcome):
"""
Adjust signal weight based on prediction accuracy.
Args:
signal_name: Which signal (e.g., "venue_proximity")
current_weight: Current importance (0.01 - 0.20)
signal_value: Signal's current value (0.0 - 1.0)
outcome: Actual outcome (1 = impulse occurred, 0 = didn't)
Returns:
Updated weight
"""
learning_rate = 0.05 # Speed of adaptation
# Calculate prediction contribution
# If signal was high AND impulse occurred, signal was predictive
if signal_value > 0.7 and outcome == 1:
# Signal correctly predicted impulse - increase weight
adjustment = learning_rate * (1.0 - current_weight)
new_weight = current_weight + adjustment
elif signal_value < 0.3 and outcome == 0:
# Signal correctly predicted no impulse - increase weight
adjustment = learning_rate * (1.0 - current_weight)
new_weight = current_weight + adjustment
elif signal_value > 0.7 and outcome == 0:
# Signal predicted impulse but none occurred - decrease weight
adjustment = learning_rate * current_weight
new_weight = current_weight - adjustment
elif signal_value < 0.3 and outcome == 1:
# Signal predicted no impulse but one occurred - decrease weight
adjustment = learning_rate * current_weight
new_weight = current_weight - adjustment
else:
# Ambiguous case - minor adjustment
new_weight = current_weight
# Ensure weight stays in valid range
new_weight = max(0.01, min(0.20, new_weight))
return new_weight
Weight Normalisation
After individual updates, weights are normalised to sum to 1.0:
# Normalise weights to sum to 1.0
def normalise_weights(weights):
"""
Ensure all signal weights sum to exactly 1.0.
Args:
weights: Dictionary of {signal_name: weight}
Returns:
Normalised weights
"""
total = sum(weights.values())
normalised = {}
for signal_name, weight in weights.items():
normalised[signal_name] = weight / total
return normalised
# Example:
# Before: {"venue": 0.08, "sleep": 0.06, "time": 0.04, ...} # Sum = 0.97
# After: {"venue": 0.082, "sleep": 0.062, "time": 0.041, ...} # Sum = 1.0
Weight Adaptation Timeline
Weights evolve through distinct phases:
Phase 1: Default Weights (Days 1-7)
- Source: Population averages from all users
- Purpose: Reasonable starting point before personal data
- Adaptation rate: High (learning quickly)
- Weight change: Can shift ±20% per week
Phase 2: Personal Calibration (Days 8-30)
- Source: User's own outcome data
- Purpose: Discover personal trigger patterns
- Adaptation rate: Medium (balancing stability and learning)
- Weight change: Can shift ±10% per week
Phase 3: Stable Personalisation (Days 31+)
- Source: Accumulated personal data
- Purpose: Fine-tune established patterns
- Adaptation rate: Low (stable, minor adjustments)
- Weight change: Typically ±3% per week
Phase 4: Pattern Shift Detection (Ongoing)
- Monitors for: Significant changes in impulse patterns
- Response: Temporarily increase adaptation rate
- Triggers: Life events, location changes, new habits
Real-World Weight Evolution Examples
Example 1: Marcus's Venue Sensitivity
Initial weight (Day 1): Venue proximity = 5.9% (population average)
Observations:
- Week 1: 4 impulses, all within 500m of venue
- Week 2: 3 impulses, all within 500m of venue
- Week 3: 2 impulses, both within 500m of venue
Weight evolution:
- Day 7: 7.2% (increased due to predictive accuracy)
- Day 14: 8.9%
- Day 30: 10.4%
- Day 60: 11.2% (stabilised)
Result: Venue proximity weight nearly doubled for Marcus vs. population average
Example 2: Sarah's Sleep Sensitivity
Initial weight (Day 1): Sleep quality = 3.7% (population average)
Observations:
- Week 1: 3 impulses, all after <6 hours sleep
- Week 2: 4 impulses, all after <6 hours sleep
- Week 3: 2 impulses, both after <6 hours sleep
- Good sleep days: 0 impulses
Weight evolution:
- Day 7: 5.1%
- Day 14: 6.8%
- Day 30: 8.3%
- Day 60: 8.9% (stabilised)
Result: Sleep weight more than doubled—Sarah is highly sleep-sensitive
Example 3: Jake's Weather Insensitivity
Initial weight (Day 1): Weather conditions = 1.8% (population average)
Observations:
- Week 1-4: No correlation between weather and impulses
- Rainy days: Same impulse rate as sunny days
- Weather signal consistently non-predictive
Weight evolution:
- Day 7: 1.5%
- Day 14: 1.2%
- Day 30: 0.8%
- Day 60: 0.5% (minimum threshold)
Result: Weather weight reduced to minimum—Jake isn't weather-sensitive
Weight Bounds and Constraints
The system maintains reasonable weight ranges:
Weight Limits
| Constraint | Value | Rationale |
|---|---|---|
| Minimum weight | 0.5% | Every signal has some relevance |
| Maximum weight | 20% | No single signal dominates |
| Tier 1 minimum | 8% | Primary predictors stay important |
| Sum constraint | 100% | Weights must sum to 1.0 |
Rate Limiting
- Maximum weekly change: ±20% (prevents wild swings)
- Minimum data for update: 10 observations (prevents overfitting)
- Cooling period: 24 hours between major adjustments
Effectiveness Data
Adaptive weights vs. fixed weights:
| Metric | Fixed Weights | Adaptive Weights | Improvement |
|---|---|---|---|
| Prediction Accuracy (Day 1-7) | 72% | 72% | Equal (using defaults) |
| Prediction Accuracy (Day 30+) | 72% | 84% | +12% |
| Prediction Accuracy (Day 90+) | 72% | 87% | +15% |
| User Satisfaction | 4.1/5 | 4.6/5 | +12% |
User Testimonials
"Whistl figured out that being near venues is my big trigger. Now it's extra careful when I'm near Crown. That personalisation is powerful." — Marcus, 28
"After a month, Whistl knew my sleep was the key. Now when I sleep badly, it's on high alert. It learned me." — Sarah, 34
"The app gets smarter over time. It's not the same as when I started—it knows my patterns now." — Jake, 31
Conclusion
The Adaptive Weight System transforms Whistl from a generic risk calculator into a deeply personal protection system. By learning which signals matter most for YOU, Whistl becomes more accurate, more relevant, and more effective over time.
Your risk profile is unique. Your weights should be too.
Experience Personalised Risk Assessment
Whistl's adaptive weights learn your unique patterns. Download free and get protection that evolves with you.
Download Whistl FreeRelated: Risk Orchestrator | 27 Risk Signals | Machine Learning Money Management