第零课:RUL 是什么?------生活中的直觉
生活中的「还能用多久」
| 场景 | 问题 | 你已经在做的「预测」 |
| 手机电池 | 还能撑多久? | 看电量百分比、充电次数,心里有数 |
| 汽车轮胎 | 还能跑多少公里? | 看磨损、胎压、使用里程 |
| 打印机墨盒 | 还能打多少页? | 看剩余墨水、打印量 |
| 电梯钢丝绳 | 还能用多久才需更换? | 看磨损、裂纹、使用次数 |
|---|
RUL(Remaining Useful Life)就是在回答:从【现在】到【失效】还有多长时间(或多少次循环)。
三类维护策略
|-------------------|---------------------------|
| 故障后维护(Reactive) | 坏了再修,成本高、停机风险大 |
| 定期维护(Preventive) | 固定周期更换,可能换得太早浪费、或太晚已坏 |
| 预测性维护(Predictive) | 根据状态预测「还能撑多久」,在最佳时机安排维护 ✓ |
RUL 是预测性维护的核心:告诉你【大概还能用X小时】,你就可以提前排检修、备件、不停产。
第一课:RUL 的数学定义与问题形式
1.1 时间线理解
时间轴: [安装/大修] ──────── t_current ──────── [失效]
↑
"现在"这个时刻
RUL = t_failure - t_current (剩余到失效的时间)
-
t_current:当前时刻(或当前采样周期)
-
t_failure:失效时刻(设备不能继续安全运行的时刻)
-
RUL:从当前到失效的剩余时间(小时、天、或采样周期数)
1.2 退化 vs 故障
| 概念 | 含义 | 例子 |
|---|---|---|
| 退化 | 性能/健康度随时间逐渐变差 | 轴承磨损越来越严重、振动变大、温度升高 |
| 故障 | 已不能正常工作的状态 | 轴承卡死、断裂、严重异响 |
| RUL 预测 | 在退化过程中预测「距离故障还有多久」 | 根据当前振动/温度曲线,估计还能运行 X 小时 |
关键是:我们需要在「还没坏」的时候,根据当前状态预测「什么时候会坏」。
1.3 RUL 的表示方式
| 方式 | 说明 | 例子 |
|---|---|---|
| 直接 RUL | 剩余小时/天 | RUL = 45 小时 |
| 健康指数 HI | 0--100% 健康度 | HI = 62% |
| 分段 RUL | 粗分类 | 0--7天 / 7--30天 / 30天以上 |
选用建议:
| 场景 | 更推荐 |
|---|---|
| 有 run-to-failure 数据,需精确排程 | 直接 RUL |
| 无完整失效数据,或主要做健康监控 | 健康指数 HI |
| 快速上线、资源有限、只需粗略分级 | 分段 RUL |
实际落地时可以组合使用:例如模型输出「直接 RUL」,再映射成 HI 用于仪表盘展示,同时用分段 RUL 做告警优先级。
第二课:超简单示例------手机电池「健康度」
2.1 不用 AI 也能做「预测」
手机电池的「健康度」本质就是一种简化的 RUL:
健康度 = f(充电循环次数, 使用时间, 温度历史)
≈ 初始容量 × 衰减曲线(循环次数)
-
输入:充电次数、使用时长、温度等
-
输出:健康度百分比(相当于归一化的「剩余寿命」)
很多手机用经验公式就能算,不需要深度学习。
2.2 退化曲线的直觉
健康度/性能
100% │●
│ ●
│ ●
│ ●●
│ ●●●
│ ●●●●
│ ●●●●● ← 接近失效
0% └──────────────────────────→ 时间/循环次数
安装 正常期 退化期 失效
-
正常期:性能基本稳定,RUL 很大(可截断为常数)
-
退化期:性能下降,RUL 随时间减小
-
失效:RUL ≈ 0
2.3 从「健康度」到「RUL」
若健康度 60%,且已知「从 100% 到 0% 大约需要 500 次循环」:
-
剩余循环数 ≈ 500 × (60% - 0%) = 300 次
-
若每次循环约 1 天 → RUL ≈ 300 天(粗略估计)
这已经是一个最简单的 RUL 模型:用健康度线性映射到剩余时间。
第三课:用 Python 做第一次 RUL 预测
3.1 构造「假想」的退化数据
我们先不用真实传感器,用公式生成一条从「健康」到「失效」的曲线:
python
import numpy as np
import matplotlib.pyplot as plt
# 模拟一条轴承退化曲线:振动幅值随时间增加
np.random.seed(42)
n_steps = 200 # 200 个时间步,模拟从安装到失效
# 退化模型:健康时振动低,越接近失效振动越高
t = np.linspace(0, 1, n_steps)
vibration = 0.1 + 0.9 * t**2 + np.random.randn(n_steps) * 0.05 # 振动随 t 增加
vibration = np.maximum(vibration, 0.1) # 确保非负
# 每个时刻的 RUL = 剩余步数(或剩余时间)
rul = np.arange(n_steps - 1, -1, -1) # [199, 198, ..., 1, 0]
# 画出来看看
plt.figure(figsize=(10, 4))
plt.subplot(1, 2, 1)
plt.plot(vibration, 'b-', label='振动幅值')
plt.xlabel('时间步')
plt.ylabel('振动')
plt.legend()
plt.subplot(1, 2, 2)
plt.plot(rul, 'g-', label='RUL (剩余步数)')
plt.xlabel('时间步')
plt.ylabel('RUL')
plt.legend()
plt.tight_layout()
plt.show()
运行结果:

