Skip to main content

A Python implementation of the exponential degradation model for remaining useful life (RUL) prediction

Project description

Exponential Degradation Model

License: MIT Python Version

A Python implementation of the exponential degradation model for predicting remaining useful life (RUL) of degrading systems. This package provides a probabilistic approach to prognostics using Bayesian parameter updating.

Overview

This implementation is based on the exponential degradation model described in:

Gebraeel, N. (2006). "Sensory-Updated Residual Life Distributions for Components With Exponential Degradation Patterns." IEEE Transactions on Automation Science and Engineering, 3(4), 382-393.

The model is designed for systems that exhibit exponential degradation patterns and provides:

  • Bayesian parameter updating as new degradation measurements become available
  • Probabilistic RUL predictions with confidence intervals
  • Uncertainty quantification through parameter variance tracking
  • Correlation modeling between degradation parameters

This package provides functionality similar to MATLAB's exponentialDegradationModel from the Predictive Maintenance Toolbox.

Features

  • Bayesian updating: Refines model parameters with each new observation
  • Multiple observation fitting: Efficient batch parameter updates
  • Comprehensive predictions: Point estimates, confidence intervals, and full probability distributions
  • Truncated distributions: Ensures physically meaningful (positive) RUL predictions
  • Correlation handling: Accounts for parameter correlations in uncertainty propagation
  • Numerical stability: Robust handling of edge cases and numerical issues

Installation

From PyPI (when published)

pip install exponential-degradation-model

From Source

git clone https://github.com/houtj/exponentialDegradationModel.git
cd exponentialDegradationModel
pip install -e .

Development Installation

pip install -e ".[dev]"

Quick Start

import numpy as np
from exponential_degradation import ExponentialDegradationModel

# Create model with failure threshold
model = ExponentialDegradationModel(threshold=10.0)

# Prepare degradation measurements
times = np.array([1, 2, 3, 4, 5])
measurements = np.array([1.5, 2.1, 2.9, 4.2, 5.8])

# Fit the model to observations
model.fit(measurements, times)

# Predict remaining useful life
rul_result = model.predict_rul(confidence_level=0.95)

print(f"Predicted RUL: {rul_result['RUL']:.2f}")
print(f"Mean RUL: {rul_result['mean']:.2f}")
print(f"95% CI: [{rul_result['CI'][0]:.2f}, {rul_result['CI'][1]:.2f}]")

Mathematical Model

Degradation Path

The model assumes an exponential degradation path:

y(t) = exp(θ + β·t) + φ

where:

  • θ (theta): Initial value parameter (log-scale)
  • β (beta): Growth rate parameter (degradation rate)
  • φ (phi): Offset parameter
  • t: Time

Failure Condition

The system fails when the degradation measurement reaches a threshold D:

y(t) ≥ D

Remaining Useful Life

The RUL at time t is:

RUL = L - t

where L is the time to failure:

L = [ln(D - φ) - θ] / β

Bayesian Updating

As new measurements arrive, the model uses Bayesian updating to refine the parameter estimates (θ, β) and their uncertainties (variances and correlation). This provides increasingly accurate RUL predictions as more degradation data becomes available.

Uncertainty Quantification

The RUL prediction accounts for parameter uncertainty through variance propagation:

Var(L) = (1/β²) · [Var(θ) + (μ_L·β)²·Var(β) - 2·μ_L·β·Cov(θ,β)]

The RUL distribution is modeled as a truncated normal distribution (truncated at zero) to ensure physically meaningful positive RUL values.

API Reference

ExponentialDegradationModel

Initialization

ExponentialDegradationModel(
    threshold,
    theta=1.0,
    theta_variance=1e6,
    beta=1.0,
    beta_variance=1e6,
    rho=0.0,
    phi=-1.0
)

Parameters:

  • threshold (float): Failure threshold value
  • theta (float, optional): Initial value parameter. Default: 1.0
  • theta_variance (float, optional): Initial variance of theta. Default: 1e6 (high uncertainty)
  • beta (float, optional): Growth rate parameter. Default: 1.0
  • beta_variance (float, optional): Initial variance of beta. Default: 1e6
  • rho (float, optional): Correlation coefficient between theta and beta [-1, 1]. Default: 0.0
  • phi (float, optional): Offset parameter. Default: -1.0

