MeteoNorm-RF / scripts /inference.py
zhangrenchao's picture
Publish MeteoNorm-RF reproduction
b11ef36 verified
Raw
History Blame Contribute Delete
2.54 kB
"""Predict the test set and perform hour/season-window weather normalization."""
import sys
from pathlib import Path
import numpy as np
import yaml
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
from model.meteonorm_rf import BASE_FEATURES, encode_features, load_checkpoint
def circular_day_distance(a, b):
distance = np.abs(a - b)
return np.minimum(distance, 365 - distance)
def main():
config = yaml.safe_load((ROOT / "conf/config.yaml").read_text())
data = np.load(ROOT / config["data"]["path"])
model, metadata = load_checkpoint(ROOT / config["paths"]["checkpoint"])
x = encode_features(data)
test = np.asarray(metadata["test_indices"], dtype=np.int64)
observed = data["pollution"][test]
predicted = model.predict(x[test])
repeats = int(config["normalization"]["engineering_resamples"])
window = int(config["normalization"]["season_window_days"])
rng = np.random.default_rng(int(config["seed"]) + 17)
normalized = np.empty_like(predicted)
weather_columns = [BASE_FEATURES.index(name) for name in
("wind_speed", "wind_direction", "pressure", "temperature", "relative_humidity")]
all_hour, all_doy = data["hour"], data["day_of_year"]
for output_index, row_index in enumerate(test):
candidates = np.flatnonzero((all_hour == all_hour[row_index]) &
(circular_day_distance(all_doy, all_doy[row_index]) <= window))
draws = rng.choice(candidates, repeats, replace=True)
replicated = np.repeat(x[row_index:row_index + 1], repeats, axis=0)
replicated[:, weather_columns] = x[draws][:, weather_columns]
# ttrend, day-of-year, weekend, hour, and station remain at the target time/station.
normalized[output_index] = model.predict(replicated).mean(0)
output = ROOT / config["paths"]["inference"]
output.parent.mkdir(parents=True, exist_ok=True)
np.savez_compressed(output, test_indices=test, observed=observed, predicted=predicted,
normalized=normalized, ttrend=data["ttrend"][test],
day_of_year=data["day_of_year"][test], hour=data["hour"][test],
station_id=data["station_id"][test], pollutant_names=data["pollutant_names"],
resamples=np.array(repeats), season_window_days=np.array(window))
print(f"predictions={output.relative_to(ROOT)} test_rows={len(test)} normalization_resamples={repeats}")
if __name__ == "__main__":
main()