Update global-temperature example to use TimesFM 2.5 API

This commit is contained in:
Rajat Sen
2026-06-08 17:31:07 +00:00
parent e56854bc9e
commit 6ed1d8a7a2
5 changed files with 196 additions and 193 deletions
@@ -1,13 +1,13 @@
date,point_forecast,q10,q20,q30,q40,q50,q60,q70,q80,q90,q99
2025-01-01,1.2593384,1.248188,1.140702,1.1880752,1.2137158,1.2394564,1.2593384,1.2767732,1.297132,1.32396,1.367888
2025-02-01,1.2856668,1.2773758,1.1406044,1.1960833,1.2322671,1.2593892,1.2856668,1.3110137,1.3400218,1.3751202,1.4253658
2025-03-01,1.2950127,1.2869918,1.126852,1.1876173,1.234988,1.2675052,1.2950127,1.328448,1.354729,1.4035482,1.4642649
2025-04-01,1.2207624,1.2084007,1.0352504,1.1041918,1.151865,1.1853008,1.2207624,1.256663,1.2898555,1.3310349,1.4016538
2025-05-01,1.1702554,1.153313,0.9691495,1.0431063,1.0932612,1.1276176,1.1702554,1.201966,1.2390311,1.2891905,1.3632389
2025-06-01,1.1455553,1.1275499,0.94203794,1.0110554,1.0658777,1.1061188,1.1455553,1.1806211,1.2180579,1.2702757,1.345366
2025-07-01,1.1702348,1.1510556,0.9503718,1.0347577,1.0847733,1.1287677,1.1702348,1.2114835,1.2482276,1.2997853,1.3807325
2025-08-01,1.2026825,1.1859496,0.9709255,1.0594383,1.1106675,1.1579902,1.2026825,1.2399211,1.2842004,1.3408126,1.419526
2025-09-01,1.1909748,1.1784849,0.95943713,1.0403702,1.103606,1.1511956,1.1909748,1.2390201,1.2832941,1.3354731,1.416972
2025-10-01,1.1490841,1.1264795,0.9079477,0.99529266,1.0548235,1.1052223,1.1490841,1.1897774,1.240414,1.2868769,1.3775467
2025-11-01,1.0804785,1.0624356,0.8361266,0.9259792,0.9882403,1.0386353,1.0804785,1.1281581,1.1759715,1.228377,1.3122478
2025-12-01,1.0613453,1.0366092,0.80220693,0.89521873,0.9593707,1.0152239,1.0613453,1.1032857,1.15315,1.216908,1.2959521
date,point_forecast,mean,q10,q20,q30,q40,q50,q60,q70,q80,q90
2025-01-01,1.2223774,1.2215943,1.1230627,1.1613995,1.1832488,1.2030286,1.2223774,1.240989,1.2626991,1.2927711,1.339603
2025-02-01,1.2563584,1.2502017,1.1482248,1.1891649,1.2134029,1.2355918,1.2563584,1.2787917,1.3061507,1.3358022,1.3880283
2025-03-01,1.286477,1.2816916,1.1694773,1.2141376,1.2430503,1.2636719,1.286477,1.3101407,1.3365126,1.3725822,1.4265702
2025-04-01,1.240488,1.2406754,1.119298,1.1689228,1.1957527,1.2162383,1.240488,1.265359,1.2880774,1.3237736,1.3806401
2025-05-01,1.2026378,1.1969143,1.0776879,1.1280149,1.1554759,1.1801765,1.2026378,1.2274072,1.2546852,1.2890899,1.3469675
2025-06-01,1.21002,1.1963896,1.0811386,1.1352499,1.1687461,1.1853771,1.21002,1.2333429,1.255994,1.2938039,1.3532466
2025-07-01,1.2253109,1.2151253,1.0917634,1.1474797,1.176413,1.2029413,1.2253109,1.250956,1.2764856,1.3113455,1.3728349
2025-08-01,1.2421811,1.2292916,1.1043029,1.1598811,1.1929151,1.2164187,1.2421811,1.266998,1.2924675,1.3304923,1.394975
2025-09-01,1.269735,1.2603163,1.1239274,1.1872942,1.2162873,1.242951,1.269735,1.2976494,1.3236798,1.3580028,1.4252181
2025-10-01,1.2496669,1.2436218,1.0962446,1.1630417,1.1938806,1.221712,1.2496669,1.2757387,1.3041382,1.3376691,1.409816
2025-11-01,1.2135266,1.2031629,1.0545524,1.1223581,1.157211,1.1864623,1.2135266,1.2447275,1.2706528,1.3091388,1.3801678
2025-12-01,1.2034141,1.1867243,1.0412307,1.1113251,1.1433371,1.1752325,1.2034141,1.2308054,1.2621957,1.2912495,1.370078
1 date point_forecast mean q10 q20 q30 q40 q50 q60 q70 q80 q99 q90
2 2025-01-01 1.2593384 1.2223774 1.2215943 1.248188 1.1230627 1.140702 1.1613995 1.1880752 1.1832488 1.2137158 1.2030286 1.2394564 1.2223774 1.2593384 1.240989 1.2767732 1.2626991 1.297132 1.2927711 1.367888 1.32396 1.339603
3 2025-02-01 1.2856668 1.2563584 1.2502017 1.2773758 1.1482248 1.1406044 1.1891649 1.1960833 1.2134029 1.2322671 1.2355918 1.2593892 1.2563584 1.2856668 1.2787917 1.3110137 1.3061507 1.3400218 1.3358022 1.4253658 1.3751202 1.3880283
4 2025-03-01 1.2950127 1.286477 1.2816916 1.2869918 1.1694773 1.126852 1.2141376 1.1876173 1.2430503 1.234988 1.2636719 1.2675052 1.286477 1.2950127 1.3101407 1.328448 1.3365126 1.354729 1.3725822 1.4642649 1.4035482 1.4265702
5 2025-04-01 1.2207624 1.240488 1.2406754 1.2084007 1.119298 1.0352504 1.1689228 1.1041918 1.1957527 1.151865 1.2162383 1.1853008 1.240488 1.2207624 1.265359 1.256663 1.2880774 1.2898555 1.3237736 1.4016538 1.3310349 1.3806401
6 2025-05-01 1.1702554 1.2026378 1.1969143 1.153313 1.0776879 0.9691495 1.1280149 1.0431063 1.1554759 1.0932612 1.1801765 1.1276176 1.2026378 1.1702554 1.2274072 1.201966 1.2546852 1.2390311 1.2890899 1.3632389 1.2891905 1.3469675
7 2025-06-01 1.1455553 1.21002 1.1963896 1.1275499 1.0811386 0.94203794 1.1352499 1.0110554 1.1687461 1.0658777 1.1853771 1.1061188 1.21002 1.1455553 1.2333429 1.1806211 1.255994 1.2180579 1.2938039 1.345366 1.2702757 1.3532466
8 2025-07-01 1.1702348 1.2253109 1.2151253 1.1510556 1.0917634 0.9503718 1.1474797 1.0347577 1.176413 1.0847733 1.2029413 1.1287677 1.2253109 1.1702348 1.250956 1.2114835 1.2764856 1.2482276 1.3113455 1.3807325 1.2997853 1.3728349
9 2025-08-01 1.2026825 1.2421811 1.2292916 1.1859496 1.1043029 0.9709255 1.1598811 1.0594383 1.1929151 1.1106675 1.2164187 1.1579902 1.2421811 1.2026825 1.266998 1.2399211 1.2924675 1.2842004 1.3304923 1.419526 1.3408126 1.394975
10 2025-09-01 1.1909748 1.269735 1.2603163 1.1784849 1.1239274 0.95943713 1.1872942 1.0403702 1.2162873 1.103606 1.242951 1.1511956 1.269735 1.1909748 1.2976494 1.2390201 1.3236798 1.2832941 1.3580028 1.416972 1.3354731 1.4252181
11 2025-10-01 1.1490841 1.2496669 1.2436218 1.1264795 1.0962446 0.9079477 1.1630417 0.99529266 1.1938806 1.0548235 1.221712 1.1052223 1.2496669 1.1490841 1.2757387 1.1897774 1.3041382 1.240414 1.3376691 1.3775467 1.2868769 1.409816
12 2025-11-01 1.0804785 1.2135266 1.2031629 1.0624356 1.0545524 0.8361266 1.1223581 0.9259792 1.157211 0.9882403 1.1864623 1.0386353 1.2135266 1.0804785 1.2447275 1.1281581 1.2706528 1.1759715 1.3091388 1.3122478 1.228377 1.3801678
13 2025-12-01 1.0613453 1.2034141 1.1867243 1.0366092 1.0412307 0.80220693 1.1113251 0.89521873 1.1433371 0.9593707 1.1752325 1.0152239 1.2034141 1.0613453 1.2308054 1.1032857 1.2621957 1.15315 1.2912495 1.2959521 1.216908 1.370078
@@ -1,5 +1,5 @@
{
"model": "TimesFM 1.0 (200M) PyTorch",
"model": "TimesFM 2.5 (200M) PyTorch",
"input": {
"source": "NOAA GISTEMP Global Temperature Anomaly",
"n_observations": 36,
@@ -23,166 +23,166 @@
"2025-12"
],
"point": [
1.25933837890625,
1.285666823387146,
1.2950127124786377,
1.2207623720169067,
1.170255422592163,
1.1455552577972412,
1.1702347993850708,
1.2026824951171875,
1.1909748315811157,
1.1490840911865234,
1.080478549003601,
1.0613453388214111
1.2223774194717407,
1.2563583850860596,
1.286476969718933,
1.240488052368164,
1.202637791633606,
1.2100199460983276,
1.2253109216690063,
1.2421810626983643,
1.2697349786758423,
1.2496669292449951,
1.2135266065597534,
1.2034140825271606
],
"quantiles": {
"mean": [
1.2215943336486816,
1.25020170211792,
1.281691551208496,
1.240675449371338,
1.1969143152236938,
1.1963895559310913,
1.215125322341919,
1.229291558265686,
1.260316252708435,
1.243621826171875,
1.2031629085540771,
1.186724305152893
],
"10%": [
1.2481880187988281,
1.2773758172988892,
1.286991834640503,
1.2084007263183594,
1.1533130407333374,
1.1275498867034912,
1.1510555744171143,
1.1859495639801025,
1.1784849166870117,
1.1264795064926147,
1.0624356269836426,
1.036609172821045
1.1230627298355103,
1.1482248306274414,
1.1694773435592651,
1.119297981262207,
1.0776878595352173,
1.0811386108398438,
1.0917633771896362,
1.1043028831481934,
1.123927354812622,
1.0962445735931396,
1.054552435874939,
1.0412306785583496
],
"20%": [
1.1407020092010498,
1.1406043767929077,
1.126852035522461,
1.0352504253387451,
0.9691494703292847,
0.9420379400253296,
0.9503718018531799,
0.970925509929657,
0.9594371318817139,
0.9079477190971375,
0.8361266255378723,
0.8022069334983826
1.161399483680725,
1.1891648769378662,
1.2141375541687012,
1.168922781944275,
1.1280149221420288,
1.1352498531341553,
1.1474796533584595,
1.1598811149597168,
1.1872942447662354,
1.1630417108535767,
1.1223580837249756,
1.1113251447677612
],
"30%": [
1.1880751848220825,
1.1960833072662354,
1.187617301940918,
1.104191780090332,
1.0431063175201416,
1.01105535030365,
1.0347577333450317,
1.0594383478164673,
1.040370225906372,
0.9952926635742188,
0.9259791970252991,
0.8952187299728394
1.18324875831604,
1.2134028673171997,
1.2430503368377686,
1.195752739906311,
1.1554758548736572,
1.1687461137771606,
1.1764130592346191,
1.1929150819778442,
1.2162872552871704,
1.193880558013916,
1.1572109460830688,
1.1433371305465698
],
"40%": [
1.2137157917022705,
1.232267141342163,
1.2349879741668701,
1.151865005493164,
1.0932612419128418,
1.0658776760101318,
1.084773302078247,
1.1106674671173096,
1.1036059856414795,
1.0548235177993774,
0.9882403016090393,
0.9593706727027893
1.2030285596847534,
1.2355917692184448,
1.263671875,
1.216238260269165,
1.1801764965057373,
1.1853771209716797,
1.2029412984848022,
1.216418743133545,
1.2429510354995728,
1.2217119932174683,
1.1864622831344604,
1.1752325296401978
],
"50%": [
1.2394564151763916,
1.2593891620635986,
1.267505168914795,
1.1853008270263672,
1.127617597579956,
1.1061187982559204,
1.128767728805542,
1.1579902172088623,
1.1511956453323364,
1.1052223443984985,
1.03863525390625,
1.0152238607406616
1.2223774194717407,
1.2563583850860596,
1.286476969718933,
1.240488052368164,
1.202637791633606,
1.2100199460983276,
1.2253109216690063,
1.2421810626983643,
1.2697349786758423,
1.2496669292449951,
1.2135266065597534,
1.2034140825271606
],
"60%": [
1.25933837890625,
1.285666823387146,
1.2950127124786377,
1.2207623720169067,
1.170255422592163,
1.1455552577972412,
1.1702347993850708,
1.2026824951171875,
1.1909748315811157,
1.1490840911865234,
1.080478549003601,
1.0613453388214111
1.2409889698028564,
1.2787916660308838,
1.3101407289505005,
1.2653590440750122,
1.2274072170257568,
1.2333428859710693,
1.2509560585021973,
1.266998052597046,
1.2976493835449219,
1.2757387161254883,
1.2447274923324585,
1.2308053970336914
],
"70%": [
1.27677321434021,
1.3110136985778809,
1.3284480571746826,
1.2566629648208618,
1.2019660472869873,
1.1806211471557617,
1.2114834785461426,
1.2399210929870605,
1.2390201091766357,
1.1897773742675781,
1.1281580924987793,
1.1032856702804565
1.2626991271972656,
1.3061506748199463,
1.336512565612793,
1.2880773544311523,
1.2546851634979248,
1.2559939622879028,
1.276485562324524,
1.292467474937439,
1.323679804801941,
1.30413818359375,
1.2706527709960938,
1.2621957063674927
],
"80%": [
1.2971320152282715,
1.3400218486785889,
1.3547290563583374,
1.2898554801940918,
1.2390310764312744,
1.2180578708648682,
1.248227596282959,
1.2842004299163818,
1.2832940816879272,
1.240414023399353,
1.175971508026123,
1.153149962425232
1.2927711009979248,
1.3358021974563599,
1.372582197189331,
1.3237736225128174,
1.2890899181365967,
1.2938039302825928,
1.3113454580307007,
1.3304922580718994,
1.358002781867981,
1.3376691341400146,
1.3091387748718262,
1.2912495136260986
],
"90%": [
1.3239599466323853,
1.3751201629638672,
1.403548240661621,
1.3310348987579346,
1.2891905307769775,
1.2702757120132446,
1.2997852563858032,
1.3408125638961792,
1.3354730606079102,
1.286876916885376,
1.2283769845962524,
1.2169079780578613
],
"99%": [
1.3678879737854004,
1.4253658056259155,
1.4642648696899414,
1.40165376663208,
1.3632389307022095,
1.3453660011291504,
1.380732536315918,
1.4195259809494019,
1.416972041130066,
1.3775466680526733,
1.3122477531433105,
1.2959520816802979
1.3396029472351074,
1.3880282640457153,
1.426570177078247,
1.3806401491165161,
1.3469674587249756,
1.3532465696334839,
1.3728349208831787,
1.394974946975708,
1.425218105316162,
1.409816026687622,
1.380167841911316,
1.3700779676437378
]
}
},
"summary": {
"forecast_mean_c": 1.186,
"forecast_max_c": 1.295,
"forecast_min_c": 1.061,
"vs_last_year_mean": -0.067
"forecast_mean_c": 1.235,
"forecast_max_c": 1.286,
"forecast_min_c": 1.203,
"vs_last_year_mean": -0.017
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

After

Width:  |  Height:  |  Size: 147 KiB

@@ -11,6 +11,7 @@ from pathlib import Path
import numpy as np
import pandas as pd
import timesfm
# Preflight check
print("=" * 60)
@@ -35,27 +36,28 @@ print(
# TimesFM expects a list of 1D numpy arrays
input_series = df["anomaly_c"].values.astype(np.float32)
# Load TimesFM 1.0 (PyTorch)
# NOTE: TimesFM 2.5 PyTorch checkpoint has a file format issue at time of writing.
# The model.safetensors file is not loadable via torch.load().
# Using TimesFM 1.0 PyTorch which works correctly.
print("\n🤖 Loading TimesFM 1.0 (200M) PyTorch...")
import timesfm
# Load TimesFM 2.5 (PyTorch)
print("\n🤖 Loading TimesFM 2.5 (200M) PyTorch...")
hparams = timesfm.TimesFmHparams(horizon_len=12)
checkpoint = timesfm.TimesFmCheckpoint(
huggingface_repo_id="google/timesfm-1.0-200m-pytorch"
model = timesfm.TimesFM_2p5_200M_torch.from_pretrained(
"google/timesfm-2.5-200m-pytorch",
torch_compile=False,
)
model = timesfm.TimesFm(hparams=hparams, checkpoint=checkpoint)
model.compile(timesfm.ForecastConfig(
max_context=512,
max_horizon=12,
normalize_inputs=True,
use_continuous_quantile_head=True,
fix_quantile_crossing=True,
))
# Forecast
print("\n📈 Running forecast (12 months ahead)...")
forecast_input = [input_series]
frequency_input = [0] # Monthly data
point_forecast, experimental_quantile_forecast = model.forecast(
forecast_input,
freq=frequency_input,
horizon=12,
inputs=forecast_input,
)
print(f" Point forecast shape: {point_forecast.shape}")
@@ -65,9 +67,8 @@ print(f" Quantile forecast shape: {experimental_quantile_forecast.shape}")
point = point_forecast[0] # Shape: (horizon,)
quantiles = experimental_quantile_forecast[0] # Shape: (horizon, num_quantiles)
# TimesFM quantiles: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.99]
# Index mapping: 0=10%, 1=20%, ..., 4=50% (median), ..., 9=99%
quantile_labels = ["10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "99%"]
# TimesFM 2.5 columns: 0=mean, 1=10%, 2=20%, ..., 5=50% (median), ..., 9=90%
quantile_labels = ["mean", "10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%"]
# Create forecast dates (2025 monthly)
last_date = df["date"].max()
@@ -80,16 +81,16 @@ output_df = pd.DataFrame(
{
"date": forecast_dates.strftime("%Y-%m-%d"),
"point_forecast": point,
"q10": quantiles[:, 0],
"q20": quantiles[:, 1],
"q30": quantiles[:, 2],
"q40": quantiles[:, 3],
"q50": quantiles[:, 4], # Median
"q60": quantiles[:, 5],
"q70": quantiles[:, 6],
"q80": quantiles[:, 7],
"q90": quantiles[:, 8],
"q99": quantiles[:, 9],
"mean": quantiles[:, 0],
"q10": quantiles[:, 1],
"q20": quantiles[:, 2],
"q30": quantiles[:, 3],
"q40": quantiles[:, 4],
"q50": quantiles[:, 5], # Median
"q60": quantiles[:, 6],
"q70": quantiles[:, 7],
"q80": quantiles[:, 8],
"q90": quantiles[:, 9],
}
)
@@ -100,7 +101,7 @@ output_df.to_csv(output_dir / "forecast_output.csv", index=False)
# JSON output for the report
output_json = {
"model": "TimesFM 1.0 (200M) PyTorch",
"model": "TimesFM 2.5 (200M) PyTorch",
"input": {
"source": "NOAA GISTEMP Global Temperature Anomaly",
"n_observations": len(df),
@@ -135,24 +136,24 @@ print("=" * 60)
print(
f"\n📅 Forecast period: {forecast_dates[0].strftime('%Y-%m')} to {forecast_dates[-1].strftime('%Y-%m')}"
)
print(f"\n🌡️ Temperature Anomaly Forecast (°C above 1951-1980 baseline):")
print(f"\n {'Month':<10} {'Point':>8} {'80% CI':>15} {'90% CI':>15}")
print("\n🌡️ Temperature Anomaly Forecast (°C above 1951-1980 baseline):")
print(f"\n {'Month':<10} {'Point':>8} {'60% CI':>15} {'80% CI':>15}")
print(f" {'-' * 10} {'-' * 8} {'-' * 15} {'-' * 15}")
for i, (date, pt, q10, q90, q05, q95) in enumerate(
for i, (date, pt, q20, q80, q10, q90) in enumerate(
zip(
forecast_dates.strftime("%Y-%m"),
point,
quantiles[:, 1], # 20%
quantiles[:, 7], # 80%
quantiles[:, 0], # 10%
quantiles[:, 8], # 90%
quantiles[:, 2], # 20%
quantiles[:, 8], # 80%
quantiles[:, 1], # 10%
quantiles[:, 9], # 90%
)
):
print(
f" {date:<10} {pt:>8.3f} [{q10:>6.3f}, {q90:>6.3f}] [{q05:>6.3f}, {q95:>6.3f}]"
f" {date:<10} {pt:>8.3f} [{q20:>6.3f}, {q80:>6.3f}] [{q10:>6.3f}, {q90:>6.3f}]"
)
print(f"\n📊 Summary Statistics:")
print("\n📊 Summary Statistics:")
print(f" Mean forecast: {point.mean():.3f}°C")
print(
f" Max forecast: {point.max():.3f}°C (Month: {forecast_dates[point.argmax()].strftime('%Y-%m')})"
@@ -162,6 +163,6 @@ print(
)
print(f" vs 2024 mean: {point.mean() - df['anomaly_c'].iloc[-12:].mean():+.3f}°C")
print(f"\n✅ Output saved to:")
print("\n✅ Output saved to:")
print(f" {output_dir / 'forecast_output.csv'}")
print(f" {output_dir / 'forecast_output.json'}")
@@ -16,6 +16,8 @@ from __future__ import annotations
import json
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
@@ -57,11 +59,11 @@ def main() -> None:
label="Historical (NOAA GISTEMP)",
)
# Plot 90% CI (outer band)
ax.fill_between(dates, q10, q90, alpha=0.2, color="#dc2626", label="90% CI")
# Plot 80% CI (outer band)
ax.fill_between(dates, q10, q90, alpha=0.2, color="#dc2626", label="80% CI")
# Plot 80% CI (inner band)
ax.fill_between(dates, q20, q80, alpha=0.3, color="#dc2626", label="80% CI")
# Plot 60% CI (inner band)
ax.fill_between(dates, q20, q80, alpha=0.3, color="#dc2626", label="60% CI")
# Plot point forecast
ax.plot(