Methods

update(measurement, time)

Update model parameters with a single new observation.

model.update(measurement=2.5, time=1.0)

Parameters:

  • measurement (float): Degradation measurement at the given time
  • time (float): Time point of the measurement
fit(measurements, times)

Update model parameters with multiple observations (batch update).

measurements = np.array([1.5, 2.1, 2.9, 4.2, 5.8])
times = np.array([1, 2, 3, 4, 5])
model.fit(measurements, times)

Parameters:

  • measurements (array-like): Array of degradation measurements
  • times (array-like): Array of corresponding time points
predict()

Get a simple point estimate of the mean RUL.

rul = model.predict()

Returns:

  • float: Mean remaining useful life
predict_rul(confidence_level=0.95, num_samples=1000)

Get comprehensive RUL prediction with confidence intervals and probability distributions.

result = model.predict_rul(confidence_level=0.95, num_samples=1000)

Parameters:

  • confidence_level (float, optional): Confidence level for CI (0-1). Default: 0.95
  • num_samples (int, optional): Number of points for PDF/CDF. Default: 1000

Returns:

Dictionary containing:

  • 'RUL': Median RUL (recommended point estimate)
  • 'mean': Mean RUL
  • 'std': Standard deviation of RUL
  • 'CI': Tuple of (lower_bound, upper_bound)
  • 'pdf_time': Array of time points for PDF
  • 'pdf_values': PDF values at each time point
  • 'cdf_values': CDF values at each time point
  • 'mu_untruncated': Mean of untruncated distribution
  • 'sigma_untruncated': Std of untruncated distribution

Usage Examples

Example 1: Sequential Updating

import numpy as np
from exponential_degradation import ExponentialDegradationModel

# Initialize model
model = ExponentialDegradationModel(threshold=15.0)

# Sequential updates as new measurements arrive
times = [1, 2, 3, 4, 5]
measurements = [2.1, 3.5, 5.2, 7.8, 10.5]

for t, m in zip(times, measurements):
    model.update(m, t)
    rul = model.predict()
    print(f"Time {t}: RUL = {rul:.2f}")

Example 2: Batch Fitting with Visualization

import numpy as np
import matplotlib.pyplot as plt
from exponential_degradation import ExponentialDegradationModel

# Generate synthetic degradation data
np.random.seed(42)
true_theta = 0.5
true_beta = 0.3
times = np.array([0, 1, 2, 3, 4, 5])
measurements = np.exp(true_theta + true_beta * times) + np.random.normal(0, 0.1, len(times))

# Create and fit model
model = ExponentialDegradationModel(threshold=20.0)
model.fit(measurements, times)

# Predict RUL with confidence intervals
result = model.predict_rul(confidence_level=0.95)

# Visualize results
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))

# Plot degradation path
ax1.scatter(times, measurements, label='Measurements', color='blue')
ax1.axhline(y=20.0, color='r', linestyle='--', label='Failure Threshold')
ax1.set_xlabel('Time')
ax1.set_ylabel('Degradation')
ax1.set_title('Degradation Path')
ax1.legend()
ax1.grid(True)

# Plot RUL distribution
ax2.plot(result['pdf_time'], result['pdf_values'], label='PDF', color='green')
ax2.axvline(x=result['RUL'], color='b', linestyle='--', label=f"Median RUL: {result['RUL']:.2f}")
ax2.axvline(x=result['CI'][0], color='gray', linestyle=':', label='95% CI')
ax2.axvline(x=result['CI'][1], color='gray', linestyle=':')
ax2.set_xlabel('Remaining Useful Life')
ax2.set_ylabel('Probability Density')
ax2.set_title('RUL Distribution')
ax2.legend()
ax2.grid(True)

plt.tight_layout()
plt.show()

Example 3: Batch Fitting and Sequential Updating

import numpy as np
from exponential_degradation import ExponentialDegradationModel

# Generate synthetic degradation data (30 points total)
np.random.seed(42)
true_theta = 0.2
true_beta = 0.15
all_times = np.linspace(1, 30, 30)
all_measurements = np.exp(true_theta + true_beta * all_times) + np.random.normal(0, 0.3, 30)

