#!/usr/bin/env python # encoding: utf-8 from fastapi import FastAPI, Form, Depends from pydantic import BaseModel import numpy as np import pandas as pd from xgboost import XGBRegressor from sklearn.preprocessing import StandardScaler from sklearn.preprocessing import MinMaxScaler from sklearn.preprocessing import RobustScaler from skforecast.ForecasterAutoreg import ForecasterAutoreg from sklearn.metrics import mean_squared_error, mean_absolute_percentage_error import joblib app = FastAPI() class Msg(BaseModel): msg: str class RetrainRequest(BaseModel): lag: int differentiation: str transformer: str externalTransformation: str test_size: int class PredictRequest(BaseModel): steps: int test_size: int externalTransformation: str @app.get("/welcomeMessage") async def welcome(): return {"message": "Hello World. Welcome to FastAPI!"} @app.get("/") async def root(): return {"message": "Hello World"} def form_retrain(lag: str = Form(...), differentiation: str = Form(...), transformer: str = Form(...), externalTransformation: str = Form (...), test_size: str = Form(...)): return RetrainRequest(lag=int(lag), differentiation=str(differentiation), transformer=transformer, externalTransformation=externalTransformation, test_size=int(test_size)) def form_prediction(steps: str = Form(...), externalTransformation: str = Form (...), test_size: str = Form(...)): return PredictRequest(steps=int(steps), externalTransformation=externalTransformation, test_size=int(test_size)) def apply_transformation(data, transform_type): if transform_type == 'Log': return np.log1p(data) elif transform_type == 'Square Root': return np.sqrt(data) else: return data def reverse_transformation(transformed_data, transform_type): if transform_type == 'Log': return np.expm1(transformed_data) elif transform_type == 'Square Root': return np.square(transformed_data) else: return transformed_data @app.post("/retrain") async def retrain(requess: RetrainRequest = Depends(form_retrain), test_size: int = 3): with open('ammonia_market_monthly_avg_new.xlsx', 'rb') as file: df = pd.read_excel(file) df['date'] = pd.to_datetime(df['date'], format='%Y-%m-%d') df.set_index('date', inplace=True) lags = requess.lag differentiation = requess.differentiation if differentiation == "0": differentiation = None else: differentiation = int(differentiation) transformer_y = requess.transformer test_size = requess.test_size externalTransformation=requess.externalTransformation target_column = 'southeast_asia' train = df.iloc[:-(test_size)] test = df.iloc[-(test_size):] train_transformed = apply_transformation(train[target_column], externalTransformation) if transformer_y == 'StandardScaler': transformer_y = StandardScaler() elif transformer_y == 'MinMaxScaler': transformer_y = MinMaxScaler() elif transformer_y == 'RobustScaler': transformer_y = RobustScaler() else: transformer_y = None forecaster = ForecasterAutoreg( regressor = XGBRegressor(random_state=123), lags = lags, differentiation = differentiation, transformer_y = transformer_y ) forecaster.fit(y=train_transformed) predictions = forecaster.predict(steps=test_size) pred = reverse_transformation(predictions, externalTransformation) df_reset = df.reset_index() last_date = df_reset.iloc[-(test_size)]['date'] months_ahead = pd.date_range(last_date, periods=test_size, freq='M') preds = round(pred, 2).tolist() actual = test[target_column] date_value_pairs = dict(zip(months_ahead.tolist(), preds)) rmse = np.sqrt(mean_squared_error(actual, preds)) mape = mean_absolute_percentage_error(actual, preds) joblib.dump(forecaster, filename='forecaster_new.py') return { 'predictions': date_value_pairs, 'actual': actual, 'rmse': rmse, 'mape': mape } @app.post("/predict") async def predict(requess: PredictRequest = Depends(form_prediction), steps: int = 3, externalTransformation: str = "None", test_size: int = 3): try: with open('forecaster_new.py', 'rb') as file: forecaster_southeast = joblib.load(file) except FileNotFoundError: forecaster_southeast = joblib.load('forecaster_southeast.py') try: with open('ammonia_market_monthly_avg_new.xlsx', 'rb') as file: df = pd.read_excel(file) except FileNotFoundError: df = pd.read_excel('ammonia_market_monthly_avg_2010_2020.xlsx') df['date'] = pd.to_datetime(df['date'], format='%Y-%m-%d') df.set_index('date', inplace=True) steps = requess.steps test_size = requess.test_size predictions = forecaster_southeast.predict(steps=steps) pred = reverse_transformation(predictions, requess.externalTransformation) preds = round(pred, 2).tolist() df_reset = df.reset_index() last_date = df_reset.iloc[-(test_size)]['date'] months_ahead = pd.date_range(last_date, periods=steps, freq='M') date_value_pairs = dict(zip(months_ahead.tolist(), preds)) return { "steps": steps, "predictions": date_value_pairs }