You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Matlab的PCA后GMM聚类与阈值确定毕设技术求助

针对你的PCA后数据重叠问题,用GMM做故障检测的Matlab实现方案

嘿,你的毕设遇到的这个问题很典型——PCA降维后健康和故障数据重叠,说明线性降维的区分度不够,用GMM这种概率模型来建模健康数据的分布,确实是个不错的思路。下面我一步步给你讲具体操作,附带Matlab代码,你可以直接套用到你的数据上:

1. 先把数据理清楚,完成PCA投影

首先要确保你的数据格式是每行一个样本,每列一个变量。假设你的健康数据存在X_healthy(比如m行9列),7组故障数据存在一个细胞数组X_fault里(X_fault{1}到X_fault{7}分别对应每组故障数据)。

关键:PCA必须只用健康数据训练,这样才能保证投影空间是基于健康状态的:

% 对健康数据做PCA,提取前3个主成分
[coeff, score_healthy, ~] = pca(X_healthy);
PC_num = 3;
coeff_selected = coeff(:, 1:PC_num);

% 把健康数据投影到PCA空间
score_healthy_pca = score_healthy(:, 1:PC_num);

% 把所有故障数据也投影到同一个PCA空间
score_fault_pca = [];
for i = 1:7
    % 注意要减去健康数据的均值,和PCA训练时保持一致
    score_temp = (X_fault{i} - mean(X_healthy, 1)) * coeff_selected;
    score_fault_pca = [score_fault_pca; score_temp];
end

% 合并所有数据方便后续处理
all_scores = [score_healthy_pca; score_fault_pca];

2. 用健康数据训练GMM模型

GMM的作用是拟合健康数据在PCA空间里的概率分布,后续我们用这个分布来判断样本是否“异常”。Matlab自带的fitgmdist函数可以直接用:

方法一:手动指定分量数

如果你想快速测试,可以先指定分量数(比如2-5,一般2或3就够):

k = 2; % 先试试2个分量
gmm_model = fitgmdist(score_healthy_pca, k);

方法二:用BIC准则自动选最优分量数

如果想更严谨,用贝叶斯信息准则(BIC)选最优的分量数,避免过拟合或欠拟合:

max_k = 5; % 最多试5个分量
bic_values = zeros(max_k, 1);
for k = 1:max_k
    model = fitgmdist(score_healthy_pca, k);
    bic_values(k) = model.BIC;
end
% 找BIC最小的分量数(BIC越小,模型拟合越好)
[~, optimal_k] = min(bic_values);
gmm_model = fitgmdist(score_healthy_pca, optimal_k);

3. 计算每个样本的对数概率密度

训练好GMM后,计算每个样本在这个模型下的对数概率密度——健康样本的概率会比较高,故障样本因为偏离健康分布,概率会低很多:

% 健康样本的对数概率
log_prob_healthy = logpdf(gmm_model, score_healthy_pca);
% 故障样本的对数概率
log_prob_fault = logpdf(gmm_model, score_fault_pca);

4. 确定故障检测的阈值

我们用健康样本的对数概率分布来设定阈值,比如取健康样本对数概率的第5百分位数——意思是95%的健康样本概率都高于这个值,低于这个值的样本就判定为故障:

% 计算第5百分位作为阈值(你也可以试试第10百分位,根据误报率调整)
threshold = prctile(log_prob_healthy, 5);

如果想更精准,也可以画ROC曲线找最优阈值,但毕设里用百分位数已经足够直观,容易解释。

5. 验证检测效果并可视化

最后一步就是看看你的GMM模型能不能有效区分健康和故障数据:

% 计算健康样本的误报率(把健康判成故障的比例)
healthy_pred = log_prob_healthy < threshold;
false_alarm_rate = sum(healthy_pred)/length(healthy_pred);
fprintf('健康样本误报率:%.2f%%\n', false_alarm_rate*100);

% 计算故障样本的检测率(把故障正确判出来的比例)
fault_pred = log_prob_fault < threshold;
detection_rate = sum(fault_pred)/length(fault_pred);
fprintf('故障样本检测率:%.2f%%\n', detection_rate*100);

% 画箱线图直观对比
boxplot([log_prob_healthy; log_prob_fault], ...
    'Labels', {'健康数据', '故障数据'}, ...
    'Title', '健康与故障数据的对数概率分布');
hold on;
% 画出阈值线
plot([1,2], [threshold, threshold], 'r--', 'LineWidth', 2);
legend('样本数据', '检测阈值');
hold off;

几个关键提醒

  • 绝对不能用故障数据训练GMM:GMM是用来建模健康状态的分布,混进故障数据会让模型“适应”异常,失去检测能力。
  • 如果对数概率的区分度还是不够,可以试试用PCA的残差来训练GMM:就是原始数据减去PCA重构的数据,残差里的异常信号有时候更明显。
  • 分量数k不用太大,一般2-3就足够,太大容易过拟合健康数据的噪声。

内容的提问来源于stack exchange,提问作者user624918

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:16:44