Spaces:
Sleeping
Sleeping
| import pandas as pd | |
| import numpy as np | |
| from sklearn.linear_model import RidgeCV, LassoCV | |
| from sklearn.preprocessing import StandardScaler | |
| from sklearn.pipeline import Pipeline | |
| from sklearn.metrics import r2_score, mean_absolute_error, mean_squared_error | |
| from sklearn.ensemble import RandomForestRegressor | |
| from xgboost import XGBRegressor | |
| import warnings | |
| import os | |
| warnings.filterwarnings('ignore') | |
| class EmissionForecaster: | |
| def __init__(self, data_path='new_daily_emissions_column_format.xlsx'): | |
| self.data_path = data_path | |
| self.target_col = 'Total Emissions' | |
| self.sector_cols = ['Aviation (%)', 'Ground Transport (%)', 'Industry (%)', 'Power (%)', 'Residential (%)'] | |
| self.performance_metrics = {} | |
| if os.path.exists(data_path): | |
| self._train_model() | |
| def _create_features(self, df): | |
| df = df.copy() | |
| df = df.dropna(subset=['Date', self.target_col]) | |
| df = df.sort_values('Date').reset_index(drop=True) | |
| # 1. Trend & Cyclical Features | |
| df['time_index'] = np.arange(len(df)) | |
| df['month_sin'] = np.sin(2 * np.pi * df['Date'].dt.month / 12) | |
| df['month_cos'] = np.cos(2 * np.pi * df['Date'].dt.month / 12) | |
| df['dow_sin'] = np.sin(2 * np.pi * df['Date'].dt.dayofweek / 7) | |
| df['dow_cos'] = np.cos(2 * np.pi * df['Date'].dt.dayofweek / 7) | |
| # 2. Optimized Lags & Rolling | |
| for lag in [1, 7]: | |
| df[f'lag_{lag}'] = df[self.target_col].shift(lag) | |
| df['roll_mean_7'] = df[self.target_col].shift(1).rolling(window=7).mean() | |
| return df.dropna().reset_index(drop=True) | |
| def _train_model(self): | |
| df_raw = pd.read_excel(self.data_path) | |
| df_raw['Date'] = pd.to_datetime(df_raw['Date'], dayfirst=True) | |
| self.avg_sectors = df_raw[self.sector_cols].mean().to_dict() | |
| df_feat = self._create_features(df_raw) | |
| self.df_features = df_feat | |
| # Consistent feature set | |
| self.feature_cols = ['time_index', 'month_sin', 'month_cos', 'dow_sin', 'dow_cos', 'lag_1', 'lag_7', 'roll_mean_7'] | |
| X = df_feat[self.feature_cols].values | |
| y = df_feat[self.target_col].values | |
| # 80-20 Split | |
| split_idx = int(len(X) * 0.80) | |
| X_train, X_test = X[:split_idx], X[split_idx:] | |
| y_train, y_test = y[:split_idx], y[split_idx:] | |
| # Base Models with High Regularization | |
| base_models = [ | |
| ('lasso', LassoCV(cv=5)), | |
| ('rf', RandomForestRegressor(n_estimators=100, max_depth=2, random_state=42)), | |
| ('xgb', XGBRegressor(n_estimators=100, max_depth=1, learning_rate=0.05, reg_lambda=100, random_state=42)) | |
| ] | |
| train_preds, test_preds, trained_pipes = [], [], [] | |
| for name, model in base_models: | |
| pipe = Pipeline([('scaler', StandardScaler()), ('model', model)]) | |
| pipe.fit(X_train, y_train) | |
| trained_pipes.append(pipe) | |
| train_preds.append(pipe.predict(X_train)) | |
| test_preds.append(pipe.predict(X_test)) | |
| # Meta-model (RidgeCV auto-tunes the best regularization) | |
| meta_model = RidgeCV(alphas=[10, 50, 100, 200, 500]) | |
| meta_model.fit(np.column_stack(train_preds), y_train) | |
| self.model = {'base': trained_pipes, 'meta': meta_model} | |
| # Full Performance Evaluation | |
| y_tr_pred = meta_model.predict(np.column_stack(train_preds)) | |
| y_ts_pred = meta_model.predict(np.column_stack(test_preds)) | |
| self.performance_metrics = { | |
| 'train': { | |
| 'r2': round(r2_score(y_train, y_tr_pred), 4), | |
| 'mae': round(mean_absolute_error(y_train, y_tr_pred), 4), | |
| 'rmse': round(np.sqrt(mean_squared_error(y_train, y_tr_pred)), 4) | |
| }, | |
| 'test': { | |
| 'r2': round(r2_score(y_test, y_ts_pred), 4), | |
| 'mae': round(mean_absolute_error(y_test, y_ts_pred), 4), | |
| 'rmse': round(np.sqrt(mean_squared_error(y_test, y_ts_pred)), 4) | |
| } | |
| } | |
| def forecast_days(self, n_days): | |
| recent_emissions = self.df_features[self.target_col].values.tolist() | |
| last_date = self.df_features['Date'].iloc[-1] | |
| last_idx = self.df_features['time_index'].iloc[-1] | |
| forecasts = [] | |
| for i in range(1, n_days + 1): | |
| f_date = last_date + pd.Timedelta(days=i) | |
| feat_vals = [ | |
| last_idx + i, # time_index | |
| np.sin(2 * np.pi * f_date.month / 12), np.cos(2 * np.pi * f_date.month / 12), | |
| np.sin(2 * np.pi * f_date.dayofweek / 7), np.cos(2 * np.pi * f_date.dayofweek / 7), | |
| recent_emissions[-1], recent_emissions[-7], np.mean(recent_emissions[-7:]) | |
| ] | |
| X_ptr = np.array(feat_vals).reshape(1, -1) | |
| base_p = [m.predict(X_ptr)[0] for m in self.model['base']] | |
| pred = self.model['meta'].predict(np.array(base_p).reshape(1, -1))[0] | |
| recent_emissions.append(pred) | |
| sects = {k.replace(' (%)','').replace(' ','_'): round(pred * v / 100, 4) for k, v in self.avg_sectors.items()} | |
| forecasts.append({'Date': f_date, 'Total_Emission': round(pred, 4), **sects}) | |
| return pd.DataFrame(forecasts) | |
| if __name__ == "__main__": | |
| obj = EmissionForecaster() | |
| # 1. Full Performance Table | |
| m = obj.performance_metrics | |
| print("\n" + " COMPLETE MODEL PERFORMANCE ".center(60, "=")) | |
| print(f"{'Metric':<15} | {'Training Set':<15} | {'Test Set':<15}") | |
| print("-" * 60) | |
| print(f"{'R2 Score':<15} | {m['train']['r2']:<15} | {m['test']['r2']:<15}") | |
| print(f"{'MAE':<15} | {m['train']['mae']:<15} | {m['test']['mae']:<15}") | |
| print(f"{'RMSE':<15} | {m['train']['rmse']:<15} | {m['test']['rmse']:<15}") | |
| print("="*60) | |
| # 2. Generate and Split CSVs | |
| days = 1096 # 2026-2028 | |
| print(f"\nGenerating and splitting forecast for {days} days...") | |
| forecast_df = obj.forecast_days(days) | |
| # Save Full View (Predicted only) | |
| full_csv = forecast_df.copy() | |
| full_csv['Date'] = full_csv['Date'].dt.strftime('%Y-%m-%d') | |
| full_csv.to_csv("emission_forecast_3years_full.csv", index=False) | |
| print("1. Saved: emission_forecast_3years_full.csv") | |
| # Save Individual Years | |
| for yr in [2026, 2027, 2028]: | |
| year_data = forecast_df[forecast_df['Date'].dt.year == yr].copy() | |
| year_data['Date'] = year_data['Date'].dt.strftime('%Y-%m-%d') | |
| year_data = year_data[['Date', 'Total_Emission', 'Aviation', 'Ground_Transport', 'Industry', 'Power', 'Residential']] | |
| year_data.to_csv(f"emission_forecast_{yr}.csv", index=False) | |
| print(f" Generated: emission_forecast_{yr}.csv") | |
| print("\n" + " SUCCESS: ALL FILES SAVED ".center(60, "=")) |