小言_互联网的博客

基于MATLAB的深度自动编码器的无监督轴承异常检测

376人阅读  评论(0)

        基于MATLAB的DeepLearnToolbox工具箱(https://github.com/rasmusbergpalm/DeepLearnToolbox),本文在此基础上改成深度自动编码器用于无监督学习,即含有多个隐含层的自动编码器,其输入=输出,简称DAE。后续将其用于轴承故障的异常检测中。

1.相关原理

图1  DAE初始化示意图

       对于一个含n个隐含层的DAE,训练时分为预训练与微调两个阶段。预训练阶段时,相邻两层可以通过采用一个单隐层的自动编码器(AE)进行预训练,下一个AE的输入来自上一个AE的隐含层输出,即DAE的上一个隐含层的输出,相关理论可以看这个论文(https://kns.cnki.net/kcms/detail/detail.aspx?FileName=1020832508.nh&DbName=CMFD2021)。上面称之为逐层预训练,训练完毕之后,得到n个AE,利用这些AE的输入权重与输出权重替换DAE中的初始权重,初始化示意图如图1所示,接着在这个基础上利用bp算法进行微调,得到最终的DAE。

2.DAE用于MNIST手写字体重构


  
  1. %% DAE
  2. clc;clear;close all;format compact
  3. addpath(genpath('../utils/'))
  4. rng(0)
  5. %% 1.导入数据
  6. load mnist_uint8
  7. data= double(train_x);
  8. % method=@mapstd;
  9. method= @mapminmax;
  10. [xs,mapping]= method(data');
  11. train_x= xs';
  12. %% 无监督训练多个自动编码器 假设输入维度为 sizes=[n n1 n2],则训练两个ae 一个是n-n1-n 一个是n1-n2-n1
  13. sizes= [size(train_x,2) 200 100 50];
  14. learningRate1= 0.01;%各ae的学习率
  15. numepochs1= 10;%各ae的训练次数
  16. batchsize1= 256;%%各ae的batchsize
  17. activation_function= 'sigm';%各ae的激活函数
  18. dae = daesetup(sizes,activation_function,learningRate1);
  19. opts.numepochs = numepochs1;
  20. opts.batchsize = batchsize1;
  21. opts.show= 1;% 0就不显示训练过程
  22. dae = daetrain(dae, train_x, opts);
  23. %% 采用上面无监督预训练好的几个AE来堆栈DAE,构建深度自编码器
  24. learningRate2= 0.01;%sae的学习率
  25. numepochs2= 100;%dae的训练次数
  26. batchsize2= 256;%dae的batchsize
  27. nn = nnsetup([size(train_x,2) 200 100 50 100 200 size(train_x,2)]);%对称的结构,和ae一样,只不过dae是包含多个隐含层的ae
  28. nn.activation_function= 'sigm';
  29. nn.learningRate= learningRate2;
  30. nn= daeunfoldnn(nn,dae);%利用AE的参数初始化DAE
  31. opts.numepochs = numepochs2;
  32. opts.batchsize = batchsize2;
  33. nn.output = 'linear';
  34. opts.show= 1;% 0就不显示训练过程
  35. opts.plot = 1;%0就不显示loss曲线
  36. nn = nntrain(nn, train_x, train_x, opts);%输入=输出
  37. disp('训练完毕')
  38. %%
  39. re = nnpredict(nn, train_x);
  40. % 取几个重构的画图
  41. xs= method('reverse',re',mapping);
  42. pred_x= uint8(xs');
  43. pred_x= pred_x(1:25,:);
  44. n= 1;
  45. convaspred_x= uint8(zeros(28*5,28*5));
  46. for i = 1:5
  47. for j =1:5
  48. convaspred_x((i-1)*28+1: i*28,(j-1)*28+1:j*28)=reshape(pred_x(n,:),[28,28])';
  49. n= n+1;
  50. end
  51. end
  52. % 取对应的几个真实的画图
  53. xs= method('reverse',train_x',mapping);
  54. real_x= uint8(xs');
  55. real_x= real_x(1:25,:);
  56. n= 1;
  57. convasreal_x= uint8(zeros(28*5,28*5));
  58. for i = 1:5
  59. for j =1:5
  60. convasreal_x((i-1)*28+1: i*28,(j-1)*28+1:j*28)=reshape(real_x(n,:),[28,28])';
  61. n= n+1;
  62. end
  63. end
  64. figure
  65. imshow(convaspred_x)
  66. title('reconstruct')
  67. figure
  68. imshow(convasreal_x)
  69. title('original')

训练次数设置的100次,目测loss曲线还在继续下降,可以继续训练,这里就不做展示了。

3 基于DAE的轴承故障无监督异常检测

背景:自然界中含有大量正常样本 而少量异常样本,如果直接构建2分类模型,则容易造成数据不均衡,为此有专家提出无监督异常检测。作为异常检测的经典方法,DAE仅用正常样本进行训练,其输入=输出,以输入输出之间的重构误差最小化作为损失函数,学习的是正常样本的数据分布,当输入异常样本时,由于DAE没有用异常数据进行训练,其重构数据与本身将会产生较大的重构误差,基于此思想,DAE本广泛用于异常检测中。

3.1 数据集构建

       采用西储大学轴承故障诊断数据集,48K/0HP数据,共9类故障+一类正常。为模拟自然界中的【大量正常样本 而少量异常样本】这一情况。本文从正常数据中取1000个正常样本,标签记为1;从9类故障中每类取10个样本,共90个故障样本,记为2。


  
  1. %% 数据预处理(训练集 测试集划分)
  2. clc;clear;close all
  3. %% 加载原始数据
  4. load 0HP/48k_Drive_End_B007_0_122; a1=X122_DE_time'; %1
  5. load 0HP/48k_Drive_End_B014_0_189; a2=X189_DE_time'; %2
  6. load 0HP/48k_Drive_End_B021_0_226; a3=X226_DE_time'; %3
  7. load 0HP/48k_Drive_End_IR007_0_109; a4=X109_DE_time'; %4
  8. load 0HP/48k_Drive_End_IR014_0_174 ; a5=X173_DE_time';%5
  9. load 0HP/48k_Drive_End_IR021_0_213 ; a6=X213_DE_time';%6
  10. load 0HP/48k_Drive_End_OR007@6_0_135 ;a7=X135_DE_time';%7
  11. load 0HP/48k_Drive_End_OR014@6_0_201 ;a8=X201_DE_time';%8
  12. load 0HP/48k_Drive_End_OR021@6_0_238 ;a9=X238_DE_time';%9
  13. load 0HP/normal_0_97 ;a10=X097_DE_time';%10
  14. %% 自然界中含有大量正常样本 而少量异常样本,因此下面生成数据集的时候正常弄多点
  15. N1= 1000;
  16. N2= 10;
  17. L= 1024;% 异常状态(故障类数据)每种状态取N2个样本 每个样本长度为L,而正常状态取N1个样本 每个样本长度为L
  18. data= [];label=[];
  19. for i=1:10
  20. if i==1;ori_data=a1;end
  21. if i==2;ori_data=a2;end
  22. if i==3;ori_data=a3;end
  23. if i==4;ori_data=a4;end
  24. if i==5;ori_data=a5;end
  25. if i==6;ori_data=a6;end
  26. if i==7;ori_data=a7;end
  27. if i==8;ori_data=a8;end
  28. if i==9;ori_data=a9;end
  29. if i==10;ori_data=a10;end
  30. for j=1:N1
  31. if i<=9
  32. if j==N2+1
  33. break
  34. end
  35. end
  36. start_point= randi(length(ori_data)-L);%随机取一个起点
  37. end_point= start_point+L-1;
  38. data= [data ;ori_data(start_point:end_point)];
  39. label= [label;i];
  40. end
  41. end
  42. %% 异常检测标签,除了正常之外,其他的都是异常,正常用1来表示,异常用标签2表示
  43. % 无监督的异常检测方法,训练时仅用正常样本来进行训练
  44. data_normal= data(label==10,:);%注意上面,加载的时候正常是a10
  45. data_abnormal= data(label~=10,:);%不是10的都是异常
  46. % 正常样本取200个以及所有的异常数据作为测试集,用来测试网络性能
  47. index= randperm(size(data_normal,1));
  48. train_x= data_normal(index(1:end-200),:);
  49. test_x= [data_normal(index(end-200+1:end),:);
  50. data_abnormal];
  51. test_y= [ones(size(data_normal(index(end-200+1:end),:),1),1);2*ones(size(data_abnormal,1),1)];%测试集的标签,训练集全是正常的,这里就不做标签了
  52. save result/data_process train_x test_x test_y

3.2 DAE无监督异常检测,DAE结构为1024-10-8-5-8-10-1024(参数是随笔设的,并没有最优)


  
  1. %% DAE 深度自动编码器 无监督异常检测
  2. clc;clear;close all;format compact
  3. addpath(genpath( 'utils/'))
  4. rng( 0)
  5. %% 1.导入数据
  6. load result/data_process
  7. data=train_x;
  8. % method=@mapstd;
  9. method=@mapminmax;
  10. [xs,mapping]=method(data');
  11. train_x=xs';
  12. %% 无监督训练多个自动编码器 假设输入维度为 sizes=[n n1 n2],则训练两个ae 一个是n-n1-n 一个是n1-n2-n1
  13. sizes=[size(train_x, 2) 10 8 5];
  14. learningRate1= 0.01; %各ae的学习率
  15. numepochs1= 10; %各ae的训练次数
  16. batchsize1= 20; %%各ae的batchsize
  17. activation_function= 'sigm'; %各ae的激活函数
  18. dae = daesetup(sizes,activation_function,learningRate1);
  19. opts.numepochs = numepochs1;
  20. opts.batchsize = batchsize1;
  21. opts.show= 1; % 0就不显示训练过程
  22. dae = daetrain(dae, train_x, opts);
  23. %% 采用上面无监督预训练好的几个AE来堆栈DAE,构建深度自编码器
  24. learningRate2= 0.01; %sae的学习率
  25. numepochs2= 100; %dae的训练次数
  26. batchsize2= 20; %dae的batchsize
  27. nn = nnsetup([size(train_x, 2) 10 8 5 8 10 size(train_x, 2)]); %对称的结构,和ae一样,只不过dae是包含多个隐含层的ae
  28. nn.activation_function= 'sigm';
  29. nn.learningRate= learningRate2;
  30. nn=daeunfoldnn(nn,dae); %利用AE的参数初始化DAE
  31. opts.numepochs = numepochs2;
  32. opts.batchsize = batchsize2;
  33. nn.output = 'linear';
  34. opts.show= 1; % 0就不显示训练过程
  35. opts.plot = 1; %0就不显示loss曲线
  36. disp( 'Train DAE ')
  37. nn = nntrain(nn, train_x, train_x, opts); %输入=输出
  38. disp( '训练完毕')
  39. %% 预测 并计算指标
  40. labels0 = nnpredict(nn, train_x);
  41. % 计算每一个重构误差
  42. error0=sum((labels0-train_x).^ 2, 2);
  43. % 以均值+3方差为阈值
  44. threshold=mean(error0)+ 3*std(error0);
  45. %% 对测试集进行分类
  46. data=test_x;
  47. xs=method( 'apply',data',mapping);
  48. test_x=xs';
  49. labels = nnpredict(nn, test_x);
  50. % 计算每一个重构误差
  51. error=sum((labels-test_x).^ 2, 2);
  52. figure;plot(error);
  53. %% 计算检测的正确率
  54. pred=[];
  55. pred(error<=threshold, 1)= 1;
  56. pred(error>threshold, 1)= 2;
  57. real=test_y;
  58. MatrixClassTable=[real pred];
  59. [EA,OA,AA,Kappa]=ClassifiEvaluate(MatrixClassTable);
  60. disp( '----------结果-------------')
  61. disp( '各类精度');EA
  62. disp( '总体精度');OA
  63. disp( '平均精度');AA
  64. disp( 'kappa系数');Kappa
  65. figure
  66. plot(real, 'ro')
  67. hold on ;grid on
  68. plot(pred, 'b*')
  69. legend( '真实标签', '预测标签')
  70. xlabel( '测试集样本')
  71. ylabel( '标签')

loss curve:

测试集中每个样本的重构误差(头200个为正常数据,后面90个为异常数据):

以训练集样本的重构误差的均值+3倍方差为阈值,对测试集样本进行判别,大于该阈值的为异常,小于该预测的为正常,得出以下:

混淆矩阵
ConfuMatrix =
   199     1
     0    90
各类精度
EA =
    0.9950
    1.0000
总体精度
OA =
    0.9966
平均精度
AA =
    0.9975
kappa系数
Kappa =
    0.9920

可见DAE是有效的

完整代码:https://mianbaoduo.com/o/bread/YZmbkppw

 

 


转载:https://blog.csdn.net/qq_41043389/article/details/117191687
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场