import time
from utils.levels import complete_level, render_page, initialize_level
from utils.login import get_login, initialize_login
import streamlit as st
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import RandomizedSearchCV
import matplotlib.pyplot as plt
from matplotlib.backends.backend_agg import RendererAgg
_lock = RendererAgg.lock
import base64
from io import BytesIO
from PIL import Image, ImageFilter
import lightgbm as lgb
initialize_login()
initialize_level()
LEVEL = 3
File_PATH = 'datasets/Building_forcasting.csv'
def process_file(csv_file):
data = pd.read_csv(csv_file, index_col='Timestamp')
data.index = pd.to_datetime(data.index)
data = data.fillna(0)
return data
def model_train(train_X, train_y, model_choice, train_size):
if model_choice == 'LightGBM':
model = lgb.LGBMRegressor()
elif model_choice == 'Random Forest':
model = RandomForestRegressor(n_estimators=100, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(train_X, train_y, train_size=train_size/100, random_state=42, shuffle=False)
model.fit(X_train, y_train)
return model, X_test, y_test
def create_model_inputs(data, lag, mean_period):
df_processed = data.copy()
df_processed['PV_Output_lag'] = df_processed['PV_Output'].shift(lag)
df_processed['PV_Output_mean'] = df_processed['PV_Output'].rolling(window=mean_period).mean()
X = df_processed[['Solar_Irradiance', 'Temperature', 'Rain_Fall', 'Wind_speed', 'PV_Output_lag', 'PV_Output_mean']].dropna()
y = df_processed[['PV_Output']].loc[X.index]
return X, y
def show_output(y_test, y_pred):
st.sidebar.subheader("Model Performance")
st.sidebar.write(f"Test R2 score: {r2_score(y_test, y_pred):.2f}")
fig, axs = plt.subplots(3, figsize=(12, 18))
axs[0].plot(y_test.index, y_pred/1000, label='Predicted')
axs[0].plot(y_test.index, y_test['PV_Output']/1000, label='Actual')
axs[0].legend()
axs[0].set_title('Prediction vs Actual (Solar Power Generation)')
axs[0].set_xlabel('Date')
axs[0].set_ylabel('Solar Power Generation (kW)')
axs[1].plot(y_test.index, y_pred/1000, label='Predicted')
axs[1].set_title('Predicted Solar Power Generation')
axs[1].set_xlabel('Date')
axs[1].set_ylabel('Solar Power Generation (kW)')
axs[2].plot(y_test.index, y_test['PV_Output']/1000, label='Actual')
axs[2].set_title('Actual Solar Power Generation')
axs[2].set_xlabel('Date')
axs[2].set_ylabel('Solar Power Generation (kW)')
fig.tight_layout()
with _lock:
st.pyplot(fig)
return fig
def download_link(y_test, y_pred):
y_pred_df = pd.DataFrame({'Timestamp': y_test.index, 'Predicted_Power': y_pred, 'Actual_Total_Power_(kW)': y_test['PV_Output']})
csv = y_pred_df.to_csv(index=False)
b64 = base64.b64encode(csv.encode()).decode()
href = f'Download Predicted Power CSV File'
st.sidebar.markdown(href, unsafe_allow_html=True)
def feature_importance_plot(model, feature_names):
# Get feature importances
importance = model.feature_importances_
# Normalize by the sum of all importances
importance = 100.0 * (importance / importance.sum())
plt.figure(figsize=(10, 6))
plt.bar(feature_names, importance)
plt.title('Feature Importance')
plt.xlabel('Features')
plt.ylabel('Importance (%)')
return plt.gcf()
def download_plot(fig):
tmpfile = BytesIO()
fig.savefig(tmpfile, format='png')
encoded = base64.b64encode(tmpfile.getvalue()).decode('utf-8')
href = f'Download Result Plot'
st.sidebar.markdown(href, unsafe_allow_html=True)
def tuned_parameters(model):
if model == 'lgbm':
params = {
'num_leaves': [10, 20, 30, 40, 50],
'max_depth': [-1, 3, 5, 10],
'learning_rate': [0.01, 0.05, 0.1],
'n_estimators': [100, 500, 1000]
}
return params
elif model == 'rf':
params = {
'n_estimators': [10, 100, 500, 1000],
'max_depth': [None, 10, 20, 30, 40, 50],
'min_samples_split': [2, 5, 10],
'min_samples_leaf': [1, 2, 4]
}
return params
def step3_page():
st.header("Training the Model")
st.subheader("Step 1: Data Collection")
st.write("To initiate the weather forecasting model training process, kindly provide a sufficient and relevant dataset with weather-related attributes in .csv format for uploading. This dataset will be crucial for the model's training and accuracy.")
# Display the image and information in a grid layout
# if st.button("Upload"):
state = "data collection"
col1 = st.columns([1])
with col1[0]:
csv_file = st.file_uploader("Upload CSV", type=['csv'])
if csv_file is not None:
data = process_file(csv_file)
df = pd.DataFrame(data)
st.info("Let's display the uploaded dataset!")
st.dataframe(df)
state = "preprocessing"
else:
st.error("Please upload a valid .csv file")
if state == "preprocessing":
st.subheader("Step 2: Data Preprocessing and Feature Engineering")
st.write("Now let's preprocess our dataset to handle missing values, outliers and inconsistencies and then perform feature engineering tasks to extract meaningful features from the raw data. Finally we need to separate training variables (X) and target variable (y).")
# if st.button("Create Features and Target variable"):
X, y = create_model_inputs(data, 288, 288)
cols = st.columns(2)
state = "splitting"
with cols[0]:
st.info("Let's display the Features!")
st.dataframe(X)
with cols[1]:
st.info("Let's display our Target variable")
st.dataframe(y)
if state == "splitting":
st.subheader("Step 3: Data Splitting")
st.write("Now let's split the dataset into training and testing sets. The training set is used to train the machine learning model, and the testing set is used to evaluate its performance. For that, you have to select the train-test split %.")
train_size = st.slider("Select Train Dataset Size (%)", min_value=10, max_value=90, value=70)
state = "model selection"
if state == "model selection":
st.subheader("Step 4: Model Selection")
st.write("Different machine learning algorithms can be used for weather forecasting and the choice of model depends on the characteristics of the data and the forecasting task. But for this tutorial, you can select between a 'LightGBM' model and a 'Random Forest' model.")
models = ['LightGBM', 'Random Forest']
model_choice = st.selectbox('Choose Model', models)
state = "model training"
if state == "model training":
st.subheader("Step 5: Model Training")
st.write("Finally, let's train our weather forecasting model based on the parameters that you have selected!")
if st.button("Train", key="train"):
model, X_test, y_test = model_train(X, y, model_choice, train_size)
my_bar = st.progress(0, text="Training model...")
for i in range(100):
my_bar.progress(i, text="Training model...")
my_bar.progress(100, text="Training completed")
state = "model predict"
st.success("Model training successfully completed!")
# Display feature importance
if st.checkbox('Show feature importance'):
feature_names = ['Solar_Irradiance', 'Temperature', 'Rain_Fall', 'Wind_speed', 'PV_Output_lag',
'PV_Output_mean']
fig = feature_importance_plot(model, feature_names)
with _lock:
st.pyplot(fig)
if state == "model predict":
st.subheader("Step 5: Model Evaluation")
st.write("Now, let's evaluate our weather forecasting model's performance against the test data set.")
y_pred = model.predict(X_test)
fig = show_output(y_test, y_pred)
# download_link(y_test, y_pred)
#
# download_plot(fig)
if st.button("Complete"):
complete_level(LEVEL)
render_page(step3_page, LEVEL)