要点:
-
振动越大 → 越接近失效 → RUL 越小
-
每个时刻我们已知「真实的 RUL」(因为我们是用公式生成的)
3.2 用线性回归预测 RUL
把「振动」当输入,RUL 当输出,用线性回归做第一次预测:
python
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error
# 输入:最近 10 步的振动均值(简化版「特征」)
window = 10
X = np.array([vibration[i:i+window].mean() for i in range(n_steps - window)])
y = rul[window:] # 对应的 RUL
model = LinearRegression()
model.fit(X.reshape(-1, 1), y)
y_pred = model.predict(X.reshape(-1, 1))
print(f"MAE: {mean_absolute_error(y, y_pred):.1f} 步")
# 画预测 vs 真实
plt.figure(figsize=(8, 4))
plt.plot(y, label='真实 RUL', alpha=0.7)
plt.plot(y_pred, label='预测 RUL', alpha=0.7)
plt.legend()
plt.xlabel('样本索引')
plt.show()
运行结果:

这就是最朴素的 RUL 预测:输入是「当前状态」的简单特征,输出是 RUL。
第四课:时序数据与滑窗------RUL 的「输入」怎么来
4.1 为什么要用时序?
真实场景中,我们有的不是「一个数」,而是一段时间的传感器读数:
python
时刻: t-4 t-3 t-2 t-1 t(现在)
振动: [0.2, 0.3, 0.35, 0.4, 0.45] ← 这段序列
温度: [32, 33, 34, 35, 36] ← 这段序列
↓
模型要输出: RUL = 45 小时
-
单点值信息太少,无法反映趋势
-
一段序列能反映:是突然恶化,还是缓慢退化
4.2 滑窗构造样本
给定一整条 run-to-failure 轨迹,用滑窗切成多个训练样本:
python
def create_sliding_windows(signal, rul, seq_len=50):
"""从整条退化轨迹构造 (x, y_rul) 样本"""
n = len(signal)
X, y = [], []
for i in range(n - seq_len):
x = signal[i:i+seq_len] # 输入:一段序列
target_rul = rul[i+seq_len-1] # 标签:该段末尾时刻的 RUL
X.append(x)
y.append(target_rul)
return np.array(X), np.array(y)
# 示例
X, y = create_sliding_windows(vibration, rul, seq_len=20)
print(f"样本数: {len(X)}, 输入形状: {X.shape}, 输出形状: {y.shape}")
# 样本数: 180, 输入形状: (180, 20), 输出形状: (180,)
每个样本:输入 = 过去 20 步的振动序列,输出 = 当前时刻的 RUL。
4.3 多变量扩展
设备有多个传感器:振动、温度、电流等。输入就变成:
python
x: (batch, seq_len, num_channels)
例如 (32, 512, 3) = 32 样本 × 512 时间步 × 3 通道(振动X、振动Y、温度)
y_rul: (batch,)
第五课:简单深度学习------LSTM 做 RUL
5.1 为何用深度学习?
-
线性回归只能看「一个数」,无法捕捉时序模式
-
LSTM 可以学习「振动先升后降再升」这类复杂模式
-
工业界常用 LSTM、1D-CNN、Transformer 做 RUL
5.2 最简 LSTM RUL 示例(伪代码逻辑)
python
# 概念性代码,展示结构
import torch
import torch.nn as nn
class SimpleLSTM_RUL(nn.Module):
def __init__(self, input_dim=1, hidden=64):
super().__init__()
self.lstm = nn.LSTM(input_dim, hidden, batch_first=True)
self.fc = nn.Linear(hidden, 1) # 输出一个数:RUL
def forward(self, x):
# x: (batch, seq_len, 1)
out, _ = self.lstm(x)
last = out[:, -1, :] # 取最后时间步
rul = self.fc(last) # (batch, 1)
return rul
训练时:
-
输入:
(batch, seq_len, channels)的振动/温度序列 -
标签:每段对应的 RUL
-
损失:MSE 或 Smooth L1