Tabular Classification
Scikit-learn
Joblib
English
French
wildfire
fire-weather-index
scikit-learn
logistic-regression
france
var
open-data
Instructions to use GuillaumeGay/firepredict with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Scikit-learn
How to use GuillaumeGay/firepredict with Scikit-learn:
from huggingface_hub import hf_hub_download import joblib model = joblib.load( hf_hub_download("GuillaumeGay/firepredict", "sklearn_model.joblib") ) # only load pickle files from sources you trust # read more about it here https://skops.readthedocs.io/en/stable/persistence.html - Notebooks
- Google Colab
- Kaggle
File size: 4,817 Bytes
7bbbbf6 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | """Load the frozen firepredict model and compute a chance for one commune-day.
Run from this folder:
uv run --with scikit-learn==1.9.1 --with joblib --with pandas python example.py
The model answers: what is the chance that at least one fire of 0.1 ha or more
starts in this Var commune on the target day? The forecast is issued on the
morning of the day before the target day and uses weather up to two days
before the target day.
The five inputs (one row per commune and target day):
log_usual_rate log(usual_rate + 0.01). usual_rate is the commune's average
number of days per year with at least one fire start of
0.1 ha or more (BDIFF, 2006-2025 without 2024). Take it from
usual_rates.csv by INSEE code.
log_local_fwi log(1 + FWI). FWI is the Fire Weather Index (no unit) of the
day two days before the target day, computed from the
commune's nearest Météo-France stations with daily values
(maximum temperature, minimum humidity, mean wind, daily
rain). It is an approximation, not the official FWI product.
local_wb_30d Rain minus potential evaporation (Météo-France ETP), in mm,
summed over the 30 days that end two days before the target
day, at the commune's nearest stations. Negative = dry.
orange_period 1 if the target day is in February or March (brush burning
allowed under conditions, Var prefectoral orders), else 0.
red_period 1 if the target day is in June to September (fire use
banned), else 0.
A missing input is replaced with the training median stored in
metadata.json ("fill_values"), as the frozen pipeline does.
To build these inputs from raw data (weather download, station matching,
FWI), use the code at https://github.com/guillaumegay13/firepredict
(firepredict.model_communes.build_panel and firepredict.freeze.predict).
This is a research preview, not an official warning tool. Fire danger
warnings in France come from Météo-France and the prefectures.
"""
import hashlib
import json
from pathlib import Path
import joblib
import numpy as np
import pandas as pd
import sklearn
HERE = Path(__file__).parent
def sha256(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
# The pipeline was saved with scikit-learn 1.9.1; older versions fail to load it.
if sklearn.__version__ != "1.9.1":
print(f"warning: scikit-learn {sklearn.__version__} found, the model was saved with 1.9.1")
metadata = json.loads((HERE / "metadata.json").read_text())
# joblib files are pickles: only load files whose fingerprint you trust.
assert sha256(HERE / "model.joblib") == metadata["model_sha256"], "model.joblib does not match metadata.json"
assert sha256(HERE / "forecasts_2026.csv") == metadata["forecasts_2026"]["sha256"], "forecasts_2026.csv changed"
model = joblib.load(HERE / "model.joblib")
rates = pd.read_csv(HERE / "usual_rates.csv", dtype={"insee": str}).set_index("insee").usual_rate
def inputs(insee: str, fwi: float, wb_30d_mm: float, target_month: int) -> pd.DataFrame:
"""One row of the five model inputs, in the order the model expects."""
row = {
"log_usual_rate": np.log(rates.get(insee, np.nan) + 0.01),
"log_local_fwi": np.log1p(fwi),
"local_wb_30d": wb_30d_mm,
"orange_period": int(target_month in (2, 3)),
"red_period": int(target_month in (6, 7, 8, 9)),
}
X = pd.DataFrame([row])[metadata["inputs"]]
return X.fillna(pd.Series(metadata["fill_values"]))
examples = [
# (description, INSEE code, FWI two days before, 30-day rain - evaporation in mm, month of target day)
("Toulon, dry July day", "83137", 35.0, -140.0, 7),
("Toulon, February day", "83137", 8.0, -20.0, 2),
("Toulon, wet November day", "83137", 2.0, 60.0, 11),
]
print(f"model {metadata['version']}, frozen {metadata['frozen_at']}, inputs {metadata['inputs']}")
print(f"usual rate of Toulon (83137): {rates['83137']:.3f} days with a fire start per year\n")
for label, insee, fwi, wb, month in examples:
X = inputs(insee, fwi, wb, month)
chance = model.predict_proba(X)[0, 1]
# Same result by hand: standardise, weighted sum, logistic function.
scaler, logit = model[0], model[-1]
z = ((X.to_numpy()[0] - scaler.mean_) / scaler.scale_) @ logit.coef_[0] + logit.intercept_[0]
assert np.isclose(chance, 1 / (1 + np.exp(-z)))
print(f"{label:28s} {X.round(3).to_dict('records')[0]}")
print(f"{'':28s} chance of a fire start: {chance:.4%}\n")
forecasts = pd.read_csv(HERE / "forecasts_2026.csv", dtype={"insee": str})
print(f"forecasts_2026.csv: {len(forecasts)} rows, {forecasts.target_day.min()} to {forecasts.target_day.max()}")
|