简介:一份发表于《海军航空工程学院学报》的学术论文PDF,面向故障诊断、健康管理与数据建模方向的工程师与研究者,系统讲解基于神经网络的轴承故障预测方法。论文从传统修复性与预防性维修的局限切入,对比基于失效物理与数据驱动两类预测模型,并重点围绕BP神经网络展开,详细阐述神经元结构、正向传播与误差反向传播算法,结合轴承全寿命监测数据完成特征提取与剩余寿命评估实验验证。资源为单个PDF文件,大小约273KB,已有202人浏览学习。对于希望快速掌握神经网络在轴承剩余寿命预测中的应用原理、理解BP算法建模与验证流程的读者,这份资料提供了理论推导与实验设计兼备的浓缩参考。
1. 轴承故障预测为什么要选 BP 神经网络这条数据驱动路线
滚动轴承一旦在高速运转中失效,轻则产线停机,重则引发安全事故。传统的修复性维修是坏了再换,预防性维修则是按固定周期换件,看似稳妥,但周期定短了浪费寿命,定长了又可能扛不住突发失效。真正的出路是把“定期保养”改成“按健康状态保养”,也就是视情维修。视情维修的核心是一个量化指标——剩余使用寿命(RUL),而轴承振动信号里恰好埋着衰退趋势。问题在于振动数据高度非线性、强波动,物理建模几乎推不出一个通用的失效方程。所以这两年工业界的共识是走数据驱动:让神经网络直接从监测数据里学出“健康状态→RUL”的映射。这篇论文的思路正是如此,用 BP 神经网络对轴承全寿命振动数据做特征提取和回归建模,在实验数据上验证了后期预测精度。对做设备健康管理(PHM)的人来说,这是一个结构不大但流程完整的基线方案,尤其适合入门故障预测时先跑通特征工程、训练、滤波这一整条链路。
2. BP 神经网络结构与前向/反向传播推导
2.1 BP 神经元与前馈连接方式
BP 神经网络是一种多层前馈网络,信号从输入层逐层传到输出层,不跨层连接。论文中给出的神经元结构很典型:上一层的输出作为当前神经元的输入,每个输入乘一个权重,累加后加上阈值并且经过传递函数,得到该神经元输出。公式上,神经元的净输入是
$$s_j = \sum_{i=1}^{n} w_{ji} x_i + \theta_j = W_j^T X_j$$
其中 $X_j = [x_1, x_2, \cdots, x_n, 1]^T$,$W_j = [w_{j1}, w_{j2}, \cdots, w_{jn}, \theta_j]^T$。这里的阈值 $\theta_j$ 被统一写成 $w_{j0}$ 且对应输入 $x_0=1$,好处是梯度推导时阈值可以和权重一样处理,不用单独写一套规则。
传递函数 $f(\cdot)$ 在论文里隐含层常用 Sigmoid,输出层若做回归则常用线性函数。Sigmoid 的导数是 $\sigma'(s) = \sigma(s)(1 - \sigma(s))$,计算很方便,这也是 BP 算法能高效收敛的原因之一。
2.2 正向传播与误差函数
假设输入层有 $n$ 个节点,隐含层有 $q$ 个节点,输出层有 $m$ 个节点。隐含层输出为
$$z_j = f\left(\sum_{i=1}^{n} v_{ji} x_i\right)$$
输出层输出为
$$y_k = g\left(\sum_{j=1}^{q} w_{kj} z_j\right)$$
其中 $v_{ji}$ 是输入层到隐含层的权重,$w_{kj}$ 是隐含层到输出层的权重。训练样本是 ${(x^{(p)}, y^{(p)})}_{p=1}^{P}$,第 $p$ 个样本的期望输出是 $t^{(p)}$,实际输出是 $y^{(p)}$。定义全局误差为
$$E = \frac{1}{2} \sum_{p=1}^{P} \sum_{k=1}^{m} \left(t_k^{(p)} - y_k^{(p)}\right)^2$$
前面的 $\frac{1}{2}$ 是为了求导后消掉平方项的系数,不影响最优点。BP 的目标就是找到一组权重使 $E$ 最小。
2.3 反向传播权重更新推导
反向传播的核心是链式求导。以隐含层到输出层的权重 $w_{kj}$ 为例,误差对 $w_{kj}$ 的偏导为
$$\frac{\partial E}{\partial w_{kj}} = \frac{\partial E}{\partial y_k} \cdot \frac{\partial y_k}{\partial s_k} \cdot \frac{\partial s_k}{\partial w_{kj}}$$
三项分别计算:$\frac{\partial E}{\partial y_k} = -(t_k - y_k)$,$\frac{\partial y_k}{\partial s_k} = g'(s_k)$,$\frac{\partial s_k}{\partial w_{kj}} = z_j$。所以
$$\Delta w_{kj} = \eta \sum_{p} (t_k - y_k) g'(s_k) z_j$$
输入层到隐含层的权重 $v_{ji}$ 需要把误差继续往回传:
$$\Delta v_{ji} = \eta \sum_{p} \left[ \sum_{k} (t_k - y_k) g'(s_k) w_{kj} \right] f'(s_j) x_i$$
论文里省略了中间步骤,直接给出了最终迭代式。实操时不需要手写这些链式求导,但理解这个流程对调学习率、诊断梯度消失很有帮助。比如隐含层梯度里乘了 $f'(s_j)$,Sigmoid 饱和区导数趋近 0,这就是为什么权重初始化不能太大、数据要归一化的理论根源。
3. 轴承振动特征提取:时域、频域与小波低频分量的组合
3.1 浴盆曲线与特征选择依据
轴承从健康到失效,故障发生率呈浴盆曲线形态,分为早期失效期、偶然失效期和耗散失效期。故障预测关注的是偶然失效期和耗散失效期,因为这两个阶段轴承开始出现可观测的退化趋势。论文的思路是:提取的特征必须和浴盆曲线的后两段形状吻合,才能真实反映衰退过程。如果提取的均值、方差曲线一直平坦,直到失效前才突变,那对剩余寿命预测几乎没有帮助。
从全寿命振动数据里,论文选了 8 个特征:
| 序号 | 特征描述 | 类型 |
|---|---|---|
| 1 | 一个振动周期的均值 | 时域 |
| 2 | 一个振动周期的方差 | 时域 |
| 3 | 一个振动周期数据傅里叶变换的功率谱 | 频域 |
| 4 | 小波分解后的低频分量 A1 | 时频 |
| 5 | 小波分解后的低频分量 A2 | 时频 |
| 6 | 小波分解后的低频分量 A3 | 时频 |
| 7 | 小波分解后的低频分量 A4 | 时频 |
| 8 | 小波分解后的低频分量 A5 | 时频 |
为什么选这 8 个?均值能反映振动能量的缓慢趋势,方差能体现波动程度的加剧,功率谱则刻画频域能量的分布变化。小波低频分量保留的是信号的大致轮廓,滤掉了高频噪声,和轴承整体的磨损趋势更相关,比直接拿原始振动幅值稳定得多。
3.2 特征提取代码实现
常见做法是先把振动信号按一个转轴的旋转周期切段,比如每段 2560 个采样点,然后对每段计算特征。代码用 Python 写:
import numpy as np from scipy.fft import rfft import pywt def extract_features(signal, fs): """ 输入:一段轴承振动信号,shape=(N,) 输出:8维特征向量 """ # 1. 均值 mean_val = np.mean(signal) # 2. 方差 var_val = np.var(signal) # 3. 傅里叶功率谱(取正频部分并计算能量) freq_spec = np.abs(rfft(signal)) ** 2 power_spectrum = np.mean(freq_spec[1:]) # 去掉直流分量,取平均功率 # 4-8. 小波分解取5层低频分量 coeffs = pywt.wavedec(signal, 'db4', level=5) low_freq_components = coeffs[1:] # 各层近似系数,实际是cA1~cA5 # 对各层低频系数求均方根,作为特征值 low_freq_features = [np.sqrt(np.mean(c**2)) for c in low_freq_components] feature_vector = np.array([mean_val, var_val, power_spectrum] + low_freq_features) return feature_vector这段代码里,rfft返回正频率部分,去掉直流后取均值,得到的是信号在频域上的平均能量。小波分解用db4小波,分解 5 层,coeffs[1:]是各层逼近系数。对每一层系数取均方根值,是为了把不同长度系数压缩成一个标量。注意:故障预测的特征必须按时间序列排列,每个时间节点算一次,最终得到一个(时间节点数, 8)的特征矩阵。
3.3 中值滤波与归一化处理
提取完特征后,两类处理是必须的。第一是中值滤波,目的是去掉振动瞬时冲击造成的毛刺,让特征曲线更平滑。中值滤波的窗口大小取 3~5 个时间节点比较合适,窗口太小滤波不明显,太大会抹掉真实的衰退突变。第二是归一化,原始特征量纲差异很大:均值可能只有 0.5,功率谱可能到几千,如果不归一化,BP 神经网络训练时大数值特征会主导权重更新,导致小数值特征失效。论文里的归一化函数没有给具体形式,一般用 min-max 归一化:
$$x_{\text{norm}} = \frac{x - x_{\min}}{x_{\max} - x_{\min}}$$
注意:归一化参数必须只用训练集的 min/max 计算,不能混入测试集,否则会引入未来数据的信息,造成评估结果虚高。这是故障预测里最常见的泄露错误之一。
下面是归一化和中值滤波的示例代码:
from scipy.signal import medfilt def preprocess_features(feature_matrix_train, feature_matrix_test): """ 特征矩阵shape: (n_samples, n_features) 返回训练和测试的归一化特征,参数仅从训练集获取 """ n_features = feature_matrix_train.shape[1] train_norm = np.zeros_like(feature_matrix_train) test_norm = np.zeros_like(feature_matrix_test) for i in range(n_features): # 中值滤波,窗口大小5 train_col = medfilt(feature_matrix_train[:, i], kernel_size=5) test_col = medfilt(feature_matrix_test[:, i], kernel_size=5) # 从训练集取min/max fmin = train_col.min() fmax = train_col.max() train_norm[:, i] = (train_col - fmin) / (fmax - fmin + 1e-10) test_norm[:, i] = (test_col - fmin) / (fmax - fmin + 1e-10) return train_norm, test_norm这里medfilt是 scipy 提供的一维中值滤波,kernel_size=5表示取前后共 5 个点的中位数。分母加上1e-10防止除零。测试集归一化用的是训练集的fmin和fmax,这一点在工程上必须严格执行。
4. 基于 BP 神经网络的剩余寿命预测实现
4.1 训练样本构造与网络结构参数
训练样本的构造方式是:设 $x_i$ 为第 $i$ 个时间节点的特征向量,$r_i$ 为该节点对应的真实剩余寿命,单位是振动监测周期的个数。把 ${(x_i, r_i)}$ 输入 BP 神经网络训练。这样网络学习到的映射是“当前特征→还能活多久”,而不是“特征→是否故障”,所以输出层的激活函数用线性函数,也就是不加任何压缩。
网络结构上,输入层节点数固定为 8,输出层节点数为 1,关键调的是隐含层节点数。按论文实验的规模,隐含层取 10 个节点、单隐层就够用。节点数太少拟合能力不足,预测曲线会过于平滑;节点数太多容易过拟合,在训练集上误差极小、测试集上误差反弹。一个参考经验:
| 样本量级 | 隐含层节点数建议 | 隐含层层数 |
|---|---|---|
| <1000 | 5~10 | 1 |
| 1000~5000 | 10~20 | 1~2 |
| >5000 | 20~50 | 2 |
4.2 训练过程与学习率设置
权重优化采用梯度下降。论文推导出的更新公式,在实现里就体现为一句代码:weights -= learning_rate * gradient。学习率 $\eta$ 取 0.01 比较保险,迭代次数设 1000,误差阈值设 0.0001。如果学习率太大,权重会来回震荡无法收敛;太小则收敛慢。下面用 Python 和 scikit-learn 的MLPRegressor给出一个可跑的示例:
from sklearn.neural_network import MLPRegressor from sklearn.metrics import mean_absolute_error # X_train, y_train 已经归一化 # y_train 是剩余寿命,也可以归一化到[0,1]帮助收敛 model = MLPRegressor( hidden_layer_sizes=(10,), # 单隐层10个节点 activation='logistic', # Sigmoid solver='sgd', # 随机梯度下降 learning_rate_init=0.01, max_iter=1000, tol=1e-4, random_state=42 ) model.fit(X_train, y_train) # 预测训练集并查看误差 y_pred_train = model.predict(X_train) print(f"训练集平均绝对误差: {mean_absolute_error(y_train, y_pred_train):.4f}")hidden_layer_sizes=(10,)表示单隐层 10 节点。activation='logistic'对应论文中的 Sigmoid。solver='sgd'就是 BP 梯度下降,如果数据量不大也可以用adam更快收敛,但论文里描述的是标准 BP 过程,这里保持一致。tol=1e-4是迭代停止的误差阈值。注意 y 如果也做了归一化,预测后要反向还原才能得到真实寿命周期的数值。
4.3 剩余寿命粗估计与滑动窗口滤波
训练完成后,对待估样本的每个时间节点输入特征 $x_i$,网络输出一个剩余寿命粗估计 $\hat{r}_i$。由于振动监测数据本身是序贯的,相邻节点的真实剩余寿命应该接近,所以论文对粗估计做了进一步滤波:对当前节点取前后共 n 个节点的估计值求平均。论文实验里 n 取 3,公式是
$$\widetilde{r}i = \frac{1}{3} \sum{k=i-1}^{i+1} \hat{r}_k$$
这种滑动平均能明显抑制单点突变。实现时要注意边界处理:前两个和后两个节点不足 3 个邻居,常见做法是只对有效邻居求平均,或者对边界节点直接沿用粗估计。代码示例:
def sliding_average_filter(r_est, window=3): half = window // 2 n = len(r_est) r_smooth = np.zeros_like(r_est) for i in range(n): left = max(0, i - half) right = min(n - 1, i + half) r_smooth[i] = np.mean(r_est[left:right + 1]) return r_smooth窗口大小 n=3 是论文里的值,实际使用时可以尝试 n=5 或 n=7,观察曲线平滑度和响应速度。窗口越大曲线越平滑,但对真实的寿命突降会反应迟钝。如果预测目标是给出“还能工作多少分钟”,用 n=5 也行,但要在评估指标里加入对突变时刻的惩罚,不然单纯追求平滑会把失效点提前或延后。
5. 实验验证与工程化排错:从两套数据到可靠部署
5.1 训练集与测试集划分及结果评估
论文用了两组轴承全寿命数据,一组做训练集,一组做测试集。这种“用某台轴承的完整寿命数据训练,再预测另一台轴承”的设置非常接近真实场景,因为实际部署时不可能为每一台轴承都先跑到失效再训练。评估方式是绘制测试集的剩余寿命估计值与真实值随时间的对比曲线,论文给出的结果表明:模型整体预测趋势接近真实值,且运行后期节点 t > 800 后,剩余寿命估计准确率显著提高。这个现象很符合 BP 神经网络的特性——退化后期特征变化明显,网络更容易区分不同的寿命阶段。
为了量化评估,建议在测试集上计算平均绝对误差和误差随寿命区间分布。比如:
| 寿命区间 | 平均绝对误差(周期) | 相对误差 |
|---|---|---|
| 全寿命期 | 18.6 | 12.3% |
| 后期(t>800) | 6.2 | 6.8% |
后期误差更小是因为轴承进入耗散失效期后,振动能量和频域分量都会快速上升,特征和剩余寿命的线性关系更强,网络容易把握。而早期退化缓慢,特征变化小,预测偏差大也正常。工程上如果必须提高早期精度,可以考虑把早期样本加权,或者改用时序模型,比如 LSTM、TCN,不过这些模型需要的数据量和训练成本会明显增加。
5.2 六个容易踩的坑与规避方法
第一,归一化泄露。前面提过,测试集的 min/max 必须来自训练集。很多人直接对整个数据集做归一化再切分,导致测试信息提前进入训练,验证结果虚高。
第二,特征对齐错误。剩余寿命是按“节点到失效点的周期数”计算的,如果节点定义用的是“等间隔时间”,而不是“等转数”,轴承转速波动时特征对应关系就会错位。最好按主轴转数或固定角度采样。
第三,对粗估计直接取整输出。网络输出是连续值,而真实寿命是整数周期。不要在模型输出处直接 round,而是保留浮点数做后续滤波,最后再按业务需要向上取整为“安全寿命”。
第四,过度依赖滑动平均。滤波窗口 n=3 在论文实验里表现不错,但换数据后要先做敏感性实验。用一个简单脚本扫描 n=1,3,5,7,9,观察平均绝对误差的变化,选误差最小的窗口,而不是直接照搬。
第五,忽略失效阶段识别。浴盆曲线提示轴承从健康到失效要经历两个阶段,如果设备长期处于早期平稳期,特征几乎不变,此时网络给出的预测可能长期停留在一个常数附近,产生“估计值偏保守”的错觉。建议结合趋势检测,当特征斜率超过阈值时才激活寿命预测,否则只输出“健康”。
第六,训练样本太少导致的偏差。论文里只有两组数据,一组训练一组测试,本质上是单样本验证,泛化性能没有被充分评估。实操中至少要准备 10 组以上全寿命数据,用留一法或 K 折交叉验证,才能比较可信地估计模型在其它轴承上的误差。
最后一个可用技巧:把 BP 网络的输出残差分析一下。如果残差随时间的增大而增大,说明模型对后期的预测方差变大,此时可以在后期给滤波窗口加权,比如靠近失效点使用更短的窗口,让预测值更快跟随真实衰变。反过来,如果残差集中在早期,则说明特征提取不够敏感,优先检查小波低频分量是否覆盖了早期微弱磨损的频率带,而不是急于调网络结构。把这条残差分析流程固定为每次实验后的例行检查,比盲目调参要高效得多。
本文还有配套的精品资源,点击获取