两种主流蒙特卡洛异常值剔除方法
方法一:RANSAC(随机抽样一致)------ 最经典的蒙特卡洛鲁棒拟合
RANSAC通过随机采样 和内点计数迭代找出最能代表数据的模型,天然剔除异常值。
1.1 线性拟合RANSAC代码
matlab
function [bestModel, inlierIdx] = ransac_line(x, y, maxTrials, threshold, minInliers)
% RANSAC 线性拟合,剔除异常值
% 输入:
% x,y - 数据点(列向量)
% maxTrials - 最大迭代次数(蒙特卡洛采样数)
% threshold - 内点到直线的距离阈值
% minInliers - 最少内点数量(可选,默认总点数*0.5)
% 输出:
% bestModel - [斜率, 截距]
% inlierIdx - 内点逻辑索引
arguments
x (:,1) double
y (:,1) double
maxTrials (1,1) double = 1000
threshold (1,1) double = 0.5
minInliers (1,1) double = []
end
n = length(x);
if isempty(minInliers)
minInliers = round(0.5 * n); % 默认至少50%内点
end
bestModel = [0, 0];
bestInlierCount = 0;
inlierIdx = false(n,1);
for trial = 1:maxTrials
% 1. 随机选取2个点(最小样本集)
idx = randsample(n, 2);
xSample = x(idx);
ySample = y(idx);
% 2. 由两点确定直线模型
if diff(xSample) == 0
continue; % 垂直线,跳过(可根据需要处理)
end
slope = diff(ySample) / diff(xSample);
intercept = ySample(1) - slope * xSample(1);
% 3. 计算所有点到直线的距离
distances = abs(y - (slope*x + intercept)) / sqrt(slope^2 + 1);
% 4. 统计内点个数
inliers = distances < threshold;
inlierCount = sum(inliers);
% 5. 更新最优模型
if inlierCount > bestInlierCount && inlierCount >= minInliers
bestInlierCount = inlierCount;
bestModel = [slope, intercept];
inlierIdx = inliers;
end
end
% 可选:用所有内点重新拟合(最小二乘)提高精度
if bestInlierCount > 0
p = polyfit(x(inlierIdx), y(inlierIdx), 1);
bestModel = p;
end
fprintf('RANSAC完成:迭代%d次,内点%d个\n', maxTrials, bestInlierCount);
end
1.2 使用示例
matlab
%% 生成含异常值的数据
x = (0:0.5:20)';
y = 2*x + 5 + 2*randn(size(x)); % 正常数据
outlierIdx = randi(length(x), 10, 1);
y(outlierIdx) = y(outlierIdx) + 30*randn(10,1); % 加入异常
%% RANSAC剔除异常
[model, inlierMask] = ransac_line(x, y, 2000, 1.5);
%% 绘图对比
figure('Position',[100 100 560 380]);
plot(x, y, 'ko', 'MarkerSize',6, 'MarkerFaceColor','k'); hold on;
plot(x(inlierMask), y(inlierMask), 'bo', 'MarkerSize',8, 'MarkerFaceColor','b');
x_fit = [min(x); max(x)];
y_fit = polyval(model, x_fit);
plot(x_fit, y_fit, 'r-', 'LineWidth',2);
legend('全部数据','RANSAC内点','拟合直线');
title('RANSAC蒙特卡洛异常值剔除');
方法二:基于MC模拟的置信区间法(假设正态分布)
当数据大致服从正态分布时,通过蒙特卡洛模拟生成均值 和标准差的抽样分布,从而确定异常值阈值。
2.1 代码实现
matlab
function cleanedData = mc_outlier_removal(data, alpha, nSim)
% 蒙特卡洛模拟剔除异常值(基于正态假设)
% 输入:
% data - 列向量
% alpha - 显著性水平(如0.05)
% nSim - 蒙特卡洛模拟次数
% 输出:
% cleanedData - 剔除异常后的数据(保留原顺序)
arguments
data (:,1) double
alpha (1,1) double = 0.05
nSim (1,1) double = 10000
end
n = length(data);
mu_hat = mean(data);
sigma_hat = std(data);
% 蒙特卡洛模拟:从假设的正态分布中抽样,计算极端统计量
extreme_stats = zeros(nSim,1);
for i = 1:nSim
simData = mu_hat + sigma_hat * randn(n,1);
% 计算最大绝对偏差(相对于样本均值)
extreme_stats(i) = max(abs(simData - mean(simData)));
end
% 确定临界值(1-alpha分位数)
critical_value = quantile(extreme_stats, 1 - alpha);
% 在原数据中标记异常(超过临界值)
deviation = abs(data - mean(data));
isOutlier = deviation > critical_value;
cleanedData = data(~isOutlier);
fprintf('MC模拟剔除异常:原始%d个,剔除%d个,剩余%d个\n', ...
n, sum(isOutlier), length(cleanedData));
end
2.2 使用示例
matlab
%% 生成含异常的正态数据
rng(1);
data = [randn(100,1)*2 + 10; 25; 30; 8; 12]; % 加入4个异常
%% MC剔除
clean = mc_outlier_removal(data, 0.05, 5000);
%% 可视化
figure;
subplot(1,2,1);
histogram(data, 20); title('原始数据(含异常)');
subplot(1,2,2);
histogram(clean, 20); title('剔除异常后');
方法三:蒙特卡洛Grubbs检验(迭代剔除)
Grubbs检验是统计学中经典的异常值检测方法,结合蒙特卡洛模拟可处理非正态或小样本情况。
matlab
function [cleanData, outliers] = mc_grubbs_test(data, alpha, maxOutliers)
% 蒙特卡洛Grubbs检验:逐步剔除最极端的异常值
% 每次检验最大偏离值是否为异常,通过MC模拟计算临界值
arguments
data (:,1) double
alpha (1,1) double = 0.05
maxOutliers (1,1) double = round(0.2*length(data))
end
cleanData = data;
outliers = [];
n = length(data);
for iter = 1:maxOutliers
if n < 3, break; end
% 计算当前Grubbs统计量
mu = mean(cleanData);
sigma = std(cleanData);
[maxDev, idx] = max(abs(cleanData - mu));
G = maxDev / sigma;
% 蒙特卡洛模拟临界值
nSim = 5000;
G_sim = zeros(nSim,1);
for s = 1:nSim
simData = mu + sigma * randn(n,1);
G_sim(s) = max(abs(simData - mean(simData))) / std(simData);
end
critical = quantile(G_sim, 1 - alpha/n); % Bonferroni校正
if G > critical
outliers = [outliers; cleanData(idx)]; %#ok<AGROW>
cleanData(idx) = [];
n = n - 1;
else
break;
end
end
fprintf('Grubbs-MC检验:剔除%d个异常值\n', length(outliers));
end
参考代码 用于解决剔除样本异常值的蒙特卡洛mtlab代码 www.youwenfan.com/contentcsv/80952.html
方法对比与选用建议
| 方法 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| RANSAC | 数据有明确模型(直线、平面等) | 对大量异常鲁棒,不依赖分布假设 | 需要预设模型和阈值 |
| MC置信区间 | 近似正态分布 | 简单直观,可自定义显著性 | 对非正态数据效果差 |
| MC Grubbs | 单变量数据,怀疑少数极端异常 | 统计理论基础扎实 | 只能检测单个极端值,多次检验需校正 |
工程实用建议
- RANSAC阈值 :可通过数据尺度自适应,例如设为
median(abs(y - median(y))) * 1.4826(MAD估计)。 - MC模拟次数:一般5000~10000次足够稳定,过大影响速度。
- 混合策略:先用RANSAC剔除结构性异常,再用Grubbs剔除孤立极端值。