Skip to content

Commit 1e2061b

Browse files
guerrantifrusty1s
andauthored
[TimesFM3 12/n] Prepare fev-bench data (#1117)
Adds a per-model preparation step to the fev-bench connector and uses it to prepare data for TimesFM3 as in the published TimesFM-3 fev-bench evaluation. --------- Co-authored-by: Matthias Fey <matthias.fey@tu-dortmund.de>
1 parent 8f1d20e commit 1e2061b

2 files changed

Lines changed: 43 additions & 43 deletions

File tree

‎benchmark/timeseries/fev_bench/evaluate.py‎

Lines changed: 24 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -16,45 +16,27 @@
1616
METRICS = ("SQL", "MASE")
1717

1818

19-
def main() -> None:
20-
benchmark_dir = Path(__file__).parent.parent
21-
result_root = benchmark_dir / "fev_bench_out"
22-
output_root = benchmark_dir / "evals" / "fev_bench"
23-
24-
summaries = []
25-
for model_config in MODEL_CONFIGS.values():
26-
path = result_root / model_config.name / "results.csv"
27-
if path.exists():
28-
summaries.append(pd.read_csv(path))
29-
30-
if not summaries:
31-
raise FileNotFoundError(
32-
f"No fev-bench results found under {result_root}"
33-
)
34-
35-
# Compare with published results on tasks run by all models:
36-
tasks = set.intersection(*(set(df["task_name"]) for df in summaries))
37-
for name in REFERENCES:
38-
path = f"{FEV_BENCH_URL}/benchmarks/fev_bench/results/{name}.csv"
39-
summaries.append(pd.read_csv(path))
40-
summaries = pd.concat(summaries)
41-
summaries = summaries[summaries["task_name"].isin(tasks)]
42-
43-
output_root.mkdir(parents=True, exist_ok=True)
44-
for metric in METRICS:
45-
leaderboard = fev.leaderboard(
46-
summaries,
47-
metric_column=metric,
48-
baseline_model=BASELINE,
49-
)
50-
leaderboard.to_csv(output_root / f"leaderboard_{metric}.csv")
51-
print(f"\nfev-bench leaderboard ({metric}, {len(tasks)} tasks):")
52-
print(
53-
leaderboard[["skill_score", "win_rate"]].to_string(
54-
float_format="%.4f"
55-
)
56-
)
57-
58-
59-
if __name__ == "__main__":
60-
main()
19+
benchmark_dir = Path(__file__).parent.parent
20+
result_root = benchmark_dir / "fev_bench_out"
21+
output_root = benchmark_dir / "evals" / "fev_bench"
22+
23+
dfs = []
24+
for config in MODEL_CONFIGS.values():
25+
path = result_root / config.name / "results.csv"
26+
if path.exists():
27+
dfs.append(pd.read_csv(path))
28+
tasks = set.intersection(*(set(df["task_name"]) for df in dfs))
29+
30+
for name in REFERENCES:
31+
url = f"{FEV_BENCH_URL}/benchmarks/fev_bench/results/{name}.csv"
32+
dfs.append(pd.read_csv(url))
33+
34+
df = pd.concat(dfs)
35+
df = df[df["task_name"].isin(tasks)]
36+
37+
for i, metric in enumerate(METRICS):
38+
if i > 0:
39+
print()
40+
summary = fev.leaderboard(df, metric, baseline_model=BASELINE)
41+
print(f"fev-bench leaderboard ({metric}, {len(tasks)} tasks):")
42+
print(summary[["skill_score", "win_rate"]].to_string(float_format="%.4f"))

‎benchmark/timeseries/fev_bench/predictor.py‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
# SPDX-License-Identifier: Apache-2.0
33

4+
import zlib
45
from collections.abc import Iterator
56

67
import datasets
@@ -146,7 +147,7 @@ def _fit_predict(self, task: fev.Task) -> list[datasets.DatasetDict]:
146147

147148
pred = torch.cat(preds, dim=-2)[..., : y.size(-1), :]
148149
pred = pred.cpu().numpy() # [B, R, C, Q]
149-
levels = out.numerical_columns[: pred.shape[1]]
150+
levels = out.numerical_columns[: pred.shape[-1]]
150151
levels = [float(f"0.{q.split('q')[-1]}") for q in levels]
151152
wanted = [0.5, *task.quantile_levels]
152153
index = [levels.index(q) for q in wanted]
@@ -174,11 +175,28 @@ def _from(
174175
columns: list[str],
175176
batch_size: int,
176177
) -> Iterator[list[torch.Tensor]]:
178+
string_columns = [
179+
column
180+
for column in columns
181+
if dataset.features[column].feature.dtype in ("string", "large_string")
182+
]
183+
177184
for batch in dataset.with_format("numpy").iter(batch_size):
178185
if not columns:
179186
yield []
180187
continue
181188

189+
for column in string_columns:
190+
batch[column] = [
191+
[
192+
zlib.crc32(value.encode()) % 100
193+
if isinstance(value, str)
194+
else 0
195+
for value in values
196+
]
197+
for values in batch[column]
198+
]
199+
182200
yield [
183201
torch.from_numpy(
184202
np.asarray(

0 commit comments

Comments
 (0)