当前位置:   article > 正文

MATLAB实现随机森林(RF)回归与自变量影响程度分析_随机森林matlab

随机森林matlab

本文介绍基于MATLAB,利用随机森林RF)算法实现回归预测,以及自变量重要性排序的操作。

目录

  本文分为两部分,首先是对代码进行分段、详细讲解,方便大家理解;随后是完整代码,方便大家自行尝试。另外,关于基于MATLAB的神经网络(ANN)代码与详细解释,我们将在后期博客中介绍。

1 分解代码

1.1 最优叶子节点数与树数确定

  首先,我们需要对RF对应的叶子节点数与树的数量加以择优选取。

  1. %% Number of Leaves and Trees Optimization
  2. for RFOptimizationNum=1:5
  3. RFLeaf=[5,10,20,50,100,200,500];
  4. col='rgbcmyk';
  5. figure('Name','RF Leaves and Trees');
  6. for i=1:length(RFLeaf)
  7. RFModel=TreeBagger(2000,Input,Output,'Method','R','OOBPrediction','On','MinLeafSize',RFLeaf(i));
  8. plot(oobError(RFModel),col(i));
  9. hold on
  10. end
  11. xlabel('Number of Grown Trees');
  12. ylabel('Mean Squared Error') ;
  13. LeafTreelgd=legend({'5' '10' '20' '50' '100' '200' '500'},'Location','NorthEast');
  14. title(LeafTreelgd,'Number of Leaves');
  15. hold off;
  16. disp(RFOptimizationNum);
  17. end

  其中,RFOptimizationNum是为了多次循环,防止最优结果受到随机干扰;大家如果不需要,可以将这句话删除。

  RFLeaf定义初始的叶子节点个数,我这里设置了从5500,也就是从5500这个范围内找到最优叶子节点个数。

  InputOutput分别是我的输入(自变量)与输出(因变量),大家自己设置即可。

  运行后得到下图。

  首先,我们看到MSE最低的线是红色的,也就是5左右的叶子节点数比较合适;再看各个线段大概到100左右就不再下降,那么树的个数就是100比较合适。

1.2 循环准备

  由于机器学习往往需要多次执行,我们就在此先定义循环。

  1. %% Cycle Preparation
  2. RFScheduleBar=waitbar(0,'Random Forest is Solving...');
  3. RFRMSEMatrix=[];
  4. RFrAllMatrix=[];
  5. RFRunNumSet=10;
  6. for RFCycleRun=1:RFRunNumSet

  其中,RFRMSEMatrixRFrAllMatrix分别用来存放每一次运行的RMSEr结果RFRunNumSet是循环次数,也就是RF运行的次数。

1.3 数据划分

  接下来,我们需要将数据划分为训练集与测试集。这里要注意:RF其实一般并不需要划分训练集与测试集,因为其可以采用袋外误差(Out of Bag Error,OOB Error)来衡量自身的性能。但是因为我是做了多种机器学习方法的对比,需要固定训练集与测试集,因此就还进行了数据划分的步骤。

  1. %% Training Set and Test Set Division
  2. RandomNumber=(randperm(length(Output),floor(length(Output)*0.2)))';
  3. TrainYield=Output;
  4. TestYield=zeros(length(RandomNumber),1);
  5. TrainVARI=Input;
  6. TestVARI=zeros(length(RandomNumber),size(TrainVARI,2));
  7. for i=1:length(RandomNumber)
  8. m=RandomNumber(i,1);
  9. TestYield(i,1)=TrainYield(m,1);
  10. TestVARI(i,:)=TrainVARI(m,:);
  11. TrainYield(m,1)=0;
  12. TrainVARI(m,:)=0;
  13. end
  14. TrainYield(all(TrainYield==0,2),:)=[];
  15. TrainVARI(all(TrainVARI==0,2),:)=[];

  其中,TrainYield是训练集的因变量,TrainVARI是训练集的自变量;TestYield是测试集的因变量,TestVARI是测试集的自变量。

  因为我这里是做估产回归的,因此变量名称就带上了Yield,大家理解即可。

1.4 随机森林实现

  这部分代码其实比较简单。

  1. %% RF
  2. nTree=100;
  3. nLeaf=5;
  4. RFModel=TreeBagger(nTree,TrainVARI,TrainYield,...
  5. 'Method','regression','OOBPredictorImportance','on', 'MinLeafSize',nLeaf);
  6. [RFPredictYield,RFPredictConfidenceInterval]=predict(RFModel,TestVARI);

  其中,nTreenLeaf就是本文1.1部分中我们确定的最优树个数与最优叶子节点个数,RFModel就是我们所训练的模型,RFPredictYield是预测结果,RFPredictConfidenceInterval是预测结果的置信区间。

