信号特征提取+LSTM实现齿轮减速箱故障诊断-matlab代码

1. 数据描述

齿轮箱数据来自PHM2009年的数据挑战赛,官网:PHM2009数据挑战赛。所测试的齿轮包括一组直齿轮和斜齿轮,本例中用直齿轮的数据进行验证。实验设备照片如下。

信号特征提取+LSTM实现齿轮减速箱故障诊断-matlab代码_第1张图片
齿轮箱的输入侧和输出侧各安装一个加速度传感器,传感器参数:灵敏度:10mv/g,采样速率66.67KHz。所用的采集卡采集三个通道的数据,分别为:

  • 通道1:输入侧振动传感器数据
  • 通道2:输出侧振动传感器数据
  • 通道3:转速信号

采用人工注入故障的方式,共有8种故障类型,如下表。
信号特征提取+LSTM实现齿轮减速箱故障诊断-matlab代码_第2张图片
实验时工况为:转速分别设置为1800rpm, 2100rpm, 2400rpm, 2700rpm, 3000rpm,负载分别为低载和高载,交叉后共有10种工况,分别为
1800 rpm | 低载,1800rpm|高载,以此类推。
本例采用1800rpm|高载的实验数据建模及验证,采用通道二即输出侧振动传感器数据。每个工况下每种故障类型数据采集持续8秒,因此对于每种故障类型,每个通道总共得到66.7KHz×8秒=533307个数据点。每种故障类型的数据为533307×3通道的矩阵,数据在matlab打开如下。
信号特征提取+LSTM实现齿轮减速箱故障诊断-matlab代码_第3张图片
把通道2的数据plot出来,如下所示。
信号特征提取+LSTM实现齿轮减速箱故障诊断-matlab代码_第4张图片

2. 代码详解

代码总共包括两个.m文件

  • read_data_1800_High.m
  • main_1800_High.m
    其中第一个用于读取并划分原始数据
    第二个用于完成划分训练集测试集,特征提取+分类等工作

2.1 read_data_1800_High

// 本函数Input为
// interval - 数据划分长度,默认为6400,即每6400个数据点划为一个样本
// ind_column - 通道,默认为2,即选取第二个通道
// Output为
// label1 label2, ..., label8,分别为划分好的8种故障类型的样本
% 
function [label1 label2 label3 label4 label5 label6 label7 label8]= read_data_1800_High( interval, ind_column )
if nargin <2
    ind_column=2; //如果传递的实参小于2个,默认ind_column为2
end 

if nargin <1
    interval=6400; //默认interval=6400
end

file_rul='E:\Datasets\PHM data challenge\2009 PHM Society Conference Data Challenge-gear box\spur_30hz_High\';
// 以下为获取file_rul路径下.mat格式的所有文件
file_folder=fullfile(file_rul);
dir_output=dir(fullfile(file_folder,'*.mat'));
file_name={dir_output.name}';
num_file=max(size(file_name)); //num_file为文件数,本例中num_file=8,8个文件,分别存储齿轮箱的8种故障数据

for i=1:num_file
    file=[file_rul,file_name{i}];
    load(file);
    [filepath, name, ext]=fileparts(file);
    raw=eval(name);
    
	// 每6400个点划分为一个样本
    n=1;
    left_index=1+(n-1)*interval;
    right_index=n*interval;
    while right_index<=size(raw,1)
         temp=raw(left_index : right_index, ind_column);
         // eval函数构造label1, label2,...等变量名
         eval(['label' num2str(i) '(:,n)=temp;']); 
         n=n+1;
         left_index=1+(n-1)*interval;
         right_index=n*interval;
    end
end
end

2.2 main_1800_High

