Matlab 预防性维修,MATLAB进行预测性维护(官网例程)-基于相似性进行剩余有效寿命预测 – MATLAB中文论坛...

本帖最后由 zwlbeyond 于 2020-5-19 14:30 编辑

数据集使用了PHM08挑战数据集,是涡轮风扇发动机退化模拟数据集。

训练数据包含218个运行到故障模拟。这组测量被称为“集合”。

每个集合成员都是一个包含26列的表。 这些列包含有关机器ID,时间戳,3个操作条件和21个传感器测量值的数据。

PHM-2008数据是NASA在2008年公开的飞机发动机全寿命性能仿真数据,仿真平台为大型飞机涡扇发动机仿真软件C-MAPSS,模拟的是一个90000磅推力级的发动机模型。

MATLAB 进行预测性维护  2020.05.09-------夜莺与玫瑰1、案例描述(导入数据)

%%Data import

t = readtable('train.txt');

t(:,end) = []; %Discard last column of loaded data as all are empty ''

% Add variable names to the table

VarNames = {...

'id', 'time', 'op_setting_1', 'op_setting_2', 'op_setting_3', ...

'sensor_1', 'sensor_2', 'sensor_3', 'sensor_4', 'sensor_5', ...

'sensor_6', 'sensor_7', 'sensor_8', 'sensor_9', 'sensor_10', ...

'sensor_11', 'sensor_12', 'sensor_13', 'sensor_14', 'sensor_15', ...

'sensor_16', 'sensor_17', 'sensor_18', 'sensor_19', 'sensor_20', ...

'sensor_21'};

t.Properties.VariableNames = VarNames;

IDs = t{:,1};   %提取出ID,第一列数据

nID = unique(IDs); %不同编号,代表不同的发动机

degradationData = cell(numel(nID),1);  %退化数据初始化

%将每一组发动机下的数据提取出来

for ct=1:numel(nID)

idx = IDs == nID(ct);

degradationData{ct} = t(idx,:);

end

degradationData(1:5)

head(degradationData{2})   %返回表的前8行复制代码

退化数据都被加载到了degradationData变量中,从图1中可以看出,每组退化数据都包含26列数据,再从图2中看出,26列数据中包括了机器ID,时间戳,3个操作条件和21个传感器测量值的数据。

2、划分训练数据集和验证数据集通过查看工作区,发现退化数据degradationData总共有218组,通常我们需要将这些数据分为训练数据集和验证数据集。为了更充分地使用所有数据,我们将所有数据平分为k份,然后每一份都做一次验证数据集(其余数据做训练集),这样我们就一共有了k对训练-验证数据,这种方法叫做k折交叉验证。代码实现方法如下:

rng('default')  % 生成随机数,使用"default"是为了使用特定的随机数,这样大家的运行结果就都一样了

numEnsemble = length(degradationData);

numFold = 5;   %交叉验证分区数,即k的值

cv = cvpartition(numEnsemble, 'KFold', numFold);  %为数据创建交叉验证分区,K-折交叉验证

trainData = degradationData(training(cv, 1));  %读取第1组训练数据集

validationData = degradationData(test(cv, 1)); %读取第1组验证数据集

nsample = 10;

figure

helperPlotEnsemble(trainData, timeVariable, ...                %专用函数,绘制conditionVariables(1:2)和dataVariables(1:2)的图像

[conditionVariables(1:2) dataVariables(1:2)], nsample)     %即"op_setting_1","op_setting_2","sensor_1"和"sensor_2"复制代码

3、工作状态聚类从上图中看不出数据的退化趋势,下面我们将对退化特征进行提取。

trainDataUnwrap = vertcat(trainData{:});  %垂直串联数组,即将175数组退化数据拼接成1组

opConditionUnwrap = trainDataUnwrap(:, cellstr(conditionVariables));  %提取串联后的大数组的"op_setting_1","op_setting_2","op_setting_3"这三个一位数组

figure

