|
import streamlit as st |
|
from src.data import Energy_DataLoader |
|
from src.model import Model_Load |
|
import matplotlib.pyplot as plt |
|
import seaborn as sns |
|
import plotly.graph_objects as go |
|
from sklearn.metrics import mean_absolute_error,mean_squared_error |
|
import numpy as np |
|
import pandas as pd |
|
from streamlit.components.v1 import html |
|
from src.prediction import test_pred,val_pred |
|
|
|
model_obj=Model_Load() |
|
|
|
|
|
path='data/LD2011_2014.txt' |
|
obj=Energy_DataLoader(path) |
|
|
|
@st.cache_data |
|
def convert_df(df): |
|
return df.to_csv(index=False).encode('utf-8') |
|
|
|
|
|
st.markdown(""" |
|
<div style='text-align: center; margin-top:-70px; margin-bottom: 5px;margin-left: -50px;'> |
|
<h2 style='font-size: 20px; font-family: Courier New, monospace; |
|
letter-spacing: 2px; text-decoration: none;'> |
|
<img src="https://acis.affineanalytics.co.in/assets/images/logo_small.png" alt="logo" width="70" height="30"> |
|
<span style='background: linear-gradient(45deg, #ed4965, #c05aaf); |
|
-webkit-background-clip: text; |
|
-webkit-text-fill-color: transparent; |
|
text-shadow: none;'> |
|
Energy Demand Forecasting Dashboard |
|
</span> |
|
<span style='font-size: 40%;'> |
|
<sup style='position: relative; top: 5px; color: #ed4965;'>by Affine</sup> |
|
</span> |
|
</h2> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
with st.sidebar: |
|
st.markdown("""<div style='text-align: left; margin-top:-200px;margin-left:-40px;'> |
|
<img src="https://affine.ai/wp-content/uploads/2023/05/Affine-Logo.svg" alt="logo" width="300" height="60"> |
|
</div>""", unsafe_allow_html=True) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
option=st.selectbox("Select Model",['TFT','Prophet']) |
|
|
|
if option=='TFT': |
|
print("TFT") |
|
|
|
train_dataset,test_dataset,training,validation,earliest_time=obj.tft_data() |
|
|
|
print(f"TRAINING ::START DATE ::{train_dataset['date'].min()} :: END DATE ::{train_dataset['date'].max()}") |
|
print(f"TESTING ::START DATE ::{test_dataset['date'].min()} :: END DATE ::{test_dataset['date'].max()}") |
|
consumer_list=train_dataset['consumer_id'].unique() |
|
model=model_obj.energy_model_load(option) |
|
with st.sidebar: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
consumer=st.selectbox("Select Consumer ID",consumer_list) |
|
testing_results=test_pred(model,train_dataset=train_dataset,test_dataset=test_dataset |
|
,consumer_id=consumer) |
|
rmse=np.around(np.sqrt(mean_squared_error(testing_results['Lead_1'],testing_results['prediction'])),2) |
|
mae=np.around(mean_absolute_error(testing_results['Lead_1'],testing_results['prediction']),2) |
|
|
|
final_data=pd.concat([train_dataset,test_dataset]) |
|
consumer_data=final_data.loc[final_data['consumer_id']==consumer] |
|
consumer_data.fillna(0,inplace=True) |
|
date_list=[] |
|
demand_prediction=[] |
|
for i in range(24): |
|
encoder_data = consumer_data[lambda x: x.hours_from_start > x.hours_from_start.max() - 192] |
|
last_data = consumer_data[lambda x: x.hours_from_start == x.hours_from_start.max()] |
|
|
|
|
|
date_list.append(encoder_data.tail(1).iloc[-1,:]['date']) |
|
|
|
test_prediction = model.predict(encoder_data, |
|
mode="prediction", |
|
trainer_kwargs=dict(accelerator="cpu"), |
|
return_x=True) |
|
decoder_data = pd.concat( |
|
[last_data.assign(date=lambda x: x.date + pd.offsets.Hour(i)) for i in range(1, 2)], |
|
ignore_index=True, |
|
) |
|
decoder_data['hours_from_start']=decoder_data['hours_from_start'].max()+1 |
|
decoder_data["days_from_start"] = (decoder_data["date"] - earliest_time).apply(lambda x:x.days) |
|
decoder_data['hour'] = decoder_data['date'].dt.hour |
|
decoder_data['day'] = decoder_data['date'].dt.day |
|
decoder_data['day_of_week'] = decoder_data['date'].dt.dayofweek |
|
decoder_data['month'] = decoder_data['date'].dt.month |
|
decoder_data['power_usage']=float(test_prediction.output[0][-1]) |
|
demand_prediction.append(float(test_prediction.output[0][-1])) |
|
decoder_data['time_idx']=int(test_prediction.x['decoder_time_idx'][0][-1]) |
|
consumer_data=pd.concat([consumer_data,decoder_data]) |
|
consumer_data['lag_1']=consumer_data['power_usage'].shift(1) |
|
consumer_data['lag_5']=consumer_data['power_usage'].shift(5) |
|
consumer_data=consumer_data.reset_index(drop=True) |
|
d2=pd.DataFrame({"date":date_list,"prediction":demand_prediction})[['date','prediction']] |
|
d2['consumer_id']=consumer |
|
print(f"TEST DATA = Consumer ID : {consumer} :: MAE : {mae} :: RMSE : {rmse}") |
|
with st.sidebar: |
|
st.markdown(f""" |
|
<style> |
|
/* Sidebar header style */ |
|
.sidebar-header {{ |
|
padding: 1px; |
|
background-color: #9966FF; |
|
text-align: center; |
|
font-size: 13px; |
|
font-weight: bold; |
|
color: #FFF ; |
|
}} |
|
</style> |
|
|
|
<div class="sidebar-header"> |
|
Models Evalution |
|
</div> |
|
""",unsafe_allow_html=True) |
|
|
|
st.dataframe(pd.DataFrame({"KPI":['RMSE','MAE'],"TFT":[8.67,6.48],"Prophet":[12.82,9.79]}).set_index('KPI'),width=300) |
|
st.markdown(f""" |
|
<style> |
|
/* Sidebar header style */ |
|
.sidebar-header {{ |
|
padding: 1px; |
|
background-color:linear-gradient(45deg, #ed4965, #c05aaf); |
|
text-align: center; |
|
font-size: 13px; |
|
font-weight: bold; |
|
color: #FFF ; |
|
}} |
|
</style> |
|
|
|
<div class="sidebar-header"> |
|
KPI :: {consumer} |
|
</div> |
|
""",unsafe_allow_html=True) |
|
st.dataframe(pd.DataFrame({"KPI":['RMSE','MAE'],"TFT":[rmse,mae]}).set_index('KPI'),width=300) |
|
|
|
|
|
tab1,tab2=st.tabs(['📈Forecast Plot','🗃Forecast Table']) |
|
|
|
|
|
tab1.markdown(""" |
|
<div style='text-align: left; margin-top:-10px;margin-bottom:-10px;'> |
|
<h2 style='font-size: 30px; font-family: Palatino, serif; |
|
letter-spacing: 2px; text-decoration: none;'> |
|
📈 |
|
<span style='background: linear-gradient(45deg, #ed4965, #c05aaf); |
|
-webkit-background-clip: text; |
|
-webkit-text-fill-color: transparent; |
|
text-shadow: none;'> |
|
Forecast Plot |
|
</span> |
|
<span style='font-size: 40%;'> |
|
<sup style='position: relative; top: 5px; color: #ed4965;'></sup> |
|
</span> |
|
</h2> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
training_data=train_dataset.loc[(train_dataset['consumer_id']==consumer)][['date','Lead_1']].iloc[-100:,:] |
|
fig = go.Figure([ |
|
|
|
|
|
go.Scatter(x=testing_results['date'], y=testing_results['Lead_1'],name='Observed',line=dict(color='purple')), |
|
go.Scatter(x=testing_results['date'],y=testing_results['prediction'],name='Historical Forecast',line=dict(color='purple', dash='dot')), |
|
go.Scatter(x=d2['date'],y=d2['prediction'],name='Future Forecast',line=dict(color='Dark Orange', dash='dot'))]) |
|
fig.update_layout( |
|
xaxis_title='Date', |
|
yaxis_title='Energy Demand', |
|
margin=dict(l=0, r=0, t=50, b=0), |
|
xaxis=dict(title_font=dict(size=20)), |
|
yaxis=dict(title_font=dict(size=20))) |
|
fig.update_layout(width=900,height=400) |
|
tab1.plotly_chart(fig) |
|
|
|
tab2.markdown(""" |
|
<div style='text-align: left; margin-top:-10px;'> |
|
<h2 style='font-size: 30px; font-family: Palatino, serif; |
|
letter-spacing: 2px; text-decoration: none;'> |
|
📃 |
|
<span style='background: linear-gradient(45deg, #ed4965, #c05aaf); |
|
-webkit-background-clip: text; |
|
-webkit-text-fill-color: transparent; |
|
text-shadow: none;'> |
|
Forecast Table |
|
</span> |
|
<span style='font-size: 40%;'> |
|
<sup style='position: relative; top: 5px; color: #ed4965;'></sup> |
|
</span> |
|
</h2> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
final_r=pd.concat([d2[['date','consumer_id','prediction']],testing_results[['date','consumer_id','prediction']]]).sort_values('date').reset_index(drop=True) |
|
csv = convert_df(final_r) |
|
tab2.dataframe(final_r,width=500) |
|
tab2.download_button( |
|
"Download", |
|
csv, |
|
"file.csv", |
|
"text/csv", |
|
key='download-csv' |
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
elif option=='Prophet': |
|
print("prophet") |
|
|
|
fb_train_data,fb_test_data,consumer_dummay=obj.fb_data() |
|
|
|
|
|
|
|
print(f"TRAINING ::START DATE ::{fb_train_data['ds'].min()} :: END DATE ::{fb_train_data['ds'].max()}") |
|
print(f"TESTING ::START DATE ::{fb_test_data['ds'].min()} :: END DATE ::{fb_test_data['ds'].max()}") |
|
train_new=fb_train_data.drop('y',axis=1) |
|
test_new=fb_test_data.drop('y',axis=1) |
|
try: |
|
model=model_obj.energy_model_load(option) |
|
|
|
|
|
except: |
|
st.error('Model Not Loaded successfully!',icon="🚨") |
|
with st.sidebar: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
consumer=st.selectbox("Select Consumer ID",consumer_dummay) |
|
|
|
test_prediction=model.predict(test_new.loc[test_new[consumer]==1]) |
|
|
|
|
|
y_true_test=fb_test_data.loc[fb_test_data[consumer]==1] |
|
y_true_train=fb_train_data.loc[fb_train_data[consumer]==1] |
|
|
|
|
|
y_train_true=y_true_train[['ds','y']].iloc[-60:,:] |
|
|
|
y_test_pred=test_prediction[['ds','yhat']] |
|
y_test_true=y_true_test[['ds','y']] |
|
|
|
fb_final=pd.concat([fb_train_data,fb_test_data]) |
|
fb_consumer=fb_final.loc[fb_final[consumer]==1] |
|
date_list=[] |
|
prediction_list=[] |
|
for i in range(24): |
|
next_prediction=fb_consumer.tail(1).drop('y',axis=1) |
|
|
|
prediction=model.predict(next_prediction) |
|
|
|
|
|
|
|
date_list.append(prediction['ds'][0]) |
|
prediction_list.append(prediction['yhat'][0]) |
|
|
|
last_data = fb_consumer[lambda x: x.ds == x.ds.max()] |
|
|
|
|
|
decoder_data = pd.concat( |
|
[last_data.assign(ds=lambda x: x.ds + pd.offsets.Hour(i)) for i in range(1, 2)], |
|
ignore_index=True, |
|
) |
|
decoder_data['hour'] = decoder_data['ds'].dt.hour |
|
decoder_data['day'] = decoder_data['ds'].dt.day |
|
decoder_data['day_of_week'] = decoder_data['ds'].dt.dayofweek |
|
decoder_data['month'] = decoder_data['ds'].dt.month |
|
decoder_data['power_usage']=prediction['yhat'][0] |
|
fb_consumer=pd.concat([fb_consumer,decoder_data]) |
|
fb_consumer['lag_1']=fb_consumer['power_usage'].shift(1) |
|
fb_consumer['lag_5']=fb_consumer['power_usage'].shift(5) |
|
fb_consumer=fb_consumer.reset_index(drop=True) |
|
future_prediction=pd.DataFrame({'ds':date_list,"yhat":prediction_list}) |
|
future_prediction['consumer_id']=consumer |
|
tab1,tab2=st.tabs(['📈Forecast Plot','🗃Forecast Table']) |
|
tab1.markdown(""" |
|
<div style='text-align: left; margin-top:-10px;margin-bottom:-10px;'> |
|
<h2 style='font-size: 30px; font-family: Palatino, serif; |
|
letter-spacing: 2px; text-decoration: none;'> |
|
📈 |
|
<span style='background: linear-gradient(45deg, #ed4965, #c05aaf); |
|
-webkit-background-clip: text; |
|
-webkit-text-fill-color: transparent; |
|
text-shadow: none;'> |
|
Forecast Plot |
|
</span> |
|
<span style='font-size: 40%;'> |
|
<sup style='position: relative; top: 5px; color: #ed4965;'></sup> |
|
</span> |
|
</h2> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
y_train_true['y']=y_train_true['y'].astype('float') |
|
|
|
y_test_true['y']=y_test_true['y'].astype('float') |
|
y_test_pred['yhat']=y_test_pred['yhat'].astype('float') |
|
|
|
fig = go.Figure([ |
|
|
|
|
|
go.Scatter(x=y_test_true['ds'], y=y_test_true['y'],name='Observed',line=dict(color='purple')), |
|
go.Scatter(x=y_test_pred['ds'],y=y_test_pred['yhat'],name='Historical Forecast',line=dict(color='purple', dash='dot')), |
|
go.Scatter(x=future_prediction['ds'],y=future_prediction['yhat'],name='Future Forecast',line=dict(color='Dark Orange', dash='dot')) |
|
]) |
|
fig.update_layout( |
|
xaxis_title='Date', |
|
yaxis_title='Energy Demand', |
|
margin=dict(l=0, r=0, t=50, b=0), |
|
xaxis=dict(title_font=dict(size=20)), |
|
yaxis=dict(title_font=dict(size=20))) |
|
fig.update_layout(width=900,height=400) |
|
tab1.plotly_chart(fig) |
|
|
|
rmse=np.sqrt(mean_squared_error(y_test_true['y'],y_test_pred['yhat'])) |
|
mae=mean_absolute_error(y_test_true['y'],y_test_pred['yhat']) |
|
with st.sidebar: |
|
st.markdown(f""" |
|
<style> |
|
/* Sidebar header style */ |
|
.sidebar-header {{ |
|
padding: 1px; |
|
background-color: #9966FF; |
|
text-align: center; |
|
font-size: 13px; |
|
font-weight: bold; |
|
color: #FFF ; |
|
}} |
|
</style> |
|
|
|
<div class="sidebar-header"> |
|
Models Evalution |
|
</div> |
|
""",unsafe_allow_html=True) |
|
|
|
st.dataframe(pd.DataFrame({"KPI":['RMSE','MAE'],"TFT":[8.67,6.48],"Prophet":[12.82,9.79]}).set_index('KPI'),width=300) |
|
st.markdown(f""" |
|
<style> |
|
/* Sidebar header style */ |
|
.sidebar-header {{ |
|
padding: 2px; |
|
background-color:linear-gradient(45deg, #ed4965, #c05aaf); |
|
text-align: center; |
|
font-size: 13px; |
|
font-weight: bold; |
|
color: #FFF ; |
|
}} |
|
</style> |
|
|
|
<div class="sidebar-header"> |
|
KPI :: {consumer} |
|
</div> |
|
""",unsafe_allow_html=True) |
|
st.dataframe(pd.DataFrame({"KPI":['RMSE','MAE'],"Prophet":[rmse,mae]}), width=300) |
|
|
|
results=y_test_pred.reset_index() |
|
|
|
results['consumer_id']=consumer |
|
|
|
st.divider() |
|
|
|
tab2.markdown(""" |
|
<div style='text-align: left; margin-top:-10px;'> |
|
<h2 style='font-size: 30px; font-family: Palatino, serif; |
|
letter-spacing: 2px; text-decoration: none;'> |
|
📃 |
|
<span style='background: linear-gradient(45deg, #ed4965, #c05aaf); |
|
-webkit-background-clip: text; |
|
-webkit-text-fill-color: transparent; |
|
text-shadow: none;'> |
|
Forecast Table |
|
</span> |
|
<span style='font-size: 40%;'> |
|
<sup style='position: relative; top: 5px; color: #ed4965;'></sup> |
|
</span> |
|
</h2> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
final_results=pd.concat([future_prediction[['ds','consumer_id','yhat']],results[['ds','consumer_id','yhat']]]).sort_values('ds').reset_index(drop=True) |
|
csv = convert_df(final_results) |
|
tab2.dataframe(final_results,width=500) |
|
tab2.download_button("Download", |
|
csv, |
|
"file.csv", |
|
"text/csv", |
|
key='download-csv') |
|
hide_streamlit_style = """ |
|
<style> |
|
#MainMenu {visibility: hidden;} |
|
footer {visibility: hidden;} |
|
</style> |
|
""" |
|
st.markdown(hide_streamlit_style, unsafe_allow_html=True) |
|
|