// 读取数据,label1为一个6400*83的数组,83为每种故障类型所得到的样本数
[label1, label2, label3, label4, label5, label6, label7, label8]=read_data_1800_High();
num_categories=8;
// 由于matlab中LSTM建模需要,用num2cell函数将label1转为cell型,label_x_cell为一个1×83的cell型数组,每个cell存储6400个数据点
label1_x_cell=num2cell(label1,1);
label2_x_cell=num2cell(label2,1);
label3_x_cell=num2cell(label3,1);
label4_x_cell=num2cell(label4,1);
label5_x_cell=num2cell(label5,1);
label6_x_cell=num2cell(label6,1);
label7_x_cell=num2cell(label7,1);
label8_x_cell=num2cell(label8,1);

num_1=length(label1_x_cell);
num_2=length(label2_x_cell);
num_3=length(label3_x_cell);
num_4=length(label4_x_cell);
num_5=length(label5_x_cell);
num_6=length(label6_x_cell);
num_7=length(label7_x_cell);
num_8=length(label8_x_cell);
// 创建用于存储每种故障类型的标签的数据结构,由于matlab中lstm建模需要,也需要cell型数据。例如,label1_y为一个83×1的cell型数组,目前其值为空
label1_y=cell(num_1,1);
label2_y=cell(num_2,1);
label3_y=cell(num_3,1);
label4_y=cell(num_4,1);
label5_y=cell(num_5,1);
label6_y=cell(num_6,1);
label7_y=cell(num_7,1);
label8_y=cell(num_8,1);
// 创建故障类型的标签,用1,2,3,...,8表示8种故障标签,给对应标签赋值。
for i=1:num_1; label1_y{i}='1'; end
for i=1:num_2; label2_y{i}='2'; end
for i=1:num_3; label3_y{i}='3'; end
for i=1:num_4; label4_y{i}='4'; end
for i=1:num_5; label5_y{i}='5'; end
for i=1:num_6; label6_y{i}='6'; end
for i=1:num_7; label7_y{i}='7'; end
for i=1:num_8; label8_y{i}='8'; end
// 用dividerand函数将每种故障类型的数据随机划分为4:1的比例,分别用作训练和测试
[trainInd_label1,~,testInd_label1]=dividerand(num_1,0.8,0,0.2);
[trainInd_label2,~,testInd_label2]=dividerand(num_2,0.8,0,0.2);
[trainInd_label3,~,testInd_label3]=dividerand(num_3,0.8,0,0.2);
[trainInd_label4,~,testInd_label4]=dividerand(num_4,0.8,0,0.2);
[trainInd_label5,~,testInd_label5]=dividerand(num_5,0.8,0,0.2);
[trainInd_label6,~,testInd_label6]=dividerand(num_6,0.8,0,0.2);
[trainInd_label7,~,testInd_label7]=dividerand(num_7,0.8,0,0.2);
[trainInd_label8,~,testInd_label8]=dividerand(num_8,0.8,0,0.2);

// 构建每种故障类型的训练数据
xTrain_label1=label1_x_cell(trainInd_label1);
yTrain_label1=label1_y(trainInd_label1);

xTrain_label2=label2_x_cell(trainInd_label2);
yTrain_label2=label2_y(trainInd_label2);

xTrain_label3=label3_x_cell(trainInd_label3);
yTrain_label3=label3_y(trainInd_label3);

xTrain_label4=label4_x_cell(trainInd_label4);
yTrain_label4=label4_y(trainInd_label4);

xTrain_label5=label5_x_cell(trainInd_label5);
yTrain_label5=label5_y(trainInd_label5);

xTrain_label6=label6_x_cell(trainInd_label6);
yTrain_label6=label6_y(trainInd_label6);

xTrain_label7=label7_x_cell(trainInd_label7);
yTrain_label7=label7_y(trainInd_label7);

xTrain_label8=label8_x_cell(trainInd_label8);
yTrain_label8=label8_y(trainInd_label8);

// 构建每种故障类型的测试数据
xTest_label1=label1_x_cell(testInd_label1);
yTest_label1=label1_y(testInd_label1);

xTest_label2=label2_x_cell(testInd_label2);
yTest_label2=label2_y(testInd_label2);

xTest_label3=label3_x_cell(testInd_label3);
yTest_label3=label3_y(testInd_label3);

