☰
变转速变载荷下滚动轴承退化指标构建:RBFNN与KPCA组合方法
2026/10/2 17:35:22 网站建设 项目流程

简介:这份资源面向具备机械工程或数据分析背景、熟悉Python与机器学习基础的研究生及设备状态监测研发人员,聚焦变转速变载荷工况下滚动轴承振动信号受干扰、可靠性评估困难的问题。内容以径向基函数神经网络建立系统状态特征映射,结合核主成分分析对有效参数降维,并将第一主成分作为轴承性能退化指标,同时涉及CNN、BiGRU等模型在故障诊断与寿命预测中的集成应用。资源包为1个PDF文件,约992KB,内含完整可运行代码及逐段解释,覆盖时域与频域特征提取、RBF映射、KPCA降维到可靠性计算的衔接逻辑。已有52人学习,适合用于构建退化指标、早期故障预警与剩余寿命预测的技术参考,也可通过更换不同工况数据验证模型鲁棒性。

1. 变转速变载荷下,滚动轴承退化指标为什么不能直接套 RMS

设备维护工程师最怕的场景之一:一台关键机组,转速随工艺需求频繁调整,负载也跟着工况波动,你在实验室用恒定工况标定好的 RMS 报警阈值,一上线就疯狂误报。振动烈度随转速平方增长,载荷变化又直接改变接触应力分布,同一套阈值在变转速变载荷下几乎必然失效。这就是 RBFNN-KPCA 组合方法要解决的问题——它不追求单一特征的最优,而是先用 KPCA 把高维特征空间里的非线性主成分提取出来,再用 RBFNN 拟合健康状态与退化程度之间的映射,最终构建一个对工况变化不敏感、单调性好的退化指标。适合做旋转机械状态监测、寿命预测的从业者,尤其是手头有变工况数据但苦于指标不收敛的人。

2. RBFNN 与 KPCA 为什么适合做退化指标:从线性到非线性的必然选择

2.1 退化指标的本质要求与线性方法的局限

退化指标不是随便一个统计量。它需要满足三个硬条件:单调性,即随时间推移整体趋势不可逆;鲁棒性,即对噪声和短时工况扰动不敏感;一致性,即同类轴承不同个体的指标曲线形态相似。传统时域指标里,RMS 单调性尚可但工况敏感,峭度对早期冲击敏感但后期反而下降,裕度指标波动大。频域指标如重心频率在转速变化时直接漂移,根本没法用。

线性降维方法如 PCA 假设特征间是线性关系,但轴承退化过程中,磨损、点蚀、剥落引起的振动响应是非线性耦合的。举个直观例子:早期微弱故障在时域上表现为冲击间隔的微小变化,在频域上表现为边频带的缓慢展宽,这两者之间的关系不是线性可加的。PCA 强行用线性超平面去拟合,会把非线性相关的信息当作噪声丢掉,导致退化指标在中期出现平台期,看起来像设备“卡”在某个健康状态不动了。

KPCA 通过核函数把原始特征映射到高维再生核希尔伯特空间,在那个空间里做线性 PCA,等价于在原始空间做非线性主成分分析。核函数的选择决定了映射能力,常用高斯核,因为它能把任意数据映射到无穷维,只要带宽参数选得合理,几乎可以逼近任意连续函数。这一步解决的是“特征空间非线性结构提取”的问题。

2.2 RBFNN 在退化映射中的角色:不是分类器,是回归器

很多人看到 RBFNN 第一反应是分类,但在退化指标构建里,它做的是回归。输入是 KPCA 降维后的主成分得分,输出是一个标量健康度,通常归一化到 0 到 1 之间,1 表示全新,0 表示失效。

RBFNN 的结构分三层:输入层接收 KPCA 得分,隐含层做径向基函数非线性变换,输出层线性加权求和。隐含层每个神经元的激活函数是高斯函数,中心向量和宽度参数决定了它对输入空间中哪个区域敏感。输出层权重通过最小二乘或梯度下降求解。

