Wind Turbine Maintenance Cost Prediction in ML

We offer you a brighter future with placement-ready courses - Start Now!!

Effective budgeting for wind‑turbine maintenance is essential to maximise uptime and control O&M (operation & maintenance) expenses. In this wind turbine maintenance cost prediction ML project, we will predict the monthly maintenance cost for individual turbines based on SCADA‑derived features—such as average rotor speed, power output variability, temperature, and vibration metrics—as well as environmental factors (wind speed, ambient temperature). By employing stepwise regression, we’ll identify the strongest cost drivers and build a lean linear model that balances interpretability with predictive accuracy—helping asset managers forecast maintenance budgets more reliably.

Libraries Required

import pandas as pd                                       # Data manipulation  
import numpy as np                                        # Numerical operations  
import statsmodels.api as sm                              # OLS regression  
from sklearn.model_selection import train_test_split      # Data splitting  
from sklearn.metrics import r2_score, mean_squared_error  # Evaluation  
import matplotlib.pyplot as plt                           # Visualization  

Dataset

Wind energy forecasting and maintenance data

Step-by-Step Code Implementation

Data Loading & Initial Inspection

We load monthly turbine SCADA and maintenance‑cost data, including metrics such as rotor speed, power variability, vibration levels, wind speed, and ambient temperature. Initial checks (.info(), .describe()) confirm data completeness and ranges.

# Block 1: Load dataset
# Dataset: Wind energy forecasting and maintenance data :contentReference[oaicite:1]{index=1}  
url = "https://www.kaggle.com/datasets/pythonafroz/wind-energy-forecasting-and-maintenance-data/download"  
df = pd.read_csv(url)

# Inspect structure & summary
print(df.head())
print(df.info())
print(df.describe())

Data Preprocessing

We filter to rows with non‑missing values for all key predictors and the target maintenance_cost. Predictors (X) are the five turbine health and weather features; response (y) is the monthly cost in USD. An 80/20 split yields training and test sets for unbiased evaluation.

# Block 2: Feature engineering & clean
# Assume the dataset includes monthly aggregates per turbine:
# 'rotor_speed_avg', 'power_std', 'vibration_avg', 'wind_speed_avg',
# 'ambient_temp_avg', and 'maintenance_cost' (USD)

# Drop missing entries
df = df.dropna(subset=[
    'rotor_speed_avg','power_std','vibration_avg',
    'wind_speed_avg','ambient_temp_avg','maintenance_cost'
])

# Define predictors and target
X = df[['rotor_speed_avg','power_std','vibration_avg',
        'wind_speed_avg','ambient_temp_avg']]
y = df['maintenance_cost']

# Split into train/test sets (80/20)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

Stepwise Regression Function

The stepwise_selection function iteratively adds the excluded predictor with the lowest p‑value (< 0.01) and removes the included predictor with the highest p‑value (> 0.05), stopping when no further changes occur—producing a concise set of significant features.

# Block 3: Forward–backward stepwise selection
def stepwise_selection(X, y, 
                       initial_list=[], 
                       threshold_in=0.01, 
                       threshold_out=0.05, 
                       verbose=True):
    included = list(initial_list)
    while True:
        changed = False

        # Forward step: consider adding each excluded variable
        excluded = list(set(X.columns) - set(included))
        pvals = pd.Series(index=excluded, dtype=float)
        for col in excluded:
            model = sm.OLS(y, sm.add_constant(X[included + [col]])).fit()
            pvals[col] = model.pvalues[col]
        best_pval = pvals.min()
        if best_pval < threshold_in:
            best_var = pvals.idxmin()
            included.append(best_var)
            changed = True
            if verbose:
                print(f"Add  {best_var:15} p-value {best_pval:.4f}")

        # Backward step: consider removing each included variable
        model = sm.OLS(y, sm.add_constant(X[included])).fit()
        pvals_included = model.pvalues.iloc[1:]  # drop intercept
        worst_pval = pvals_included.max()
        if worst_pval > threshold_out:
            worst_var = pvals_included.idxmax()
            included.remove(worst_var)
            changed = True
            if verbose:
                print(f"Drop {worst_var:15} p-value {worst_pval:.4f}")

        if not changed:
            break

    return included

Model Building & Evaluation

Using the selected features, we fit an Ordinary Least Squares regression via statsmodels. The .summary() output provides coefficient estimates (cost impact per unit change), standard errors, p‑values, R², and diagnostic statistics (AIC, F‑statistic).

Predictions on the held‑out test set yield R² (variance explained) and RMSE (root‑mean‑square error), quantifying predictive accuracy on unseen turbines.

# Block 4: Feature selection
selected = stepwise_selection(X_train, y_train)

# Fit final OLS model
X_train_sel = sm.add_constant(X_train[selected])
model = sm.OLS(y_train, X_train_sel).fit()
print(model.summary())

# Predict on test set
X_test_sel = sm.add_constant(X_test[selected])
y_pred = model.predict(X_test_sel)

# Compute performance metrics
print("Test R²:", r2_score(y_test, y_pred))
print("Test RMSE:", np.sqrt(mean_squared_error(y_test, y_pred)))

Residual Diagnostics

Plotting residuals against predicted costs checks for non‑random patterns or heteroscedasticity, validating the linear model assumptions.

# Block 5: Residual plot
residuals = y_test - y_pred
plt.scatter(y_pred, residuals)
plt.axhline(0, linestyle="--")
plt.xlabel("Predicted Maintenance Cost (USD)")
plt.ylabel("Residuals")
plt.title("Residuals vs. Predicted Cost")
plt.show()

Summary

Applying stepwise regression to wind‑turbine SCADA data isolates the key maintenance cost drivers—such as power variability and vibration levels—while pruning less informative variables. The resulting linear model balances interpretability (few, significant predictors) with predictive strength (high test‑set R², low RMSE), equipping operations teams with a transparent tool to forecast maintenance budgets and optimise O&M strategies.

Your opinion matters
Please write your valuable feedback about PythonGeeks on Google | Facebook


PythonGeeks Team

The PythonGeeks Team delivers expert-driven tutorials on Python programming, machine learning, Data Science, and AI. We simplify Python concepts for beginners and professionals to help you master coding and advance your career.

Leave a Reply

Your email address will not be published. Required fields are marked *