xTest_label4=label4_x_cell(testInd_label4);
yTest_label4=label4_y(testInd_label4);

xTest_label5=label5_x_cell(testInd_label5);
yTest_label5=label5_y(testInd_label5);

xTest_label6=label6_x_cell(testInd_label6);
yTest_label6=label6_y(testInd_label6);

xTest_label7=label7_x_cell(testInd_label7);
yTest_label7=label7_y(testInd_label7);

xTest_label8=label8_x_cell(testInd_label8);
yTest_label8=label8_y(testInd_label8);

// 将每种故障类型的数据整合,构建完整的训练集和测试集
xTrain=[xTrain_label1 xTrain_label2 xTrain_label3 xTrain_label4 xTrain_label5 xTrain_label6 xTrain_label7 xTrain_label8];
yTrain=[yTrain_label1; yTrain_label2; yTrain_label3; yTrain_label4; yTrain_label5; yTrain_label6; yTrain_label7; yTrain_label8];
num_train=size(xTrain,2);

xTest=[xTest_label1  xTest_label2  xTest_label3 xTest_label4 xTest_label5 xTest_label6 xTest_label7 xTest_label8];
yTest=[yTest_label1; yTest_label2; yTest_label3; yTest_label4; yTest_label5; yTest_label6; yTest_label7; yTest_label8];
num_test=size(xTest,2);

//================================================================================
//以下分别对每个样本,提取三种特征:1.瞬时频率,2.瞬时谱熵,3.小波包能量,
//上述三种特征后面会被送入分类器中进行分类,实验结果表明,将小波包能量作为特征,
//能够取得最高的分类精度

// 提取瞬时频率:用matlab的pspectrum对每个样本进行谱分解,再用instfreq函数计算瞬时频率
FreqResolu=25;
TimeResolu=0.12;
// the output of pspectrum 'p' contains an estimate of the short-term, time-localized power spectrum of x. 
// In this case, p is of size Nf × Nt, where Nf is the length of f and Nt is the length of t.
 [p,f,t]=cellfun(@(x) pspectrum(x,fs,'TimeResolution',TimeResolu,'spectrogram'),xTrain,'UniformOutput', false);
