[Python] Does my timeseries RNN have data leakage?

Discussão em 'Python' iniciado por Stack, Junho 26, 2025.

  1. Stack

    Stack Membro Participativo

    I'm trying to set up an RNN to predict the generated windpower from weather data. For this I'm using a publicly available dataset from kaggle (https://www.kaggle.com/datasets/berkerisen/wind-turbine-scada-dataset/data). I'm trying to set up an RNN with tensorflow and I am very suspicous of my results and I fear that I have data leakage. My metrics are very good and the r2 value for the testing data is higher than for my training data. I think I avoided the most common pitfalls for dataleaking, i.e. splitting data before scaling and proper windowing. But as I'm quite new to machine learning I'm still unsure about this.

    This is the code for just testing the RNN so no data analysis or simpler models.

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    import seaborn as sns

    # --- Import Data ---
    df = pd.read_csv(r"T1.csv")

    # Convert Date/Time to datetime object and split into hour/day/month/year
    df['Date/Time'] = pd.to_datetime(df['Date/Time'], format='%d %m %Y %H:%M')
    df['Month'] = df['Date/Time'].dt.month
    df['week'] = df['Date/Time'].dt.isocalendar().week
    df['day'] = df['Date/Time'].dt.day
    df['Hour']=df['Date/Time'].dt.hour
    df = df.drop(columns=['Theoretical_Power_Curve (KWh)','Date/Time'])

    #%% --- Split, Scale and Window Data ---
    from sklearn.preprocessing import MinMaxScaler

    # Split data before scaling
    df = df.values
    train_size = int(0.8 * len(df))
    test_size = len(df) - train_size
    df_train, df_test = df[:train_size], df[train_size:]

    # Scale only based on training data
    sc = MinMaxScaler()
    df_train_sc = sc.fit_transform(df_train)
    df_test_sc = sc.transform(df_test)

    # Split training data in to training and validation data (90/10)
    val_size = int(0.1 * len(df_train_sc)) # 10% of training for validation
    df_train_sc, df_val_sc = df_train_sc[:-val_size], df_train_sc[-(val_size):]

    # Windowing Function
    def create_sequences(data, time_step=1):
    X, y = [], []
    for i in range(len(data) - time_step):
    X.append(data[i:(i + time_step), :])
    y.append(data[i + time_step, 0]) # FIrst feature is target
    return np.array(X), np.array(y)

    time_step = 10 # adjustable

    X_train, y_train = create_sequences(df_train_sc, time_step)
    X_val, y_val = create_sequences(df_val_sc, time_step)
    X_test, y_test = create_sequences(df_test_sc, time_step)

    #%% --- Build, Compile and Train RNN ---

    from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import LSTM, Dense, Dropout

    model = Sequential([
    LSTM(50, return_sequences=True, input_shape=(10, 7)), # First LSTM layer
    LSTM(50, return_sequences=False), # Second LSTM layer
    Dense(25, activation='relu'), # Dense hidden layer
    Dense(1) # Output layer
    ])

    # Compile the model
    model.compile(optimizer='adam', loss='mean_squared_error', metrics=['mae'])

    history = model.fit(X_train, y_train, epochs=10, batch_size=32, validation_data=(X_val, y_val))

    #%% --- Predict Windpower ---

    y_pred_train = model.predict(X_train).flatten()
    y_pred_test = model.predict(X_test).flatten()

    num_features = 7 # Update this based on your dataset

    # Create a full array for inverse transformation
    y_pred_train_full = np.zeros((y_pred_train.shape[0], num_features)) # Use the same number of features as original data
    y_pred_train_full[:, 0] = y_pred_train.flatten() # Insert predictions into the first column
    y_pred_test_full = np.zeros((y_pred_test.shape[0], num_features)) # Use the same number of features as original data
    y_pred_test_full[:, 0] = y_pred_test.flatten() # Insert predictions into the first column

    # Apply inverse transformation
    y_pred_train_inverse = sc.inverse_transform(y_pred_train_full)[:, 0] # Extract only the first column
    y_pred_test_inverse = sc.inverse_transform(y_pred_test_full)[:, 0] # Extract only the first column

    # Also invert y_train and y_test for comparison
    y_train_full = np.zeros((y_train.shape[0], num_features)) # Use the same number of features
    y_train_full[:, 0] = y_train.flatten()
    y_train_inverse = sc.inverse_transform(y_train_full)[:, 0] # Extract only the first column
    y_test_full = np.zeros((y_test.shape[0], num_features))
    y_test_full[:, 0] = y_test.flatten()
    y_test_inverse = sc.inverse_transform(y_test_full)[:, 0]

    # calculate and print metrics
    r2_train = r2_score(y_train_inverse, y_pred_train_inverse)
    r2_test = r2_score(y_test_inverse, y_pred_test_inverse)
    mae_train = mean_absolute_error(y_train_inverse, y_pred_train_inverse)
    mae_test = mean_absolute_error(y_test_inverse, y_pred_test_inverse)

    print("R² Score Training Data:", r2_train)
    print("R² Score Testing Data:", r2_test)
    print("MAE Score Training Data:", mae_train)
    print("MAE Score Testing Data:", mae_test)


    Are there any obvious mistakes? Thanks in advance

    Continue reading...

Compartilhe esta Página