为什么不用 BP 神经网络?因为 RBFNN 在样本量不大时收敛更快,且局部响应特性让它对训练数据中的局部退化模式更敏感。BP 网络全局逼近能力强,但容易过拟合,尤其在变工况数据里,工况切换点附近的样本少,BP 网络容易把工况变化误学成退化。RBFNN 的局部性反而成了优势——它不会因为某个工况下样本少就强行外推。

2.3 从原始振动到退化指标:完整信号处理链路

整个链路分四步。第一步,原始振动信号按固定长度切片,通常取 1024 或 2048 点,重叠率 50%。第二步,对每个切片提取时域和频域特征,时域包括 RMS、峭度、峰值因子、裕度因子、波形因子,频域包括重心频率、频率方差、均方频率,再加上小波包分解后各频带能量比。第三步,所有特征组成高维向量,做归一化,通常用 z-score 或最大最小归一化。第四步,KPCA 降维,取累计贡献率超过 85% 的主成分,再送入 RBFNN 回归。

这里有个容易翻车的地方:归一化必须在训练集上计算均值和标准差,然后应用到测试集。如果对整个数据集一起归一化,测试集信息泄露到训练过程,指标曲线会异常平滑,实际部署时完全不是那么回事。

import numpy as np from sklearn.preprocessing import StandardScaler from sklearn.decomposition import KernelPCA from scipy.stats import kurtosis, skew def extract_features(signal, fs): """从单段振动信号提取时域和频域特征""" features = {} # 时域特征 features['rms'] = np.sqrt(np.mean(signal**2)) features['kurtosis'] = kurtosis(signal) features['skewness'] = skew(signal) features['peak'] = np.max(np.abs(signal)) features['crest'] = features['peak'] / features['rms'] features['clearance'] = features['peak'] / (np.mean(np.sqrt(np.abs(signal)))**2) features['shape'] = features['rms'] / np.mean(np.abs(signal)) # 频域特征 spectrum = np.abs(np.fft.rfft(signal)) freq = np.fft.rfftfreq(len(signal), 1/fs) power = spectrum**2 features['centroid'] = np.sum(freq * power) / np.sum(power) features['variance'] = np.sum((freq - features['centroid'])**2 * power) / np.sum(power) features['msf'] = np.sum(freq**2 * power) / np.sum(power) return features def build_feature_matrix(signals, fs): """构建特征矩阵,每行一个样本""" feat_list = [extract_features(s, fs) for s in signals] keys = feat_list[0].keys() return np.array([[f[k] for k in keys] for f in feat_list]), list(keys)

这段代码里,extract_features对每段信号计算 10 个特征,build_feature_matrix把它们堆成矩阵。注意clearance和shape的计算方式,分母用了绝对值再开方或均值,避免负值导致复数。频域特征里centroid是重心频率,variance是频率方差,msf是均方频率,这三个对转速变化敏感,但在 KPCA 里会被非线性组合,最终退化指标反而能抵消一部分转速影响。

参数方面,fs是采样频率,必须和实际采集系统一致,否则频域特征全错。切片长度建议 1024 点起步,如果转速很低,比如低于 300 转每分钟,要加长到 2048 甚至 4096,保证一个切片里至少包含 3 到 5 个完整旋转周期。

3. KPCA 降维实操:核函数选择、参数调优与主成分个数确定

3.1 高斯核带宽参数的网格搜索与经验公式

KPCA 最关键的参数是高斯核的带宽 gamma。gamma 太大,核矩阵接近单位矩阵,每个样本都变成独立主成分,降维失去意义;gamma 太小,核矩阵所有元素接近 1,主成分全部塌缩到第一维。常见做法是在对数尺度上网格搜索,候选值从 0.001 到 10,步长按 10 的幂次走。

经验公式有两个。一个是中位数启发式:gamma 取 1 除以特征维度与特征方差中位数的乘积。另一个是 Silverman 规则:gamma 等于样本数的负 2/(维度+4) 次方。这两个公式给的是量级参考,实际还要微调。

