|
import streamlit as st
|
|
import pandas as pd
|
|
import numpy as np
|
|
from sklearn.preprocessing import MinMaxScaler
|
|
from sklearn.metrics import mean_squared_error, mean_absolute_percentage_error
|
|
from tensorflow.keras.models import Sequential
|
|
from tensorflow.keras.layers import LSTM, Dense, Dropout
|
|
import matplotlib.pyplot as plt
|
|
from datetime import timedelta
|
|
|
|
|
|
@st.cache_data
|
|
def load_data():
|
|
data = pd.read_csv("nyc_energy_consumption.csv")
|
|
data.columns = ['timeStamp', 'demand', 'precip', 'temp']
|
|
data['timeStamp'] = pd.to_datetime(data['timeStamp'])
|
|
data.set_index('timeStamp', inplace=True)
|
|
data = data.dropna()
|
|
return data
|
|
|
|
data = load_data()
|
|
|
|
|
|
scaler = MinMaxScaler(feature_range=(0, 1))
|
|
scaled_data = scaler.fit_transform(data[['demand', 'precip', 'temp']])
|
|
|
|
|
|
def create_dataset(dataset, look_back=60):
|
|
X, y = [], []
|
|
for i in range(look_back, len(dataset)):
|
|
X.append(dataset[i-look_back:i])
|
|
y.append(dataset[i, 0])
|
|
return np.array(X), np.array(y)
|
|
|
|
|
|
look_back = 60
|
|
X, y = create_dataset(scaled_data, look_back)
|
|
|
|
|
|
split_ratio = 0.8
|
|
split_index = int(len(X) * split_ratio)
|
|
X_train, X_test = X[:split_index], X[split_index:]
|
|
y_train, y_test = y[:split_index], y[split_index:]
|
|
|
|
|
|
model = Sequential([
|
|
LSTM(units=50, return_sequences=True, input_shape=(X_train.shape[1], X_train.shape[2])),
|
|
Dropout(0.2),
|
|
LSTM(units=50, return_sequences=False),
|
|
Dropout(0.2),
|
|
Dense(units=25),
|
|
Dense(units=1)
|
|
])
|
|
|
|
model.compile(optimizer='adam', loss='mean_squared_error')
|
|
|
|
|
|
history = model.fit(X_train, y_train, epochs=20, batch_size=64, validation_data=(X_test, y_test))
|
|
|
|
|
|
train_predict = model.predict(X_train)
|
|
test_predict = model.predict(X_test)
|
|
|
|
|
|
train_predict = scaler.inverse_transform(np.concatenate((train_predict, np.zeros((train_predict.shape[0], 2))), axis=1))[:, 0]
|
|
test_predict = scaler.inverse_transform(np.concatenate((test_predict, np.zeros((test_predict.shape[0], 2))), axis=1))[:, 0]
|
|
y_train_inv = scaler.inverse_transform(np.concatenate((y_train.reshape(-1, 1), np.zeros((y_train.shape[0], 2))), axis=1))[:, 0]
|
|
y_test_inv = scaler.inverse_transform(np.concatenate((y_test.reshape(-1, 1), np.zeros((y_test.shape[0], 2))), axis=1))[:, 0]
|
|
|
|
|
|
rmse = np.sqrt(mean_squared_error(y_test_inv, test_predict))
|
|
mape = mean_absolute_percentage_error(y_test_inv, test_predict) * 100
|
|
accuracy = 100 - mape
|
|
|
|
|
|
st.title("NYC Energy Consumption Forecasting with LSTM")
|
|
st.subheader("Dataset Preview")
|
|
st.write(data.head())
|
|
|
|
|
|
st.subheader("Forecasting Options")
|
|
forecast_period = st.slider("Select number of future hours to predict", min_value=1, max_value=365, value=30)
|
|
|
|
|
|
future_X = scaled_data[-look_back:]
|
|
future_X = np.reshape(future_X, (1, look_back, scaled_data.shape[1]))
|
|
|
|
future_predictions = []
|
|
for _ in range(forecast_period):
|
|
future_pred = model.predict(future_X)
|
|
future_predictions.append(future_pred[0, 0])
|
|
|
|
|
|
future_pred_expanded = np.array([[future_pred[0, 0], 0, 0]])
|
|
future_X = np.append(future_X[:, 1:, :], [future_pred_expanded], axis=1)
|
|
|
|
|
|
future_predictions = scaler.inverse_transform(
|
|
np.concatenate((np.array(future_predictions).reshape(-1, 1), np.zeros((forecast_period, 2))), axis=1))[:, 0]
|
|
|
|
|
|
last_date = data.index[-1]
|
|
future_dates = [last_date + timedelta(hours=i) for i in range(1, forecast_period + 1)]
|
|
future_predictions_df = pd.DataFrame({
|
|
'DateTime': future_dates,
|
|
'Predicted Demand': future_predictions
|
|
})
|
|
|
|
|
|
st.subheader("Forecasting and Model Evaluation")
|
|
st.write(f"Root Mean Squared Error (RMSE): {rmse:.2f}")
|
|
st.write(f"Mean Absolute Percentage Error (MAPE): {mape:.2f}%")
|
|
st.write(f"Model Accuracy: {accuracy:.2f}%")
|
|
|
|
|
|
st.subheader("Actual vs Predicted Demand")
|
|
plt.figure(figsize=(14,5))
|
|
plt.plot(y_test_inv, color='blue', label='Actual Demand')
|
|
plt.plot(test_predict, color='orange', linestyle='--', label='Predicted Demand')
|
|
plt.legend()
|
|
plt.xlabel('Time')
|
|
plt.ylabel('Demand')
|
|
st.pyplot(plt)
|
|
|
|
|
|
st.subheader("Future Predictions with Date and Time")
|
|
st.write(future_predictions_df)
|
|
|
|
|
|
st.subheader("Future Predictions Plot")
|
|
plt.figure(figsize=(14,5))
|
|
plt.plot(range(len(y_test_inv), len(y_test_inv) + forecast_period), future_predictions, color='green', linestyle='--', label='Future Prediction')
|
|
plt.legend()
|
|
plt.xlabel('Future Time')
|
|
plt.ylabel('Demand')
|
|
st.pyplot(plt)
|
|
|