Back to Claude Scientific Skills

Examples, Checklists, and Validation

skills/timesfm-forecasting/references/examples_and_validation.md

2.57.06.2 KB
Original Source

Examples, Checklists, and Validation

Runnable examples, the pre-delivery quality checklist, the mistakes that most often produce wrong forecasts, and the regression checks that confirm the skill still works.

Examples

Three fully-working reference examples live in examples/. Use them as ground truth for correct API usage and expected output shape.

ExampleDirectoryWhat It DemonstratesWhen To Use It
Global Temperature Forecastexamples/global-temperature/Basic model.forecast() call, CSV -> PNG -> GIF pipeline, 36-month NOAA contextStarting point; copy-paste baseline for any univariate series
Anomaly Detectionexamples/anomaly-detection/Two-phase detection: linear detrend + Z-score on context, quantile PI on forecast; 2-panel vizAny task requiring outlier detection on historical + forecasted data
Covariates (XReg)examples/covariates-forecasting/forecast_with_covariates() API (TimesFM 2.5), covariate decomposition, 2x2 shared-axis vizRetail, energy, or any series with known exogenous drivers

Running the Examples

bash
# Global temperature (no TimesFM 2.5 needed)
cd examples/global-temperature && python run_forecast.py && python visualize_forecast.py

# Anomaly detection (uses TimesFM 1.0)
cd examples/anomaly-detection && python detect_anomalies.py

# Covariates (API demo -- requires TimesFM 2.5 + timesfm[xreg] for real inference)
cd examples/covariates-forecasting && python demo_covariates.py

Expected Outputs

ExampleKey output filesAcceptance criteria
global-temperatureoutput/forecast_output.json, output/forecast_visualization.pngpoint_forecast has 12 values; PNG shows context + forecast + PI bands
anomaly-detectionoutput/anomaly_detection.json, output/anomaly_detection.pngSep 2023 flagged CRITICAL (z >= 3.0); >= 2 forecast CRITICAL from injected anomalies
covariates-forecastingoutput/sales_with_covariates.csv, output/covariates_data.pngCSV has 108 rows (3 stores x 36 weeks); stores have distinct price arrays

Quality Checklist

Run this checklist after every TimesFM task before declaring success:

  • Output shape correct -- point_fc shape is (n_series, horizon), quant_fc is (n_series, horizon, 10)
  • Quantile indices -- index 0 = mean, 1 = q10, 2 = q20 ... 9 = q90. NOT 0 = q0, 1 = q10.
  • Frequency flag -- TimesFM 1.0/2.0: pass freq=[0] for monthly data. TimesFM 2.5: no freq flag.
  • Series length -- context must be >= 32 data points (model minimum). Warn if shorter.
  • No NaN -- np.isnan(point_fc).any() should be False. Check input series for gaps first.
  • Visualization axes -- if multiple panels share data, use sharex=True. All time axes must cover the same span.
  • Binary outputs in Git LFS -- PNG and GIF files must be tracked via .gitattributes (repo root already configured).
  • No large datasets committed -- any real dataset > 1 MB should be downloaded to tempfile.mkdtemp() and annotated in code.
  • matplotlib.use('Agg') -- must appear before any pyplot import when running headless.
  • infer_is_positive -- set False for temperature anomalies, financial returns, or any series that can be negative.

Common Mistakes

These bugs have appeared in this skill's examples. Learn from them:

  1. Quantile index off-by-one -- The most common mistake. quant_fc[..., 0] is the mean, not q0. q10 = index 1, q90 = index 9. Always define named constants: IDX_Q10, IDX_Q20, IDX_Q80, IDX_Q90 = 1, 2, 8, 9.

  2. Variable shadowing in comprehensions -- If you build per-series covariate dicts inside a loop, do NOT use the loop variable as the comprehension variable. Accumulate into separate dict[str, ndarray] outside the loop, then assign.

    python
    # WRONG -- outer `store_id` gets shadowed:
    covariates = {store_id: arr[store_id] for store_id in stores}  # inside outer loop over store_id
    # CORRECT -- use a different name or accumulate beforehand:
    prices_by_store: dict[str, np.ndarray] = {}
    for store_id, config in stores.items():
        prices_by_store[store_id] = compute_price(config)
    
  3. Wrong CSV column name -- The global-temperature CSV uses anomaly_c, not anomaly. Always print(df.columns) before accessing.

  4. tight_layout() warning with sharex=True -- Harmless; suppress with plt.tight_layout(rect=[0, 0, 1, 0.97]) or ignore.

  5. TimesFM 2.5 required for forecast_with_covariates() -- TimesFM 1.0 does NOT have this method. Install pip install timesfm[xreg] and use checkpoint google/timesfm-2.5-200m-pytorch.

  6. Future covariates must span the full horizon -- Dynamic covariates (price, promotions, holidays) must have values for BOTH the context AND the forecast horizon. You cannot pass context-only arrays.

  7. Anomaly thresholds must be defined once -- Define CRITICAL_Z = 3.0, WARNING_Z = 2.0 as module-level constants. Never hardcode 3 or 2 inline.

  8. Context anomaly detection uses residuals, not raw values -- Always detrend first (np.polyfit linear, or seasonal decomposition), then Z-score the residuals. Raw-value Z-scores are misleading on trending data.

Validation & Verification

Use the example outputs as regression baselines. If you change forecasting logic, verify:

bash
# Anomaly detection regression check:
python -c "
import json
d = json.load(open('examples/anomaly-detection/output/anomaly_detection.json'))
ctx = d['context_summary']
assert ctx['critical'] >= 1, 'Sep 2023 must be CRITICAL'
assert any(r['date'] == '2023-09' and r['severity'] == 'CRITICAL'
           for r in d['context_detections']), 'Sep 2023 not found'
print('Anomaly detection regression: PASS')"

# Covariates regression check:
python -c "
import pandas as pd
df = pd.read_csv('examples/covariates-forecasting/output/sales_with_covariates.csv')
assert len(df) == 108, f'Expected 108 rows, got {len(df)}'
prices = df.groupby('store_id')['price'].mean()
assert prices['store_A'] > prices['store_B'] > prices['store_C'], 'Store price ordering wrong'
print('Covariates regression: PASS')"