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
Download example.py from GuillaumeGay/firepredict: direct link, hf CLI and curl.
- Browser
- Download file 4.82 kB
-
https://huggingface.co/GuillaumeGay/firepredict/resolve/main/example.py
- Command line
-
hf download hf://GuillaumeGay/firepredict/example.py
-
curl -L -o example.py https://huggingface.co/GuillaumeGay/firepredict/resolve/main/example.py
4.82 kB
| """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()}") | |