helperPlotClusters(opConditionUnwrap)  %绘制三维散点图,查看聚类情况复制代码

上边这段代码是将训练数据(共175组)串联成了一个大数组,然后分别以"op_setting_1", "op_setting_2", "op_setting_3"为x,y,z坐标绘制散点图。结果如上图:串联后的数据有3万多组,但是图上只有6个点,这是因为聚在一起的点相距太近,没有聚在一起的数据又离得太远,最终视觉效果就变成了只有6个点。如果不断地放大某个位置的点,就能看到聚在一起的密密麻麻的点了。这么分明的聚类结果是十分理想的。这说明"op_setting_1", "op_setting_2", "op_setting_3"的组合大致只有六组,所以后边我们将这六种组合对应的传感器的值分开分析。

下面使用k均值聚类的方法计算对聚类结果进行定量分析,并找到各自的聚类质心:

opts = statset('Display', 'final');  %显示最终迭代结果
[clusterIndex, centers] = kmeans(table2array(opConditionUnwrap), 6, ...  %调用kmeans函数进行k均值聚类
    'Distance', 'sqeuclidean', 'Replicates', 5, 'Options', opts);        %设置共分为6组,距离度量为欧氏距离,不同初始条件下重复计算5次
figure
helperPlotClusters(opConditionUnwrap, clusterIndex, centers)
复制代码

4、数据标准化①计算各聚类下各传感器的均值,得到大小为6*21的数组(6为聚类数,21为传感器数)。②计算各聚类下各传感器的标准差,得到大小为6*21的数组(6为聚类数,21为传感器数)。如果某组数据的标准差为0,则将该组数据统一设置为0,因为几乎恒定的传感器测量值对于剩余使用寿命估计没有用处。③分别计算该条目数据至6个聚类中心的距离,并找到最近的聚类中心。④对于每个传感器的测量值,减去“该聚类下该传感器”的平均值,再除以“该聚类下该传感器”的标准差。这种“减去均值再除以标准差”的方法叫做Z-score标准化,非常常用。经过这种处理后的数据均值为0,且符合正态分布。

centerstats = struct('Mean', table(), 'SD', table()); %初始化结构体,用于存储各传感器的均值和标准差

for v = dataVariables

centerstats.Mean.(char(v)) = splitapply(@mean, trainDataUnwrap.(char(v)), clusterIndex); %将个sensor数据划分到其所在的聚类,并求该聚类组的该传感器均值

centerstats.SD.(char(v))   = splitapply(@std,  trainDataUnwrap.(char(v)), clusterIndex); %将个sensor数据划分到其所在的聚类,并求该聚类组的该传感器标准差

end

centerstats.Mean

centerstats.SD

trainDataNormalized = cellfun(@(data) regimeNormalization(data, centers, centerstats), ... %进行数据规范化

trainData, 'UniformOutput', false);

figure

helperPlotEnsemble(trainDataNormalized, timeVariable, dataVariables(1:4), nsample)  %规范化后的退化数据可视化复制代码

为什么标准化处理后退化趋势就显现出来了呢?是因为之前6种运行状态下的传感器数据混杂在一起,互相干扰,或者说趋势性被不同运行状态引起的干扰淹没了;在我们将6种状态下的传感器区分开之后,分别进行标准化,就剔除掉了运行状态所造成的差异性,使得传感器数据在不同时间上可对比。

5、趋势分析从上图中可以看到,某些传感器退化趋势明显,某些不太明显。这里我们选择最具趋势性的传感器测量值,构建健康指数进行预测。对每个传感器测量值构建线性退化模型,并对信号的斜率的绝对值进行排序。最终选出8组退化趋势的传感器,其中四组的数据如下:

numSensors = length(dataVariables);

signalSlope = zeros(numSensors, 1);

warn = warning('off');

for ct = 1:numSensors

tmp = cellfun(@(tbl) tbl(:, cellstr(dataVariables(ct))), trainDataNormalized, 'UniformOutput', false);

mdl = linearDegradationModel(); % create model

