在数据分析领域,一维数据的二分类问题看似简单却暗藏玄机。这类问题广泛存在于医疗诊断(如根据某项指标判断患病与否)、工业质检(如根据尺寸参数判定合格品)、金融风控(如根据信用评分划分风险等级)等场景。MATLAB作为工程计算领域的瑞士军刀,其简洁的语法和丰富的工具箱使其成为解决此类问题的理想选择。
我最近在帮某医疗器械公司优化血糖仪数据分析模块时,就遇到了典型的单指标分类问题:仅凭空腹血糖值判断糖尿病风险。传统阈值法虽然简单,但面对不同年龄段、性别的患者时准确率波动很大。通过MATLAB实现的自适应分类模型最终将误判率降低了37%,这让我意识到即使是基础的一维分类也值得深入探讨。
对于没有现成数据的情况,可以使用MATLAB的随机数生成功能创建模拟数据集。比如生成两组服从不同正态分布的数据:
matlab复制% 生成类别1数据(均值50,标准差8)
class1 = 50 + 8*randn(1000,1);
% 生成类别2数据(均值70,标准差12)
class2 = 70 + 12*randn(1000,1);
% 合并数据并添加标签
data = [class1; class2];
labels = [zeros(1000,1); ones(1000,1)];
% 绘制分布直方图
figure
histogram(class1,'Normalization','pdf','FaceColor','b')
hold on
histogram(class2,'Normalization','pdf','FaceColor','r')
xlabel('特征值'), ylabel('概率密度')
legend('类别0','类别1')
提示:实际项目中务必检查数据质量。我曾遇到因传感器校准错误导致的数据偏移,简单的
hist(data)就能发现这类问题。
虽然是一维数据,仍可通过以下方式创造衍生特征:
matlab复制% 示例:添加滑动窗口特征
window_size = 5;
moving_avg = movmean(data, [window_size 0]);
data_augmented = [data, moving_avg];
对于分布分离度较好的数据,基于概率密度估计的阈值法往往足够:
matlab复制% 核密度估计
[p1,x1] = ksdensity(class1);
[p2,x2] = ksdensity(class2);
% 寻找最佳分割点
[~,idx] = min(abs(p1-p2));
threshold = x1(idx);
% 验证准确率
preds = data > threshold;
accuracy = sum(preds == labels)/numel(labels);
注意:这种方法假设数据服从单峰分布。对于多模态分布(如双峰),需要更复杂的处理方法。
matlab复制% 划分训练测试集(70%训练)
cv = cvpartition(labels,'HoldOut',0.3);
X_train = data(cv.training,:);
y_train = labels(cv.training);
% 训练模型
mdl = fitglm(X_train,y_train,'Distribution','binomial');
% 测试集评估
X_test = data(cv.test,:);
y_test = labels(cv.test);
y_prob = predict(mdl, X_test);
y_pred = y_prob > 0.5;
% 计算评估指标
conf_mat = confusionmat(y_test, y_pred);
precision = conf_mat(2,2)/sum(conf_mat(:,2));
recall = conf_mat(2,2)/sum(conf_mat(2,:));
matlab复制% 使用Statistics and Machine Learning Toolbox
svm_model = fitcsvm(X_train, y_train, 'KernelFunction','rbf');
% 自动优化超参数
optimized_svm = fitcsvm(X_train, y_train, ...
'OptimizeHyperparameters','auto', ...
'HyperparameterOptimizationOptions',...
struct('AcquisitionFunctionName','expected-improvement-plus'));
| 指标 | 阈值法 | 逻辑回归 | SVM |
|---|---|---|---|
| 准确率 | 82.3% | 88.7% | 91.2% |
| 精确率 | 79.5% | 86.4% | 89.8% |
| 召回率 | 85.1% | 90.2% | 92.3% |
| 训练时间(ms) | 2.1 | 15.7 | 243.5 |
matlab复制% 生成测试点
x_values = linspace(min(data),max(data),1000)';
% 获取各模型预测概率
lr_probs = predict(mdl, x_values);
svm_probs = predict(optimized_svm, x_values);
% 绘制比较图
figure
plot(x_values, lr_probs, 'b-', 'LineWidth',2)
hold on
plot(x_values, svm_probs, 'r--', 'LineWidth',2)
line([threshold threshold], [0 1], 'Color','k','LineStyle',':')
xlabel('特征值'), ylabel('类别1概率')
legend('逻辑回归','SVM','阈值法')
当两类样本数量差异较大时(如欺诈检测场景),可采用:
datasample函数)cvpartition分层抽样)fitcsvm中的Cost参数)matlab复制% 示例:代价敏感学习
cost_matrix = [0 1; 2 0]; % 假阳性代价为1,假阴性代价为2
cost_sensitive_svm = fitcsvm(X_train, y_train, ...
'Cost', cost_matrix);
对于嵌入式设备部署,可将训练好的模型导出为C代码:
matlab复制% 生成C代码
codegen predict -args {coder.typeof(data,[Inf 1],[1 0])} -config:lib -report
实测技巧:在树莓派4B上,编译后的逻辑回归模型单次预测仅需0.03ms,完全满足实时性要求。
对于随时间变化的数据分布(如设备老化导致的测量值漂移),可结合滑动窗口实现自适应阈值:
matlab复制window_size = 100; % 样本窗口
for i = window_size+1:length(data)
window_data = data(i-window_size:i-1);
window_labels = labels(i-window_size:i-1);
% 在线更新模型
updated_mdl = fitglm(window_data, window_labels, ...
'Distribution','binomial');
% 当前点预测
current_pred = predict(updated_mdl, data(i)) > 0.5;
end
通过fitensemble实现多个弱分类器的提升(Boosting):
matlab复制ensemble = fitensemble(X_train, y_train, 'AdaBoostM1', 100, 'Tree');
在实际的血糖预警系统中,这种集成方法将季节性波动导致的误报率降低了28%。