# Split data: first 5 points for batch fitting, remaining 25 for sequential updates
initial_times = all_times[:5]
initial_measurements = all_measurements[:5]
update_times = all_times[5:]
update_measurements = all_measurements[5:]

# Initialize model with appropriate threshold
model = ExponentialDegradationModel(threshold=200.0)

# Step 1: Batch fitting with initial 5 points
print("Step 1: Initial batch fitting with 5 points")
model.fit(initial_measurements, initial_times)
result = model.predict_rul()
print(f"  Current time: {model.ti:.2f}")
print(f"  Predicted RUL: {result['RUL']:.2f}")
print(f"  95% CI: [{result['CI'][0]:.2f}, {result['CI'][1]:.2f}]")
print(f"  Parameters: theta={model.theta:.3f}, beta={model.beta:.3f}")

# Step 2: Sequential updates with remaining 25 points
print("\nStep 2: Sequential updates with remaining 25 points")
print(f"{'Time':<8} {'Measurement':<14} {'RUL':<10} {'CI Width':<12} {'Theta':<10} {'Beta':<10}")
print("-" * 72)

rul_history = []
ci_width_history = []

for t, m in zip(update_times, update_measurements):
    model.update(m, t)
    result = model.predict_rul()
    ci_width = result['CI'][1] - result['CI'][0]
    
    # Store for analysis
    rul_history.append(result['RUL'])
    ci_width_history.append(ci_width)
    
    # Print every 5th update for brevity
    if int(t) % 5 == 0 or t == update_times[-1]:
        print(f"{t:<8.1f} {m:<14.2f} {result['RUL']:<10.2f} {ci_width:<12.2f} "
              f"{model.theta:<10.3f} {model.beta:<10.3f}")

# Final prediction summary
print("\nFinal Prediction (after 30 observations):")
final_result = model.predict_rul()
print(f"  Median RUL: {final_result['RUL']:.2f}")
print(f"  Mean RUL: {final_result['mean']:.2f}")
print(f"  Std Dev: {final_result['std']:.2f}")
print(f"  95% CI: [{final_result['CI'][0]:.2f}, {final_result['CI'][1]:.2f}]")
print(f"  Final parameters: theta={model.theta:.4f}, beta={model.beta:.4f}, rho={model.rho:.4f}")

# Analysis
print("\nObservation: CI width decreased from", f"{ci_width_history[0]:.2f} to {ci_width_history[-1]:.2f}")
print("             Parameter estimates converged with more data")
print(f"\nThis example demonstrates the hybrid approach:")
print(f"  1. Batch fitting (fit) with initial data for fast initialization")
print(f"  2. Sequential updating (update) for real-time monitoring")
print(f"  3. Uncertainty reduction as more observations are incorporated")

Example 4: Comparing Different Initial Parameters

import numpy as np
from exponential_degradation import ExponentialDegradationModel

# Same data, different initial parameter uncertainties
times = np.array([1, 2, 3, 4, 5])
measurements = np.array([1.5, 2.5, 4.0, 6.5, 10.0])

# High initial uncertainty (default)
model_uncertain = ExponentialDegradationModel(
    threshold=15.0,
    theta_variance=1e6,
    beta_variance=1e6
)
model_uncertain.fit(measurements, times)
result_uncertain = model_uncertain.predict_rul()

# Low initial uncertainty (strong prior)
model_informed = ExponentialDegradationModel(
    threshold=15.0,
    theta=0.5,
    theta_variance=0.1,
    beta=0.4,
    beta_variance=0.01
)
model_informed.fit(measurements, times)
result_informed = model_informed.predict_rul()

print("High Uncertainty Prior:")
print(f"  RUL: {result_uncertain['RUL']:.2f}")
print(f"  95% CI: [{result_uncertain['CI'][0]:.2f}, {result_uncertain['CI'][1]:.2f}]")
print(f"  CI Width: {result_uncertain['CI'][1] - result_uncertain['CI'][0]:.2f}")