instfreqTrain=cellfun(@(x,y,z) instfreq(x,y,z)', p,f,t,'UniformOutput',false);
[p,f,t]=cellfun(@(x) pspectrum(x,fs,'TimeResolution',TimeResolu,'spectrogram'),xTest,'UniformOutput', false);
instfreqTest=cellfun(@(x,y,z) instfreq(x,y,z)', p,f,t,'UniformOutput',false);

// 提取瞬时谱熵:用matlab的pspectrum对每个样本进行谱分解,再用pentropy函数计算瞬时频率
[p,f,t]=cellfun(@(x) pspectrum(x,fs,'TimeResolution',TimeResolu,'spectrogram'),xTrain,'UniformOutput', false);
pentropyTrain=cellfun(@(x,y,z) pentropy(x,y,z)', p,f,t,'UniformOutput',false);
[p,f,t]=cellfun(@(x) pspectrum(x,fs,'TimeResolution',TimeResolu,'spectrogram'),xTest,'UniformOutput', false);
pentropyTest=cellfun(@(x,y,z) pentropy(x,y,z)', p,f,t,'UniformOutput',false);

// 提取小波包能量
// num_level=5表示进行小波包五层分解,共获得2^5=32个值组成的特征向量。
num_level=5; 
index=0:1:2^num_level-1;
// wpdec为小波包分解函数
treeTrain=cellfun(@(x) wpdec(x,num_level,'dmey'), xTrain, 'UniformOutput', false);
treeTest=cellfun(@(x) wpdec(x,num_level,'dmey'), xTest, 'UniformOutput', false);
for i=1:num_train
    for j=1:length(index)
    	// wprcoef为小波系数重构函数
        reconstr_coef=wprcoef(treeTrain{i},[num_level,index(j)]);
        // 计算能量
        energy(j)=sum(reconstr_coef.^2);
    end
    energyTrain_doule(i,:)=energy;
end

energyTrain=num2cell(energyTrain_doule,2);
energyTrain=energyTrain';

for i=1:num_test
    for j=1:length(index)
        reconstr_coef=wprcoef(treeTest{i},[num_level,index(j)]);
        energy(j)=sum(reconstr_coef.^2);
    end
 energyTest_double(i,:)=energy;
end

energyTest=num2cell(energyTest_double,2);
energyTest=energyTest';

// ===============组装用于送入分类器的特征序列====================
// 下面的语句仅用了小波包能量作为输入特征
xTrainFeature=cellfun(@(x)[x], energyTrain', 'UniformOutput',false);
xTestFeature=cellfun(@(x)[x], energyTest', 'UniformOutput',false);
// 如果想用 瞬时谱熵和小波包能量三种特征作为输入,如下
// xTrainFeature=cellfun(@(x,y,z)[x;y;z],energyTrain',instfreqTrain', pentropyTrain', 'UniformOutput',false);
// xTestFeature=cellfun(@(x,y,z)[x;y;z], energyTest',instfreqTest',pentropyTest', 'UniformOutput',false);

// ============================数据标准化================================
XV=[xTrainFeature{:}];
mu=mean(XV,2);
sg=std(XV,[],2);

xTrainFeatureSD=xTrainFeature;
xTrainFeatureSD=cellfun(@(x)(x-mu)./sg, xTrainFeatureSD,'UniformOutput',false);

xTestFeatureSD=xTestFeature;
xTestFeatureSD=cellfun(@(x)(x-mu)./sg,xTestFeatureSD,'UniformOutput',false);

// =========================设计LSTM网络=================================
yTrain_categorical=categorical(yTrain);
numClasses=numel(categories(yTrain_categorical));
yTest_categorical=categorical(yTest);
sequenceInput=size(xTrainFeatureSD{1},1); // 如果选了3种特征作为数据,这里改为"3"

// 创建用于sequence-to-label分类的LSTM步骤如下:
// 1. 创建sequence input layer
// 2. 创建若干个LSTM layer
// 3. 创建一个fully connected layer
// 4. 创建一个softmax layer
// 5. 创建一个classification outputlayer
// 注意将sequence input layer的size设置为所包含的特征类别数,本例中,1或2或3,取决于你用了几种特征。fully connected layer的参数为分类数,本例中为8.
layers = [ ...
    sequenceInputLayer(sequenceInput)
     lstmLayer(256,'OutputMode','last')
    fullyConnectedLayer(numClasses)
    softmaxLayer
    classificationLayer
    ];

maxEpochs=600;
miniBatchSize=32;
// 如果不想展示训练过程,
options = trainingOptions('adam', ...
    'ExecutionEnvironment', 'gpu',...
     'SequenceLength', 'longest',...
    'MaxEpochs',maxEpochs, ...
    'MiniBatchSize', miniBatchSize, ...
    'InitialLearnRate', 0.001, ...
    'GradientThreshold', 1, ...
    'plots','training-progress', ... 
    'Verbose',true);

// ======================训练网络=========================
net2 = trainNetwork(xTrainFeatureSD,yTrain_categorical,layers,options);
// ======================测试网路==========================
testPred2 = classify(net2,xTestFeatureSD);
// 打印混淆矩阵
plotconfusion(yTest_categorical',testPred2','Testing Accuracy')

训练过程截图,如果不想展示该图,将options中的 'plots','training-progress', ... 改为'plots','none', ...


混淆矩阵截图,可以看到,精度为94%。
信号特征提取+LSTM实现齿轮减速箱故障诊断-matlab代码_第5张图片

将上述两个文件放在同一个workspace下,运行main_1800_High即可

3 展望

在后续的研究中,我们发现在keras深度学习框架下用CNN做此类问题更简便,不需要进行特征提取,教程后续补上。

你可能感兴趣的:(matlab,lstm,自动驾驶)