fit(mdl, tmp); % train mode

signalSlope(ct) = mdl.Theta;

end

warning(warn);

[~, idx] = sort(abs(signalSlope), 'descend');

sensorTrended = sort(idx(1:8))

figure

helperPlotEnsemble(trainDataNormalized, timeVariable, dataVariables(sensorTrended(3:6)), nsample)复制代码

需要注意的是,有些传感器数据呈上升趋势,有些呈下降趋势,而我们是以斜率的绝对值为选取标准的。

6、构建健康指标需要将选出的这些传感器数据融合到一个健康指标中,并通过该指标训练基于相似性的模型。假设所有的故障数据都是从健康状况开始的,开始时的健康状况设为1,失效时的健康状况为0。那么所有数据对应的健康状况都是从1下降至0。其中10组数据的健康指标的变化趋势如下:

for j=1:numel(trainDataNormalized)

data = trainDataNormalized{j};

rul = max(data.time)-data.time;

data.health_condition = rul / max(rul);

trainDataNormalized{j} = data;

end

figure

helperPlotEnsemble(trainDataNormalized, timeVariable, "health_condition", nsample)复制代码

下面开始构建健康状况的线性回归模型:①我们之前选定了8个退化规律最明显的传感器,建立这8个传感器与健康状况的线性模型。②y=ax+b这种线性回归模型大家都知道吧,在这个例子里,y就是图8中的健康指标,x就是8个传感器的数值,而a和b则是我们要估计的回归参数。与平时常用的不同的是,这里a是个1*8的矩阵,x也是个8*n的矩阵(n为每个传感器采集到的数据长度)。需要估计的就是a1~a8和b这九个参数。可以通过下述代码实现:

trainDataNormalizedUnwrap = vertcat(trainDataNormalized{:});  %将标准化后的数据垂直串联为一个大数组复制代码重构后的健康指标如上所示

7、使用同样的方法处理验证集数据将验证数据集数据进行标准化,并同样带入上一节中得到的线性模型中。此时的健康指标为:

validationDataNormalized = cellfun(@(data) regimeNormalization(data, centers, centerstats), ...

validationData, 'UniformOutput', false);

validationDataFused = cellfun(@(data) degradationSensorFusion(data, sensorToFuse, weights), ...

validationDataNormalized, 'UniformOutput', false);

figure

helperPlotEnsemble(validationDataFused, [], 1, nsample)

xlabel('Time')

ylabel('Health Indicator')

title('Validation Data')复制代码

8、建立相似性RUL模型使用训练数据建立一个基于残差的相似性RUL模型。在此设置中,模型试用二次多项式拟合每个融合数据。数据与数据之间的距离通过残差的1范数计算其中机器的健康指标是使用机器中识别的二阶多项式模型估算的机器的健康指标。相似度分数通过以下公式计算给定验证数据集中的几个集合成员,模型将找到训练数据集中最近的50个集合成员,拟合基于50个集合成员的概率分布,并使用分布中的中值作为RUL的估计。

mdl = residualSimilarityModel(...

'Method', 'poly2',...      %使用poly2方法

'Distance', 'absolute',... %绝对值距离

'NumNearestNeighbors', 50,...  %集合成员为50

'Standardize', 1);

fit(mdl, trainDataFused);    %拟合模型复制代码

9、性能评估为了评估相似性rul模型,使用50%、70%和90%的样本验证数据来预测其RUL。

breakpoint = [0.5, 0.7, 0.9];

validationDataTmp = validationDataFused{3}; % use one validation data for illustration

bpidx = 1;   %使用50%的区间

validationDataTmp50 = validationDataTmp(1:ceil(end*breakpoint(bpidx)),:);  % 50%区间内的健康指标

trueRUL = length(validationDataTmp) - length(validationDataTmp50);         % 真实剩余寿命

[estRUL, ciRUL, pdfRUL] = predictRUL(mdl, validationDataTmp50);            % 得到估计的剩余寿命、置信区间和RUL概率密度的估计值复制代码