from sklearn.decomposition import KernelPCA from sklearn.model_selection import GridSearchCV from sklearn.neural_network import MLPRegressor from sklearn.pipeline import Pipeline def optimize_kpca_gamma(X, y): """网格搜索 KPCA 带宽,以 RBFNN 回归的验证集 MSE 为准则""" gammas = [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0] best_gamma = None best_score = np.inf for g in gammas: kpca = KernelPCA(n_components=5, kernel='rbf', gamma=g) X_kpca = kpca.fit_transform(X) # 用简单 RBF 网络做快速评估 from scipy.interpolate import Rbf try: rbf = Rbf(X_kpca[:,0], X_kpca[:,1], y, function='gaussian') pred = rbf(X_kpca[:,0], X_kpca[:,1]) mse = np.mean((pred - y)**2) if mse < best_score: best_score = mse best_gamma = g except: continue return best_gamma, best_score

这段代码用KernelPCA做降维,然后拿前两个主成分用Rbf插值快速评估回归效果。注意这里只是粗筛,真正训练 RBFNN 时要用全部主成分。n_components=5是初始设定,后面还要根据累计贡献率调整。Rbf的function='gaussian'和 KPCA 的高斯核不是一回事,这里只是借它做快速非线性回归评估,别混淆。

网格搜索的代价是计算量大,如果样本超过 5000,建议先用随机子集搜,确定量级后再全量微调。另外,gamma 的最优值对数据尺度敏感,所以特征归一化必须在 KPCA 之前做,而且要用训练集的统计量。

3.2 主成分个数:累计贡献率与重构误差的双重校验

KPCA 没有像 PCA 那样的“解释方差比”直接输出,因为核空间里的方差不是原始空间的方差。确定主成分个数有两个实用方法。

方法一:计算核矩阵的特征值,按降序排列,看累计和占总和的比例。通常取 85% 到 95%。但核矩阵特征值衰减快慢和 gamma 有关,gamma 大时衰减快,取前几个就够;gamma 小时衰减慢,可能要取十几个。

方法二:重构误差。把降维后的主成分反变换回原始特征空间,计算重构误差,看误差随主成分个数增加的下降曲线,拐点处就是合适个数。

def select_n_components(X, gamma, threshold=0.9): """基于核矩阵特征值累计贡献率选择主成分个数""" from sklearn.metrics.pairwise import rbf_kernel K = rbf_kernel(X, gamma=gamma) # 中心化核矩阵 N = K.shape[0] one_n = np.ones((N, N)) / N K_centered = K - one_n @ K - K @ one_n + one_n @ K @ one_n eigvals = np.linalg.eigvalsh(K_centered) eigvals = eigvals[::-1] # 降序 eigvals = np.maximum(eigvals, 0) # 数值误差可能产生负值 cumsum = np.cumsum(eigvals) / np.sum(eigvals) n = np.searchsorted(cumsum, threshold) + 1 return n, cumsum

rbf_kernel直接算核矩阵,然后手动中心化。中心化公式是 K - 1_N K - K 1_N + 1_N K 1_N,其中 1_N 是全 1 矩阵除以 N。eigvalsh用于对称矩阵,返回升序特征值,反转后降序。np.maximum把负特征值截断到 0,这是数值计算常见的后悔药。searchsorted找到累计贡献率首次超过阈值的位置。

实际项目中,我一般会同时看累计贡献率和重构误差,取两者建议的较大值。因为退化指标对信息完整性要求高,宁可多保留一个主成分,也不要因为降维过度丢掉早期微弱故障信息。

3.3 变工况下的特征归一化策略:按工况分组还是全局

变转速变载荷数据有个棘手问题:不同工况下特征分布差异大。如果全局归一化,高转速工况的特征值大,会主导归一化尺度,低转速工况的特征被压缩到很小范围,KPCA 提取的主成分主要反映工况差异而不是退化差异。