print("\nLow Uncertainty Prior (Informed):")
print(f"  RUL: {result_informed['RUL']:.2f}")
print(f"  95% CI: [{result_informed['CI'][0]:.2f}, {result_informed['CI'][1]:.2f}]")
print(f"  CI Width: {result_informed['CI'][1] - result_informed['CI'][0]:.2f}")

When to Use This Model

Suitable Applications

This model is appropriate when:

  • ✅ Degradation follows an exponential growth pattern
  • ✅ Measurements are available over time
  • ✅ A clear failure threshold can be defined
  • ✅ Degradation is monotonically increasing
  • Uncertainty quantification is important

Example Applications

  • Bearing degradation: Vibration amplitude growth
  • Battery capacity fade: Capacity loss over charge cycles
  • Crack propagation: Crack size growth in structural components
  • Wear processes: Tool wear, brake pad wear
  • Corrosion: Material thickness loss
  • Sensor drift: Calibration drift in sensors

Not Suitable For

  • ❌ Non-exponential degradation patterns (linear, power-law, etc.)
  • ❌ Non-monotonic degradation (with recovery or fluctuations)
  • ❌ Systems without clear failure thresholds
  • ❌ Sudden failures without gradual degradation

Technical Details

Numerical Stability

The implementation includes several features to ensure numerical stability:

  • Variance clamping to prevent negative variances
  • Truncation at zero for physically meaningful RUL values
  • Safe handling of extreme parameter values
  • Fallback strategies for edge cases
  • Warning flags for numerical issues

Parameter Initialization

For systems with weak prior knowledge, use large initial variances (default 1e6) to allow the data to drive parameter estimates. For systems with strong prior knowledge, set smaller variances and appropriate mean values for theta and beta.

Measurement Requirements

For reliable parameter estimation:

  • Minimum 3-5 measurements recommended
  • Measurements should span a significant portion of the degradation range
  • More frequent measurements early in life improve predictions
  • Measurements closer to failure threshold provide more information

Dependencies

  • Python ≥ 3.8
  • NumPy ≥ 1.20.0
  • SciPy ≥ 1.7.0

Optional (for examples and visualization):

  • Matplotlib ≥ 3.5.0
  • Jupyter ≥ 1.0.0

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

License

This project is licensed under the MIT License - see the LICENSE file for details.

References

  1. Gebraeel, N. (2006). "Sensory-Updated Residual Life Distributions for Components With Exponential Degradation Patterns." IEEE Transactions on Automation Science and Engineering, 3(4), 382-393.

  2. MATLAB Documentation: exponentialDegradationModel

  3. Si, X. S., Wang, W., Hu, C. H., & Zhou, D. H. (2011). "Remaining useful life estimation–a review on the statistical data driven approaches." European Journal of Operational Research, 213(1), 1-14.

Author

Tianjun HOU

Acknowledgments

This implementation is based on the theoretical framework developed by Prof. Nagi Gebraeel and draws inspiration from MATLAB's Predictive Maintenance Toolbox.


Keywords: prognostics, remaining useful life, RUL, degradation modeling, predictive maintenance, reliability engineering, exponential degradation, Bayesian updating

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

exponential_degradation_model-0.1.0.tar.gz (260.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

exponential_degradation_model-0.1.0-py3-none-any.whl (15.4 kB view details)

Uploaded Python 3

File details

Details for the file exponential_degradation_model-0.1.0.tar.gz.

File metadata

File hashes

Hashes for exponential_degradation_model-0.1.0.tar.gz
Algorithm Hash digest
SHA256 16746009885b6d5154aed2538f7a118350f31c345f1a2aa8f5f4a835d99ce5a1
MD5 d80e9282ee90446ed648566418e4dae3
BLAKE2b-256 f2365b1e41cbde604d320b26f1ed3a00a66c2083891525f1b86f3b6e487369ae

See more details on using hashes here.

File details

Details for the file exponential_degradation_model-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for exponential_degradation_model-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c84e2cdda8d8d1f72dca6465fb9cb18f765ce2568e66753b1f75d5b3239d52cd
MD5 2f4e09b349fef52437de6e970789e66f
BLAKE2b-256 7c824cc1b6ffa5204294980468872516428b5110cd4d8f654039f0517783a1cb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page