(1)50%截段的数据验证随便选择一组验证数据,并截取其前50%的数据,绘制下图:红线为该组被截断50%的数据,蓝线为验证数据集其他组数据的退化曲线。选定的截断数据与其周围数据,将估计的RUL、真实RUL和估计RUL的概率分布进行比较。

figure

compare(mdl, validationDataTmp50);

figure

helperPlotRULDistribution(trueRUL, estRUL, pdfRUL, ciRUL)复制代码(2)70%截段的数据验证

bpidx = 2;

validationDataTmp70 = validationDataTmp(1:ceil(end*breakpoint(bpidx)), :);

trueRUL = length(validationDataTmp) - length(validationDataTmp70);

[estRUL,ciRUL,pdfRUL] = predictRUL(mdl, validationDataTmp70);

figure

compare(mdl, validationDataTmp70);

figure

helperPlotRULDistribution(trueRUL, estRUL, pdfRUL, ciRUL)复制代码

(3)90%截段的数据验证

bpidx = 3;

validationDataTmp90 = validationDataTmp(1:ceil(end*breakpoint(bpidx)), :);

trueRUL = length(validationDataTmp) - length(validationDataTmp90);

[estRUL,ciRUL,pdfRUL] = predictRUL(mdl, validationDataTmp90);

figure

compare(mdl, validationDataTmp90);

figure

helperPlotRULDistribution(trueRUL, estRUL, pdfRUL, ciRUL)复制代码

通过50%、70%、90%估计寿命的结果对比,发现随着验证数据比例的增加,寿命的估计值也会更准确(当然了)。

10、整体评价第9步中是对某一组退化数据进行的预测,现在对整个验证数据集重复相同的评估程序,并计算每个断点的估计RUL和真实RUL之间的误差。

numValidation = length(validationDataFused);复制代码

(1)绘制每个断点的误差直方图及其分布:随着观测的数据越来越多(从50%~90%),误差越来越集中于0附近。

figure

ax(1) = subplot(3,1,1);

hold on

histogram(error(:, 1), 'BinWidth', 5, 'Normalization', 'pdf')

plot(x50, pdf50)

hold off

xlabel('Prediction Error')

title('RUL Prediction Error using first 50% of each validation ensemble member')

ax(2) = subplot(3,1,2);

hold on

histogram(error(:, 2), 'BinWidth', 5, 'Normalization', 'pdf')

plot(x70, pdf70)

hold off

xlabel('Prediction Error')

title('RUL Prediction Error using first 70% of each validation ensemble member')

ax(3) = subplot(3,1,3);

hold on

histogram(error(:, 3), 'BinWidth', 5, 'Normalization', 'pdf')

plot(x90, pdf90)

hold off

xlabel('Prediction Error')

title('RUL Prediction Error using first 90% of each validation ensemble member')

linkaxes(ax)复制代码

(2)绘制箱型图箱型图是一种用作显示一组数据分散情况资料的统计图。它主要用于反映原始数据分布的特征,还可以进行多组数据分布特征的比较。

figure复制代码

(3)绘制误差棒图误差棒是数据可变性的图形表示,并用于图表以指示所报告的测量中的误差或不确定性。如下图中每个竖线代表了预测的平均误差以及一个标准差的范围。可以看出,随着观测的数据越来越多,预测误差均值越来越小,误差范围也越来越小。

errorMean = mean(error)复制代码

总结

总的来说,通过50%、70%、90%估计寿命的结果对比,发现随着验证数据比例的增加,寿命的估计值也会更准确。这个方法的关键之处在于,需要有比较大量的失效数据,经过数据聚类→数据标准化→选取退化趋势最明显的传感器→构建线性退化模型→建立相似性RUL模型→进行预测 这些步骤可以实现预测。这个大量失效数据的条件在某些产品中是不容易得到的,但是如果有这些数据,预测结果还是比较可靠的。

你可能感兴趣的:(Matlab,预防性维修)