File size: 5,406 Bytes
f15767b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/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
    }