两种策略。策略一:按工况分组归一化。先根据转速和载荷把数据分成若干工况组,每组单独计算均值和标准差,组内归一化。这样消除工况影响,但要求工况标签已知,且每个工况组样本量足够。策略二:全局归一化但加入工况特征。把转速和载荷也作为特征输入 KPCA,让非线性降维自己去解耦。这种方法不需要工况标签,但要求 KPCA 的核函数足够强,能捕捉工况与退化之间的交互。

我一般先用策略二,因为工程现场往往拿不到精确的工况标签,转速和载荷是从控制系统读的,有延迟和噪声。如果策略二效果不好,再退回策略一,用聚类方法自动划分工况组。

def normalize_by_condition(X, speeds, loads, n_groups=4): """按转速和载荷聚类分组后归一化""" from sklearn.cluster import KMeans condition_features = np.column_stack([speeds, loads]) kmeans = KMeans(n_clusters=n_groups, random_state=42) labels = kmeans.fit_predict(condition_features) X_norm = np.zeros_like(X) for g in range(n_groups): mask = labels == g if np.sum(mask) < 10: continue scaler = StandardScaler() X_norm[mask] = scaler.fit_transform(X[mask]) return X_norm, labels

KMeans对转速和载荷聚类,n_groups=4是经验值,工况复杂时可以增加到 6 或 8。每个簇内单独StandardScaler。注意如果某个簇样本少于 10,跳过归一化,保留原始值,否则均值和标准差估计不可靠。返回的labels可以后续用来分析退化指标在不同工况下的一致性。

4. RBFNN 回归建模:从 KPCA 得分到健康度的映射与训练细节

4.1 RBFNN 结构设计与隐含层神经元个数确定

RBFNN 的输入维度等于 KPCA 保留的主成分个数,通常 3 到 8 维。输出维度 1,即健康度。隐含层神经元个数是关键超参数,太少欠拟合,太多过拟合。

确定方法有三种。第一种,经验公式:神经元个数等于输入维度的 2 到 3 倍。第二种,递增法:从 5 个开始,每次加 5 个,看验证集误差,误差不再下降就停止。第三种,正交最小二乘:从大量候选中心里逐个选择对输出贡献最大的,自动确定个数。工程上常用第二种,简单可控。

隐含层中心向量的初始化用 KMeans 聚类,聚类数等于神经元个数,聚类中心作为初始中心。宽度参数有两种设法:统一宽度,取所有中心间平均距离的某个比例;或者每个神经元单独设宽度,取它到最近邻中心距离。统一宽度简单,但数据分布不均匀时局部逼近能力差。我一般用每个神经元单独设宽度,计算量稍大但效果更稳。

class RBFNN: def __init__(self, n_input, n_hidden, n_output=1): self.n_input = n_input self.n_hidden = n_hidden self.n_output = n_output self.centers = None self.widths = None self.weights = None def _rbf_activation(self, X, center, width): """高斯径向基函数""" dist = np.sum((X - center)**2, axis=1) return np.exp(-dist / (2 * width**2)) def fit(self, X, y): from sklearn.cluster import KMeans # 用 KMeans 初始化中心 kmeans = KMeans(n_clusters=self.n_hidden, random_state=42, n_init=10) kmeans.fit(X) self.centers = kmeans.cluster_centers_ # 计算每个中心的宽度:到最近邻中心距离 from scipy.spatial.distance import cdist dists = cdist(self.centers, self.centers) np.fill_diagonal(dists, np.inf) self.widths = np.min(dists, axis=1) # 构建隐含层输出矩阵 H = np.zeros((X.shape[0], self.n_hidden)) for i in range(self.n_hidden): H[:, i] = self._rbf_activation(X, self.centers[i], self.widths[i]) # 最小二乘求输出权重,加正则项防止病态 lam = 1e-3 self.weights = np.linalg.solve(H.T @ H + lam * np.eye(self.n_hidden), H.T @ y) return self def predict(self, X): H = np.zeros((X.shape[0], self.n_hidden)) for i in range(self.n_hidden): H[:, i] = self._rbf_activation(X, self.centers[i], self.widths[i]) return H @ self.weights

