我的代码是否存在过拟合或者数据泄露的情况?

问题描述 投票:0回答:1

关于预测能量的代码。我写了一段代码,检查了一下,好像没有数据泄露的情况。但过了一段时间,MAPE 值在对未来的预测中显着增加。你能帮我检查一下我写的代码是否存在数据泄露吗?我怀疑那些滚动的部件。 (我从 gpt 检查过,但不确定是否正确。:))

import pandas as pd
import numpy as np
from xgboost import XGBRegressor
from sklearn.linear_model import LinearRegression, Ridge, Lasso, ElasticNet
from sklearn.neighbors import KNeighborsRegressor
from sklearn.tree import DecisionTreeRegressor, ExtraTreeRegressor
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor, ExtraTreesRegressor
from lightgbm import LGBMRegressor
from catboost import CatBoostRegressor
from sklearn.metrics import mean_absolute_error, mean_squared_error, median_absolute_error, explained_variance_score, r2_score, mean_absolute_percentage_error
import matplotlib.pyplot as plt


file_path = 'data.xlsx'
data = pd.read_excel(file_path)


data.drop(["Unnamed: 0", "Akşam", "Vardiya_A", "Vardiya_B", "Vardiya_C", "Yeni Çeyrek", "Çeyrek"], axis=1, inplace=True)


data['Tarih'] = pd.to_datetime(data['Tarih'])

data.dropna(inplace=True)


data = pd.get_dummies(data, prefix_sep='_', drop_first=True)

data.columns = pd.Index([col if list(data.columns).count(col) == 1 else f"{col}_{i}" for i, col in enumerate(data.columns)])

X = data.drop(columns=["Enerji", "Tarih"])  
y = data['Enerji']  
tarih = data['Tarih']  


window_size = 3


results_df = pd.DataFrame(columns=['Model', 'Tarih', 'Saat', 'Gerçek Değer', 'Tahmin Edilen Değer', 'MAPE'])

models = [
#     ('RF', RandomForestRegressor()),
#     ('GBM', GradientBoostingRegressor()),
#     ("XGBoost", XGBRegressor(objective='reg:squarederror')),
#     ("LightGBM", LGBMRegressor()),
    ("CatBoost", CatBoostRegressor(verbose=False)),
#     ("ExtraTrees", ExtraTreesRegressor())
]


for i in reversed(range(552, 1273)):
    
    
    X_train = X[:-i].copy()
    X_test = X[-i:-i+24].copy()
    y_train = y[:-i].copy()
    y_test = y[-i:-i+24].copy()
    tarih_test = tarih[-i:-i+24].copy()

   
    X_train['Moving_Avg'] = y_train.rolling(window=window_size).mean().shift(1).fillna(method='bfill')

    
    if X_test.empty:
        continue

    for name, model in models:
        
        model.fit(X_train, y_train)
        
        y_pred = []
        y_temp = y_train[-window_size:].tolist()  

        for j in range(len(X_test)):
            
            X_test_single = X_test.iloc[j:j+1, :].copy()
            X_test_single['Moving_Avg'] = np.mean(y_temp[-window_size:])  # Son tahminlere bakarak hareketli ortalamayı güncelle
            
            
            pred = model.predict(X_test_single)[0]
            y_pred.append(pred)
            
            
            y_temp.append(pred)

        y_pred = np.array(y_pred)
        
        
        mape = mean_absolute_percentage_error(y_test, y_pred)
        
        
        temp_df = pd.DataFrame({
            'Model': name,
            'Tarih': tarih_test.dt.date,
            'Saat': tarih_test.dt.time,
            'Gerçek Değer': y_test.values,
            'Tahmin Edilen Değer': y_pred,
            'MAPE': [mape] * len(y_test)
        })
        results_df = pd.concat([results_df, temp_df], ignore_index=True)
    
    print(f'Kalan Saat: {i}')


plt.figure(figsize=(12, 6))
plt.plot(data['Tarih'], y, label='Gerçek Enerji Tüketimi')
plt.plot(results_df['Tarih'] + pd.to_timedelta(results_df['Saat'].astype(str)), results_df.groupby('Model')['Tahmin Edilen Değer'].mean(), linestyle='--')
plt.xlabel('Tarih')
plt.ylabel('Enerji Tüketimi')
plt.title('Farklı Modellerle Zaman Serisi Tahmini')
plt.legend()
plt.show()


results_df.head()



python pandas dataframe artificial-intelligence ml
1个回答
0
投票

用于训练和测试的滑动窗口方法(即,在 X[:-i] 上训练并在 X[-i:-i+24] 上测试)可能会导致过度拟合。

这里有一些避免数据泄露的思考:

# Calculate rolling mean on the entire y_train before the loop
y_rolling_mean = y_train.rolling(window=window_size).mean().shift(1).fillna(method='bfill')

# Use this pre-calculated rolling mean in both X_train and X_test
X_train['Moving_Avg'] = y_rolling_mean

# During predictions, do not update the rolling mean with predicted values
X_test['Moving_Avg'] = y_rolling_mean.iloc[-window_size:].mean()  # Use last known rolling mean

修复固定滚动窗口:

window_size = 365  # Or another appropriate size based on your data

for i in reversed(range(552, 1273)):
    # Maintain a fixed window size
    X_train = X[-(i+window_size):-i].copy()
    y_train = y[-(i+window_size):-i].copy()
    tarih_train = tarih[-(i+window_size):-i].copy()
    
    X_test = X[-i:-i+24].copy()
    y_test = y[-i:-i+24].copy()
    tarih_test = tarih[-i:-i+24].copy()

    # Proceed with the rolling mean and model training as before

您可以使用保留验证集来检查您的模型如何概括未见过的数据。

© www.soinside.com 2019 - 2024. All rights reserved.