1.5 精度衡量

  在这里,我们用RMSEr衡量模型精度。

  1. %% Accuracy of RF
  2. RFRMSE=sqrt(sum(sum((RFPredictYield-TestYield).^2))/size(TestYield,1));
  3. RFrMatrix=corrcoef(RFPredictYield,TestYield);
  4. RFr=RFrMatrix(1,2);
  5. RFRMSEMatrix=[RFRMSEMatrix,RFRMSE];
  6. RFrAllMatrix=[RFrAllMatrix,RFr];
  7. if RFRMSE<400
  8. disp(RFRMSE);
  9. break;
  10. end
  11. disp(RFCycleRun);
  12. str=['Random Forest is Solving...',num2str(100*RFCycleRun/RFRunNumSet),'%'];
  13. waitbar(RFCycleRun/RFRunNumSet,RFScheduleBar,str);
  14. end
  15. close(RFScheduleBar);

  在这里,我定义了当RMSE满足<400这个条件时,模型将自动停止;否则将一直执行到本文1.2部分中我们指定的次数。其中,模型每一次运行都会将RMSEr结果记录到对应的矩阵中。

1.6 变量重要程度排序

  接下来,我们结合RF算法的一个功能,对所有的输入变量进行分析,去获取每一个自变量对因变量的解释程度。

  1. %% Variable Importance Contrast
  2. VariableImportanceX={};
  3. XNum=1;
  4. % for TifFileNum=1:length(TifFileNames)
  5. % if ~(strcmp(TifFileNames(TifFileNum).name(4:end-4),'MaizeArea') | ...
  6. % strcmp(TifFileNames(TifFileNum).name(4:end-4),'MaizeYield'))
  7. % eval(['VariableImportanceX{1,XNum}=''',TifFileNames(TifFileNum).name(4:end-4),''';']);
  8. % XNum=XNum+1;
  9. % end
  10. % end
  11. for i=1:size(Input,2)
  12. eval(['VariableImportanceX{1,XNum}=''',i,''';']);
  13. XNum=XNum+1;
  14. end
  15. figure('Name','Variable Importance Contrast');
  16. VariableImportanceX=categorical(VariableImportanceX);
  17. bar(VariableImportanceX,RFModel.OOBPermutedPredictorDeltaError)
  18. xtickangle(45);
  19. set(gca, 'XDir','normal')
  20. xlabel('Factor');
  21. ylabel('Importance');

  这里代码就不再具体解释了,大家会得到一幅图,是每一个自变量对因变量的重要程度,数值越大,重要性越大。

  其中,我注释掉的这段是依据我当时的数据情况来的,大家就不用了。

  更新:这里请大家注意,上述代码中我注释掉的内容,是依据每一幅图像的名称对重要性排序的X轴(也就是VariableImportanceX)加以注释(我当时做的是依据遥感图像估产,因此每一个输入变量的名称其实就是对应的图像的名称),所以使得得到的变量重要性柱状图的X轴会显示每一个变量的名称。大家用自己的数据来跑的时候,可以自己设置一个变量名称的字段元胞然后放到VariableImportanceX,然后开始figure绘图;如果在输入数据的特征个数(也就是列数)比较少的时候,也可以用我上述代码中间的这个for i=1:size(Input,2)循环——这是一个偷懒的办法,也就是将重要性排序图的X轴中每一个变量的名称显示为一个正方形,如下图红色圈内。这里比较复杂,因此如果大家这一部分没有搞明白或者是一直报错,在本文下方直接留言就好~

1.7 保存模型

  接下来,就可以将合适的模型保存。

  1. %% RF Model Storage
  2. RFModelSavePath='G:\CropYield\02_CodeAndMap\00_SavedModel\';
  3. save(sprintf('%sRF0410.mat',RFModelSavePath),'nLeaf','nTree',...
  4. 'RandomNumber','RFModel','RFPredictConfidenceInterval','RFPredictYield','RFr','RFRMSE',...
  5. 'TestVARI','TestYield','TrainVARI','TrainYield');

  其中,RFModelSavePath是保存路径,save后的内容是需要保存的变量名称。

2 完整代码

  完整代码如下:

  1. %% Number of Leaves and Trees Optimization
  2. for RFOptimizationNum=1:5
  3. RFLeaf=[5,10,20,50,100,200,500];
  4. col='rgbcmyk';
  5. figure('Name','RF Leaves and Trees');
  6. for i=1:length(RFLeaf)
  7. RFModel=TreeBagger(2000,Input,Output,'Method','R','OOBPrediction','On','MinLeafSize',RFLeaf(i));
  8. plot(oobError(RFModel),col(i));
  9. hold on
  10. end
  11. xlabel('Number of Grown Trees');
  12. ylabel('Mean Squared Error') ;
  13. LeafTreelgd=legend({'5' '10' '20' '50' '100' '200' '500'},'Location','NorthEast');
  14. title(LeafTreelgd,'Number of Leaves');
  15. hold off;
  16. disp(RFOptimizationNum);
  17. end
  18. %% Notification
  19. % Set breakpoints here.
  20. %% Cycle Preparation
  21. RFScheduleBar=waitbar(0,'Random Forest is Solving...');
  22. RFRMSEMatrix=[];
  23. RFrAllMatrix=[];
  24. RFRunNumSet=50000;
  25. for RFCycleRun=1:RFRunNumSet
  26. %% Training Set and Test Set Division
  27. RandomNumber=(randperm(length(Output),floor(length(Output)*0.2)))';
  28. TrainYield=Output;
  29. TestYield=zeros(length(RandomNumber),1);
  30. TrainVARI=Input;
  31. TestVARI=zeros(length(RandomNumber),size(TrainVARI,2));
  32. for i=1:length(RandomNumber)
  33. m=RandomNumber(i,1);
  34. TestYield(i,1)=TrainYield(m,1);
  35. TestVARI(i,:)=TrainVARI(m,:);
  36. TrainYield(m,1)=0;
  37. TrainVARI(m,:)=0;
  38. end
  39. TrainYield(all(TrainYield==0,2),:)=[];
  40. TrainVARI(all(TrainVARI==0,2),:)=[];
  41. %% RF
  42. nTree=100;
  43. nLeaf=5;
  44. RFModel=TreeBagger(nTree,TrainVARI,TrainYield,...
  45. 'Method','regression','OOBPredictorImportance','on', 'MinLeafSize',nLeaf);
  46. [RFPredictYield,RFPredictConfidenceInterval]=predict(RFModel,TestVARI);
  47. % PredictBC107=cellfun(@str2num,PredictBC107(1:end));
  48. %% Accuracy of RF
  49. RFRMSE=sqrt(sum(sum((RFPredictYield-TestYield).^2))/size(TestYield,1));
  50. RFrMatrix=corrcoef(RFPredictYield,TestYield);
  51. RFr=RFrMatrix(1,2);
  52. RFRMSEMatrix=[RFRMSEMatrix,RFRMSE];
  53. RFrAllMatrix=[RFrAllMatrix,RFr];
  54. if RFRMSE<1000
  55. disp(RFRMSE);
  56. break;
  57. end
  58. disp(RFCycleRun);
  59. str=['Random Forest is Solving...',num2str(100*RFCycleRun/RFRunNumSet),'%'];
  60. waitbar(RFCycleRun/RFRunNumSet,RFScheduleBar,str);
  61. end
  62. close(RFScheduleBar);
  63. %% Variable Importance Contrast
  64. VariableImportanceX={};
  65. XNum=1;
  66. % for TifFileNum=1:length(TifFileNames)
  67. % if ~(strcmp(TifFileNames(TifFileNum).name(4:end-4),'MaizeArea') | ...
  68. % strcmp(TifFileNames(TifFileNum).name(4:end-4),'MaizeYield'))
  69. % eval(['VariableImportanceX{1,XNum}=''',TifFileNames(TifFileNum).name(4:end-4),''';']);
  70. % XNum=XNum+1;
  71. % end
  72. % end
  73. for i=1:size(Input,2)
  74. eval(['VariableImportanceX{1,XNum}=''',i,''';']);
  75. XNum=XNum+1;
  76. end
  77. figure('Name','Variable Importance Contrast');
  78. VariableImportanceX=categorical(VariableImportanceX);
  79. bar(VariableImportanceX,RFModel.OOBPermutedPredictorDeltaError)
  80. xtickangle(45);
  81. set(gca, 'XDir','normal')
  82. xlabel('Factor');
  83. ylabel('Importance');
  84. %% RF Model Storage
  85. RFModelSavePath='G:\CropYield\02_CodeAndMap\00_SavedModel\';
  86. save(sprintf('%sRF0410.mat',RFModelSavePath),'nLeaf','nTree',...
  87. 'RandomNumber','RFModel','RFPredictConfidenceInterval','RFPredictYield','RFr','RFRMSE',...
  88. 'TestVARI','TestYield','TrainVARI','TrainYield');

  至此,大功告成。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/94475
推荐阅读
相关标签
  

闽ICP备14008679号