fit方法里,KMeans初始化中心,cdist算中心间距离,np.fill_diagonal把对角线设为无穷大,然后取每行最小值作为宽度。隐含层输出矩阵 H 的每一列是一个神经元的激活值。输出权重用带正则的最小二乘求解,lam=1e-3是正则系数,防止 H^T H 奇异。predict方法重复计算 H 然后加权求和。

参数说明:n_hidden建议从 10 开始试,如果验证集误差大就加到 20、30。lam在 1e-4 到 1e-2 之间调,数据噪声大时取大一点。宽度计算用最近邻距离,如果中心分布很不均匀,可以改用全局平均距离乘以 0.5 到 1.0 的系数。

4.2 训练集构建:健康度标签怎么定才不引入主观偏差

RBFNN 是监督学习,需要健康度标签。但实际数据里,健康度真值往往不知道,只能根据维护记录近似。常见做法有三种。

第一种,线性衰减假设:从全新到失效,健康度从 1 线性降到 0。简单但不符合实际,轴承退化通常前期慢、中期快、后期又慢,呈 S 形。

第二种,基于失效阈值的分段线性:根据振动烈度超过某个阈值的时刻作为失效点,之前按时间比例线性插值。比第一种好,但阈值选择主观。

第三种,无监督标签生成:用 KPCA 第一主成分的某种变换作为伪标签,再训练 RBFNN 去拟合。这种方法避免了人工标注,但伪标签的质量依赖 KPCA 效果。

我一般用第二种和第三种结合:先用 KPCA 第一主成分看趋势,确定大致失效点,再用分段线性生成标签,最后用 RBFNN 拟合。这样既利用了数据本身的结构,又保留了工程判断。

def generate_health_labels(rul, failure_threshold=0.7): """基于剩余寿命生成健康度标签,S 形映射""" rul_norm = rul / np.max(rul) # S 形函数:前期慢,中期快,后期慢 health = 1 / (1 + np.exp(-10 * (rul_norm - 0.5))) # 归一化到 0-1 health = (health - health.min()) / (health.max() - health.min()) return health

rul是剩余寿命,可以用时间或循环次数表示。failure_threshold这里没直接用,实际可以结合阈值做截断。S 形函数用exp实现,系数 10 控制陡峭程度,越大越接近阶跃。归一化保证输出在 0 到 1 之间。这个标签生成方式比线性更符合轴承退化规律,但系数需要根据具体数据调整。

4.3 训练过程监控:早停、学习率与过拟合判断

RBFNN 的输出权重用最小二乘直接求解,没有迭代,所以不存在学习率。但如果用梯度下降训练中心、宽度和权重,就需要学习率和早停。

早停策略:把训练集按 8:2 分训练和验证,每轮迭代后算验证集 MSE,如果连续 10 轮不下降就停止,取验证集误差最小时的参数。学习率初始设 0.01,如果误差震荡就减半,如果下降太慢就加倍。

过拟合判断:训练集 MSE 远小于验证集 MSE,比如差一个数量级,就是过拟合。解决方法是减少隐含层神经元个数、增大正则系数、增加训练样本。欠拟合则相反,两个误差都大且接近,需要增加神经元或降低正则。

