Matlab机器学习分类与参数寻优

做过机器学习的小伙伴都知道,手动调参是非常痛苦的一件事,单个参数调整还好,但是一旦多个参数调整就非常麻烦,耗时不说,还得守着电脑一点点试。

前两天在一个matlab群里聊天,有一位朋友问到matlab有没有像python的gridsearchcv这样的寻找最优参数的函数。我想起之前在做一些小项目的时候是用遗传算法来找寻最优参数的。因此本来想记录一下这个方法,于是找了个小项目想试一下,但是奈何鄙人不才,没能调试成功,本着不害人的态度,最后只能用for循环来完成。

废话不多说,开始正题。

该示例的目的是对机器是否发生故障进行预测(与我之前写的Python gridsearchcv那一篇一样)。

1 数据读取与处理
%% 读取数据
data = readtable('train data.xlsx',VariableNamingRule='preserve');

 观察一下原始数据格式,有几列数据是用不到的,因此这个直接删除这几列,

% 去除无用数据
data.("机器编号")=[];
data.("统一规范代码")=[];
data.("具体故障类别")=[];

同时,“机器质量等级” 这一列是字符,这里我们把它编码成 1 2 3 这种离散数值。

% 编码
map=string(data.("机器质量等级"));
map(map=='H')=1;
map(map=='M')=2;
map(map=='L')=3;
data.("机器质量等级")=double(map);

至此我们数据就算处理好了,现在要做的就是构建模型,对第7列 “是否发生故障” 进行预测。

2 数据划分

利用cvpartition函数 按照7:3来划分训练集与测试集。

% 定义划分比例
trainRatio = 0.7; % 训练集比例
testRatio = 0.3; % 测试集比例

% 随机划分数据集
cv = cvpartition(size(data, 1), 'HoldOut', testRatio);

% 获取训练集和测试集索引
trainIndices = training(cv);
testIndices = test(cv);

% 根据索引划分数据集
trainData = data(trainIndices, :); % 训练集数据
testData = data(testIndices, :); % 测试集数据
trainLabels=trainData(:,7);
testLabels=testData(:,7);
trainData(:,7)=[];
testData(:,7)=[];
trainData=table2array(trainData);
testData=table2array(testData);
 3 模型构建

这里我们新建一个函数文件rf_fun.m,专门用来放随机森林模型函数。

function [accuracy,predictedLabels] = rf_fun(trainData,trainLabels,testData,testLabels,numTrees,MaxNumSplits)
% 训练随机森林分类器
model = TreeBagger(numTrees, trainData, trainLabels,'MaxNumSplits',MaxNumSplits);

% 预测测试集
predictedLabels = double(string(predict(model, testData)));

% 评估分类器性能
accuracy = 1-sum(abs(predictedLabels-testLabels)) ./ numel(testLabels);
disp(['准确率:', num2str(accuracy)]);
end

我们放在主函数里运行一下,发现准确率为0.9711,当然,这个结果具有随机性,由于数据划分原因,每次运行结果都不一样,但大概就是0.97左右。

%% 随机森林
[accuracy,predictedLabels] = rf_fun(trainData,trainLabels,testData,testLabels,numTrees,MaxNumSplits)

4  参数寻优

一切准备工作就绪后,下面就是参数寻优过程了,这里由于是寻找两个参数,我写了两个for循环,i 代表树的数量这个参数,j 代表最大分裂数这个参数,调用我们之前写好的随机森林函数,并添加一个if语句来判断准确率是否是最高,将准确率最高的那次结果存储在4个best变量里。

% 参数寻优
n=1;
accuracy_max=0.9;
for i=100:50:400
    for j=1:10
        [accuracy(n),predictedLabels(:,n)] = rf_fun(trainData,trainLabels,testData,testLabels,i,j);
        if accuracy(n)>accuracy_max
            accuracy_max=accuracy(n);
            best_acc=accuracy(n);
            best_predict=predictedLabels(:,n);
            best_numTrees=i;
            best_MaxNumSplits=j;
        end
        n=n+1;
    end
end
disp(['最优参数为:',num2str([best_numTrees,best_MaxNumSplits])]);
disp(['准确率为:',num2str(best_acc)]);

我们运行一下看看,

 可以看到,当树的数量为200,最大分裂节点为9时,准确率最高,为0.97963,比刚刚的结果高出了0.008左右。

绘制准确率曲线发现,当X=29和69时准确率是一样的,也就是当数的数量为200或400,最大分裂节点为9,测试集准确率最高。

 总结

总结一下,这个方法运行起来也很慢,但是避免了手动一个个调参了,起码可以放着运行然后安心玩手机了不是么?

还有开头说的遗传算法寻优,我想了一下运行不通的原因,是因为这几个参数都是整数,因此需要用到整数规划,待我调试好再做补充吧。

有错误与不足的地方欢迎各位批评指正!

完整代码

主函数:

clc,clear
close all
% matlab参数寻优示例
% 读取数据
data = readtable('train data.xlsx',VariableNamingRule='preserve');

% 去除无用数据
data.("机器编号")=[];
data.("统一规范代码")=[];
data.("具体故障类别")=[];

% 编码
map=string(data.("机器质量等级"));
map(map=='H')=1;
map(map=='M')=2;
map(map=='L')=3;
data.("机器质量等级")=double(map);

% 数据划分
% 定义划分比例
trainRatio = 0.7; % 训练集比例
testRatio = 0.3; % 测试集比例

% 随机划分数据集
cv = cvpartition(size(data, 1), 'HoldOut', testRatio);

% 获取训练集和测试集索引
trainIndices = training(cv);
testIndices = test(cv);

% 根据索引划分数据集
trainData = data(trainIndices, :); % 训练集数据
testData = data(testIndices, :); % 测试集数据
trainLabels=trainData.(7);
testLabels=testData.(7);
trainData(:,7)=[];
testData(:,7)=[];
trainData=table2array(trainData);
testData=table2array(testData);

% 参数寻优
n=1;
accuracy_max=0.9;
for i=100:50:400
    for j=1:10
        [accuracy(n),predictedLabels(:,n)] = rf_fun(trainData,trainLabels,testData,testLabels,i,j);
        if accuracy(n)>accuracy_max
            accuracy_max=accuracy(n);
            best_acc=accuracy(n);
            best_predict=predictedLabels(:,n);
            best_numTrees=i;
            best_MaxNumSplits=j;
        end
        n=n+1;
    end
end
disp(['最优参数为:',num2str([best_numTrees,best_MaxNumSplits])]);
disp(['准确率为:',num2str(best_acc)]);
plot(accuracy)

随机森林函数:

function [accuracy,predictedLabels] = rf_fun(trainData,trainLabels,testData,testLabels,numTrees,MaxNumSplits)
% 训练随机森林分类器
model = TreeBagger(numTrees, trainData, trainLabels,'MaxNumSplits',MaxNumSplits);

% 预测测试集
predictedLabels = double(string(predict(model, testData)));

% 评估分类器性能
accuracy = 1-sum(abs(predictedLabels-testLabels)) ./ numel(testLabels);
disp(['准确率:', num2str(accuracy)]);
end

  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值