GWLSTM / inference.py
kozy9's picture
Upload LSTM — test RMSE 2.9386 m R² 0.5505
3d62172 verified
"""
inference.py — LSTM Groundwater Level Forecasting
==================================================
Usage
-----
from inference import load_model, forecast
model, scaler_X, scaler_y = load_model()
prediction = forecast(model, scaler_X, scaler_y, X_window)
"""
import json
import joblib
import numpy as np
import pandas as pd
from pathlib import Path
from tensorflow.keras.models import load_model as keras_load
MODEL_PATH = Path(__file__).parent / "lstm_model.keras"
SCALER_X_PATH = Path(__file__).parent / "scaler_X.pkl"
SCALER_Y_PATH = Path(__file__).parent / "scaler_y.pkl"
CONFIG_PATH = Path(__file__).parent / "model_config.json"
def load_model():
"""Load the LSTM model and both scalers."""
model = keras_load(MODEL_PATH)
scaler_X = joblib.load(SCALER_X_PATH)
scaler_y = joblib.load(SCALER_Y_PATH)
print("LSTM model and scalers loaded.")
return model, scaler_X, scaler_y
def load_config():
with open(CONFIG_PATH) as f:
return json.load(f)
def forecast(model, scaler_X, scaler_y, X_window: pd.DataFrame):
"""
Predict the next month's groundwater level.
Parameters
----------
model : loaded Keras model
scaler_X : fitted MinMaxScaler for features
scaler_y : fitted MinMaxScaler for target
X_window : DataFrame with columns [water_level, temperature,
precipitation, wind_speed] and exactly 24 rows
(the lookback window)
Returns
-------
prediction : float — forecasted water level in original units (m)
"""
cfg = load_config()
required = cfg['features']
lookback = cfg['lookback_months']
missing = [c for c in required if c not in X_window.columns]
if missing:
raise ValueError(f"X_window is missing columns: {missing}")
if len(X_window) != lookback:
raise ValueError(f"X_window must have {lookback} rows, got {len(X_window)}")
X_scaled = scaler_X.transform(X_window[required])
X_input = X_scaled.reshape(1, lookback, len(required))
y_scaled = model.predict(X_input, verbose=0).flatten()
prediction = scaler_y.inverse_transform(y_scaled.reshape(-1, 1)).flatten()[0]
return float(prediction)
if __name__ == "__main__":
model, scaler_X, scaler_y = load_model()
cfg = load_config()
print(f"Model: {cfg['architecture']}")
print(f"Test RMSE: {cfg['test_metrics']['RMSE']} m")
# Dummy window — replace with real data
import numpy as np
dummy = pd.DataFrame({
'water_level' : np.random.uniform(60, 75, 24),
'temperature' : np.random.uniform(3, 15, 24),
'precipitation': np.random.uniform(20, 120, 24),
'wind_speed' : np.random.uniform(10, 25, 24),
})
pred = forecast(model, scaler_X, scaler_y, dummy)
print(f"\nForecast (next month): {pred:.4f} m")