def train_with_early_stopping(model, X_train, y_train, X_val, y_val, epochs=500, lr=0.01, patience=10): """梯度下降训练 RBFNN,带早停""" best_val_loss = np.inf best_params = None wait = 0 for epoch in range(epochs): # 前向传播 H = np.zeros((X_train.shape[0], model.n_hidden)) for i in range(model.n_hidden): H[:, i] = model._rbf_activation(X_train, model.centers[i], model.widths[i]) pred = H @ model.weights # 反向传播更新权重(简化版,只更新输出权重) error = pred - y_train grad = H.T @ error / X_train.shape[0] model.weights -= lr * grad # 验证 H_val = np.zeros((X_val.shape[0], model.n_hidden)) for i in range(model.n_hidden): H_val[:, i] = model._rbf_activation(X_val, model.centers[i], model.widths[i]) val_pred = H_val @ model.weights val_loss = np.mean((val_pred - y_val)**2) if val_loss < best_val_loss: best_val_loss = val_loss best_params = model.weights.copy() wait = 0 else: wait += 1 if wait >= patience: break model.weights = best_params return model, best_val_loss

这段代码只更新输出权重,中心固定为 KMeans 结果。lr=0.01是初始学习率,patience=10是早停耐心值。每次验证后如果损失下降就保存权重,否则等待计数加一,超过耐心值就停止。最后恢复最佳权重。注意这里没有更新中心和宽度,因为 KMeans 初始化已经给了不错的中心,微调它们容易过拟合。如果数据量很大,可以加中心微调,但学习率要更小。

5. 避坑与排查:变工况退化指标构建中的五个血泪教训

5.1 现象:退化指标曲线在工况切换点出现尖峰,原因:特征未做工况解耦,解决:加入工况特征或分组归一化

工况切换时,转速和载荷突变,振动信号的非平稳性急剧增加。如果特征提取窗口跨越切换点,时域和频域特征都会出现异常值。KPCA 虽然能非线性降维,但如果训练数据里切换点样本少,它学不到这种模式,RBFNN 会把异常值映射成健康度突变。

解决方法是:要么在特征提取时避开切换点,用切换后稳定运行的数据;要么把转速和载荷作为特征输入 KPCA,让降维过程自己解耦;要么按工况分组归一化。我一般先试第二种,不行再退回第三种。

5.2 现象:早期故障阶段退化指标平坦,原因:KPCA 主成分被工况方差主导,解决:按工况分层做 KPCA 或加权核矩阵

早期故障的特征变化很微弱,如果工况方差远大于退化方差,KPCA 的前几个主成分主要反映工况差异,退化信息被压到后面的主成分里。而 RBFNN 通常只用前几个主成分,导致早期故障被忽略。

解决方法是分层做 KPCA:先按工况分组,每组单独做 KPCA,提取组内主成分,再合并。或者给核矩阵加权,降低工况差异大的样本对的权重。加权核矩阵的实现复杂一些,但效果更平滑。

5.3 现象:RBFNN 训练误差很小但测试集退化指标震荡,原因:隐含层神经元过多导致过拟合,解决:减少神经元并增大正则

训练误差小说明 RBFNN 拟合能力强,但测试集震荡说明它把训练数据里的噪声也学进去了。变工况数据里,工况切换和传感器噪声都会产生异常样本,RBFNN 的局部响应特性让它对这些异常特别敏感。

解决方法是减少隐含层神经元个数,从 30 降到 15 甚至 10,同时增大正则系数lam,从 1e-3 加到 1e-2。另外,训练集里要剔除明显的异常样本,比如振动幅值超过正常范围 5 倍以上的切片。

5.4 现象:不同轴承的退化指标曲线形态差异大,原因:健康度标签生成方式不一致,解决:统一标签生成规则并做曲线对齐

同一批轴承,即使型号相同,个体差异也会导致退化速率不同。如果健康度标签按各自的时间比例生成,曲线形态会被人为拉齐,但实际退化模式差异被掩盖。如果按绝对时间生成,曲线形态又差异太大,没法比较。

解决方法是统一标签生成规则,比如都用 S 形函数,但参数根据各自失效时间调整。然后做曲线对齐,用动态时间规整或简单的线性缩放,把不同轴承的指标曲线映射到同一时间尺度上。这样既保留了个体差异,又便于横向比较。

5.5 现象:在线部署时指标计算延迟大,原因:KPCA 和 RBFNN 每次都要重新计算核矩阵,解决:预计算训练集核矩阵并缓存模型参数

