Wind Turbine Maintenance Cost Prediction in ML
Boost Your Career with In-demand Skills - 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.
