3. Your First Modelο
In this tutorial, youβll build and train your first complete TurboGuard model for turbofan engine anomaly detection. Weβll cover both LSTM AutoEncoder and Forecasting LSTM approaches.
3.1. π― What Youβll Buildο
By the end of this tutorial, youβll have:
β A trained LSTM AutoEncoder for anomaly detection
β A complete evaluation pipeline
β Visualization of results
Letβs get started! π
3.2. Step 1: Data Preparationο
Load and Explore the Dataset
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from src.LSTM_AutoEncoder.data_loader import DataLoader
# Initialize data loader
loader = DataLoader()
# Load FD001 dataset
train_data, test_data = loader.load_dataset('FD001')
print("Dataset Overview:")
print(f"Training engines: {train_data['unit_id'].nunique()}")
print(f"Test engines: {test_data['unit_id'].nunique()}")
print(f"Training cycles: {len(train_data)}")
print(f"Test cycles: {len(test_data)}")
Expected Output:
Dataset Overview:
Training engines: 100
Test engines: 100
Training cycles: 20631
Test cycles: 13096
Explore Sensor Data
# Look at sensor columns
sensor_cols = [col for col in train_data.columns if col.startswith('s')]
print(f"Available sensors: {len(sensor_cols)}")
print(f"Sensor names: {sensor_cols}")
# Check data types and missing values
print("\nData Info:")
print(train_data.info())
Data Preprocessing
from src.LSTM_AutoEncoder.preprocessor import DataPreprocessor
# Initialize preprocessor
preprocessor = DataPreprocessor()
# Normalize the data
train_normalized = preprocessor.fit_transform(train_data)
test_normalized = preprocessor.transform(test_data)
print("β
Data preprocessing completed!")
print(f"Normalized training shape: {train_normalized.shape}")
3.3. Step 2: Build LSTM AutoEncoderο
Model Architecture
from src.LSTM_AutoEncoder.lstm_autoencoder import LSTMAutoEncoder
# Initialize AutoEncoder
autoencoder = LSTMAutoEncoder()
# Build model architecture
autoencoder.build_model(input_shape=(SEQUENCE_LENGTH, N_FEATURES))
# Display model summary
print("Model Architecture:")
autoencoder.model.summary()
Expected Architecture:
Model: "lstm_autoencoder"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
lstm_encoder (LSTM) (None, 64) 22016
repeat_vector (RepeatVector) (None, 50, 64) 0
lstm_decoder (LSTM) (None, 50, 64) 33024
time_distributed (TimeDistr) (None, 50, 21) 1365
=================================================================
Total params: 56,405
Trainable params: 56,405
Prepare Training Sequences
# Create sequences for training
X_train = loader.create_sequences(
train_normalized,
sequence_length=SEQUENCE_LENGTH
)
X_test = loader.create_sequences(
test_normalized,
sequence_length=SEQUENCE_LENGTH
)
print(f"Training sequences: {X_train.shape}")
print(f"Test sequences: {X_test.shape}")
3.4. Step 3: Train the AutoEncoderο
Training Configuration
# Training parameters
EPOCHS = 50
BATCH_SIZE = 32
VALIDATION_SPLIT = 0.2
# Train the model
print("π Starting AutoEncoder training...")
history = autoencoder.train(
X_train,
epochs=EPOCHS,
batch_size=BATCH_SIZE,
validation_split=VALIDATION_SPLIT,
verbose=0
)
print("β
AutoEncoder training completed!")
Monitor Training Progress
# Plot training history
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'], label='Training Loss')
plt.plot(history.history['val_loss'], label='Validation Loss')
plt.title('Model Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.subplot(1, 2, 2)
plt.plot(history.history['mae'], label='Training MAE')
plt.plot(history.history['val_mae'], label='Validation MAE')
plt.title('Model MAE')
plt.xlabel('Epoch')
plt.ylabel('MAE')
plt.legend()
plt.tight_layout()
plt.show()
3.5. Step 4: Anomaly Detectionο
Generate Predictions
# Get reconstructions for test data
X_test_pred = autoencoder.model.predict(X_test)
# Calculate reconstruction errors
reconstruction_errors = np.mean(np.square(X_test - X_test_pred), axis=(1, 2))
print(f"Reconstruction errors shape: {reconstruction_errors.shape}")
print(f"Mean reconstruction error: {reconstruction_errors.mean():.4f}")
print(f"Std reconstruction error: {reconstruction_errors.std():.4f}")
Set Anomaly Threshold
# Calculate threshold using training data
X_train_pred = autoencoder.model.predict(X_train)
train_errors = np.mean(np.square(X_train - X_train_pred), axis=(1, 2))
# Use 95th percentile as threshold
threshold = np.percentile(train_errors, 95)
print(f"Anomaly threshold: {threshold:.4f}")
# Detect anomalies
anomalies = reconstruction_errors > threshold
anomaly_rate = anomalies.sum() / len(anomalies)
print(f"Detected anomalies: {anomalies.sum()}/{len(anomalies)}")
print(f"Anomaly rate: {anomaly_rate:.2%}")
Visualize Anomaly Detection
plt.figure(figsize=(15, 5))
plt.subplot(1, 2, 1)
plt.hist(train_errors, bins=50, alpha=0.7, label='Training Errors')
plt.hist(reconstruction_errors, bins=50, alpha=0.7, label='Test Errors')
plt.axvline(threshold, color='red', linestyle='--', label=f'Threshold ({threshold:.4f})')
plt.xlabel('Reconstruction Error')
plt.ylabel('Frequency')
plt.title('Error Distribution')
plt.legend()
plt.subplot(1, 2, 2)
plt.plot(reconstruction_errors, alpha=0.7)
plt.scatter(np.where(anomalies)[0], reconstruction_errors[anomalies],
color='red', s=10, label='Anomalies')
plt.axhline(threshold, color='red', linestyle='--', label='Threshold')
plt.xlabel('Sample Index')
plt.ylabel('Reconstruction Error')
plt.title('Anomaly Detection Results')
plt.legend()
plt.tight_layout()
plt.show()
3.6. Step 5: Build Forecasting LSTMο
Forecasting Model Setup
from src.Forecasting_LSTM.forecasting_lstm import PrognosticLSTMModel
# Initialize forecasting model
forecaster = PrognosticLSTMModel(
sequence_length=SEQUENCE_LENGTH,
n_features=N_FEATURES
)
# Build model
forecaster.build_model(input_shape=(SEQUENCE_LENGTH, N_FEATURES))
print("Forecasting Model Architecture:")
forecaster.model.summary()
Prepare Forecasting Data
processor = DataProcessor()
df = processor.load_cmapss_data('/path/to/FD001.txt')
# Extract sensor columns and operational mode as numpy arrays
sensor_cols = [col for col in df.columns if col.startswith('sensor_')]
data = df[sensor_cols].values
modes = df['op_mode'].values
# Parameters
SEQUENCE_LENGTH = 30
# Create sequences with modes using your model method
model = PrognosticLSTMModel(n_features=data.shape[1], sequence_length=SEQUENCE_LENGTH)
X, y, mode_seq = model.create_sequences(data, modes=modes)
print(f"Input shape: {X.shape}")
print(f"Target shape: {y.shape}")
print(f"Mode sequence shape: {mode_seq.shape}")
# Split train/val (example: 80% train)
split_idx = int(0.8 * len(X))
X_train, y_train, modes_train = X[:split_idx], y[:split_idx], mode_seq[:split_idx]
X_val, y_val, modes_val = X[split_idx:], y[split_idx:], mode_seq[split_idx:]
Train Forecasting Model
print("π Starting Forecasting LSTM training...")
forecast_history = forecaster.train(
X_train, y_train,
X_val, y_val
epochs=30,
batch_size=32,
validation_split=0.2
)
print("β
Forecasting LSTM training completed!")
3.7. Step 6: Model Evaluationο
Comprehensive Performance Metrics
from sklearn.metrics import classification_report, confusion_matrix
# For AutoEncoder anomaly detection
# Create binary labels (assuming last 30% of engine life is anomalous)
def create_binary_labels(data):
labels = []
for unit_id in data['unit_id'].unique():
unit_data = data[data['unit_id'] == unit_id]
unit_length = len(unit_data)
# Last 30% cycles are considered anomalous
anomaly_start = int(0.7 * unit_length)
unit_labels = [0] * anomaly_start + [1] * (unit_length - anomaly_start)
labels.extend(unit_labels)
return np.array(labels)
# Create ground truth labels for sequences
test_labels = create_binary_labels(test_normalized)
# Align with sequence data (simplified)
sequence_labels = test_labels[SEQUENCE_LENGTH-1:][:len(anomalies)]
# Classification report
print("AutoEncoder Anomaly Detection Performance:")
print(classification_report(sequence_labels, anomalies.astype(int)))
Performance Summary
# Create comprehensive performance summary
performance_summary = {
'AutoEncoder': {
'Reconstruction MSE': np.mean(reconstruction_errors),
'Detection Accuracy': np.mean(sequence_labels == anomalies.astype(int)),
'Anomaly Rate': anomaly_rate,
'Threshold': threshold
},
'Forecasting LSTM': {
'RUL RMSE': rmse,
'RUL MAE': mae,
'Training Loss': forecast_history.history['loss'][-1],
'Validation Loss': forecast_history.history['val_loss'][-1]
}
}
print("\n" + "="*50)
print("FINAL PERFORMANCE SUMMARY")
print("="*50)
for model_name, metrics in performance_summary.items():
print(f"\n{model_name}:")
for metric_name, value in metrics.items():
if isinstance(value, float):
print(f" βββ {metric_name}: {value:.4f}")
else:
print(f" βββ {metric_name}: {value}")
3.8. Step 7: Save Your Modelsο
Save Trained Models
import os
from datetime import datetime
# Create models directory
os.makedirs('models/trained', exist_ok=True)
# Generate timestamp for model versioning
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
# Save AutoEncoder
autoencoder_path = f'models/trained/autoencoder_FD001_{timestamp}.h5'
autoencoder.model.save(autoencoder_path)
print(f"β
AutoEncoder saved to: {autoencoder_path}")
# Save Forecasting LSTM
forecaster_path = f'models/trained/forecaster_FD001_{timestamp}.h5'
forecaster.model.save(forecaster_path)
print(f"β
Forecasting LSTM saved to: {forecaster_path}")
# Save preprocessing parameters
import pickle
preprocessor_path = f'models/trained/preprocessor_FD001_{timestamp}.pkl'
with open(preprocessor_path, 'wb') as f:
pickle.dump(preprocessor, f)
print(f"β
Preprocessor saved to: {preprocessor_path}")
Save Model Configuration
import json
# Model configuration
model_config = {
'dataset': 'FD001',
'timestamp': timestamp,
'autoencoder': {
'sequence_length': SEQUENCE_LENGTH,
'n_features': N_FEATURES,
'encoding_dim': ENCODING_DIM,
'epochs': EPOCHS,
'batch_size': BATCH_SIZE,
'threshold': float(threshold)
},
'forecaster': {
'sequence_length': SEQUENCE_LENGTH,
'n_features': N_FEATURES,
'forecast_horizon': 10,
'epochs': 30,
'batch_size': 32
},
'performance': performance_summary
}
config_path = f'models/trained/config_FD001_{timestamp}.json'
with open(config_path, 'w') as f:
json.dump(model_config, f, indent=2)
print(f"β
Configuration saved to: {config_path}")
3.9. Step 8: Test Model Loadingο
Load and Test Saved Models
from tensorflow.keras.models import load_model
# Load models
loaded_autoencoder = load_model(autoencoder_path)
loaded_forecaster = load_model(forecaster_path)
# Load preprocessor
with open(preprocessor_path, 'rb') as f:
loaded_preprocessor = pickle.load(f)
print("β
All models loaded successfully!")
# Test loaded models
test_sample = X_test[:5] # Test with 5 samples
# Test AutoEncoder
test_reconstruction = loaded_autoencoder.predict(test_sample)
test_errors = np.mean(np.square(test_sample - test_reconstruction), axis=(1, 2))
print(f"Test reconstruction errors: {test_errors}")
# Test Forecaster
test_forecast = loaded_forecaster.predict(test_sample)
print(f"Test forecast shape: {test_forecast.shape}")
3.10. Step 9: Visualization Dashboardο
Create Summary Visualization
def create_model_dashboard(results, title="TurboGuard Model Results"):
"""Create comprehensive visualization dashboard"""
fig, axes = plt.subplots(2, 3, figsize=(18, 12))
fig.suptitle(title, fontsize=16, fontweight='bold')
# Plot 1: Reconstruction Errors
axes[0, 0].plot(results['reconstruction_errors'])
axes[0, 0].axhline(results['threshold'], color='red', linestyle='--',
label=f'Threshold: {results["threshold"]:.4f}')
axes[0, 0].scatter(np.where(results['anomalies'])[0],
results['reconstruction_errors'][results['anomalies']],
color='red', s=20, alpha=0.7, label='Anomalies')
axes[0, 0].set_title('Reconstruction Error Timeline')
axes[0, 0].set_xlabel('Sample Index')
axes[0, 0].set_ylabel('Reconstruction Error')
axes[0, 0].legend()
# Plot 2: RUL Estimates
axes[0, 1].plot(results['rul_estimates'])
axes[0, 1].set_title('RUL Estimates Timeline')
axes[0, 1].set_xlabel('Sample Index')
axes[0, 1].set_ylabel('RUL (cycles)')
# Plot 3: Error Distribution
axes[0, 2].hist(results['reconstruction_errors'], bins=50, alpha=0.7)
axes[0, 2].axvline(results['threshold'], color='red', linestyle='--',
label='Threshold')
axes[0, 2].set_title('Reconstruction Error Distribution')
axes[0, 2].set_xlabel('Reconstruction Error')
axes[0, 2].set_ylabel('Frequency')
axes[0, 2].legend()
# Plot 4: Anomaly Rate Over Time
window_size = 100
anomaly_rate_timeline = []
for i in range(window_size, len(results['anomalies'])):
window_anomalies = results['anomalies'][i-window_size:i]
rate = window_anomalies.sum() / window_size
anomaly_rate_timeline.append(rate)
axes[1, 0].plot(anomaly_rate_timeline)
axes[1, 0].set_title(f'Anomaly Rate (Rolling Window: {window_size})')
axes[1, 0].set_xlabel('Sample Index')
axes[1, 0].set_ylabel('Anomaly Rate')
# Plot 5: RUL Distribution
axes[1, 1].hist(results['rul_estimates'], bins=30, alpha=0.7)
axes[1, 1].set_title('RUL Estimates Distribution')
axes[1, 1].set_xlabel('RUL (cycles)')
axes[1, 1].set_ylabel('Frequency')
# Plot 6: Anomaly vs RUL Correlation
normal_rul = results['rul_estimates'][~results['anomalies']]
anomaly_rul = results['rul_estimates'][results['anomalies']]
axes[1, 2].boxplot([normal_rul, anomaly_rul], labels=['Normal', 'Anomaly'])
axes[1, 2].set_title('RUL Distribution: Normal vs Anomaly')
axes[1, 2].set_ylabel('RUL (cycles)')
plt.tight_layout()
plt.show()
return fig
# Create dashboard for our results
dashboard = create_model_dashboard(sample_results, "Your First TurboGuard Model Results")
3.11. Congratulations! πο
Youβve successfully built your first complete TurboGuard model! Hereβs what you accomplished:
β Data Loading & Preprocessing - Loaded CMAPSS FD001 dataset - Normalized sensor data - Created sequential training data
β LSTM AutoEncoder - Built dual LSTM architecture - Trained for anomaly detection - Achieved reconstruction-based anomaly detection
β Forecasting LSTM - Built forecasting model - Trained for multi-step prediction
β Model Evaluation - Comprehensive performance metrics - Visualization dashboards - Model saving and loading
β Production Pipeline - Complete prediction function - Model configuration management - Reusable prediction pipeline
3.12. Key Takeawaysο
π― Performance Insights
AutoEncoder effectively captures normal engine behavior patterns
Reconstruction errors provide reliable anomaly indicators
Forecasting LSTM enables proactive maintenance planning
Combined approach improves overall detection reliability
π Best Practices Learned
Proper sequence length is crucial (50 timesteps works well)
Threshold selection significantly impacts performance
Model ensembling improves robustness
Regular model retraining maintains accuracy
3.13. Next Stepsο
Now that you have a working model, explore these advanced topics:
π§ Hyperparameter Tuning: ../user_guide/model_training
π Advanced Visualization: ../user_guide/visualization
π Production Deployment: ../examples/advanced_usage
π Multi-Dataset Training: Try FD002, FD003, FD004 datasets
π― Custom Thresholds: Implement adaptive thresholding
3.14. Troubleshootingο
Common Issues and Solutions
Issue: Model overfitting (training loss much lower than validation loss) Solution: Add dropout layers, reduce model complexity, or increase data
Issue: Poor anomaly detection performance Solution: Adjust threshold, try different sequence lengths, or add more training data
Issue: Memory errors during training Solution: Reduce batch size, use gradient accumulation, or train on smaller sequences
3.15. Resourcesο
π Further Reading - User Guide - Detailed user guide - ../api/index - Complete reference - Examples - More examples and use cases
π οΈ Tools and Extensions - TensorBoard for training visualization - MLflow for experiment tracking - Docker for containerized deployment
Youβre now ready to build production-grade predictive maintenance systems with TurboGuard! π