在线部署时,每来一个新样本,KPCA 需要计算它和所有训练样本的核函数值,如果训练集有几千个样本,计算量不小。RBFNN 还要算隐含层激活,虽然比 KPCA 快,但累积起来也有延迟。

解决方法是预计算训练集的核矩阵和特征向量,在线时只需要算新样本和训练样本的核函数值,然后投影到已训练好的主成分空间。RBFNN 的中心、宽度和权重都缓存好,在线只做前向传播。这样单次计算延迟可以降到毫秒级。

6. 进阶技巧:用单调性约束和集成策略提升退化指标可靠性

6.1 在 RBFNN 损失函数里加单调性惩罚项

退化指标理论上应该单调,但实际数据里总有波动。可以在 RBFNN 的损失函数里加一项,惩罚指标随时间的非单调变化。具体做法是:对训练集里时间相邻的样本对,如果后一个样本的健康度大于前一个,就加惩罚。

def monotonicity_loss(y_pred, time_stamps, lambda_mono=0.1): """单调性惩罚:时间靠后的健康度不应大于时间靠前的""" sorted_idx = np.argsort(time_stamps) y_sorted = y_pred[sorted_idx] diff = y_sorted[1:] - y_sorted[:-1] # 只惩罚正差值(健康度上升) penalty = np.sum(np.maximum(diff, 0)**2) return lambda_mono * penalty

time_stamps是每个样本的时间标签,sorted_idx按时间排序,diff是相邻健康度差值。np.maximum(diff, 0)只保留正值,即健康度上升的部分,平方后求和。lambda_mono控制惩罚强度,太大会导致指标过于平滑,丢失早期故障信息,一般取 0.05 到 0.2。

6.2 多模型集成:不同核参数和不同神经元个数的投票

单个 RBFNN 的退化指标可能受初始化和超参数影响。用集成策略可以提升鲁棒性。具体做法:训练多个 RBFNN,每个用不同的 KPCA 带宽和不同的隐含层神经元个数,然后对它们的输出做加权平均。权重可以用验证集误差的倒数。

def ensemble_predict(models, X, weights=None): """多模型集成预测""" preds = np.array([m.predict(X) for m in models]) if weights is None: weights = np.ones(len(models)) / len(models) return np.average(preds, axis=0, weights=weights)

models是训练好的 RBFNN 列表,weights是权重向量。np.average按权重平均。权重可以按验证集 MSE 的倒数归一化得到。集成通常能把测试集指标的方差降低 20% 到 30%,代价是训练和推理时间成倍增加。

6.3 验证退化指标好坏的三个定量指标

不能只看曲线好不好看,要用定量指标。第一个,单调性指标:计算指标序列的 Spearman 相关系数,越接近 1 越好。第二个,鲁棒性指标:计算指标序列的平滑度,用一阶差分的标准差除以均值,越小越好。第三个,一致性指标:不同轴承的指标曲线做动态时间规整后的平均距离,越小越好。

from scipy.stats import spearmanr def evaluate_degradation_index(health, time_stamps): """评估退化指标质量""" # 单调性 mono, _ = spearmanr(time_stamps, health) # 鲁棒性 diff = np.diff(health) robustness = np.std(diff) / (np.mean(np.abs(diff)) + 1e-8) return {'monotonicity': mono, 'robustness': robustness}

spearmanr算秩相关系数,mono越接近 1 单调性越好。robustness用差分标准差除以差分均值绝对值,越小说明指标越平滑。这两个指标结合起来看,单调性高于 0.9 且鲁棒性低于 0.5 就算不错。

我自己的习惯是,每次调完参数,先把这三个指标算一遍,再画曲线看。有时候曲线看着漂亮,但单调性只有 0.7,说明波动还是大,上线后可能误报。宁可单调性 0.95 但曲线不那么光滑,也不要 0.7 的漂亮曲线。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询