基于蒙特卡洛的异常值剔除(RANSAC + MC置信区间)—MATLAB实现

两种主流蒙特卡洛异常值剔除方法


方法一: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 单变量数据,怀疑少数极端异常 统计理论基础扎实 只能检测单个极端值,多次检验需校正

工程实用建议

  1. RANSAC阈值 :可通过数据尺度自适应,例如设为 median(abs(y - median(y))) * 1.4826(MAD估计)。
  2. MC模拟次数:一般5000~10000次足够稳定,过大影响速度。
  3. 混合策略:先用RANSAC剔除结构性异常,再用Grubbs剔除孤立极端值。
相关推荐
Ting.~2 小时前
在java中接入百度地图
java·开发语言·dubbo
小短腿的代码世界2 小时前
Qt对象树析构链与智能指针协同:零泄漏内存管理架构
开发语言·qt·架构
zhaqonianzhu2 小时前
LOL切回桌面问题,采用监控抓出元凶方式
开发语言
Aurorar0rua2 小时前
CS50 x 2024 Notes Arrays - 04
c语言·开发语言·学习方法
Asize2 小时前
数组数据结构底层:从灵活到陷阱
前端·javascript·算法
hairenwangmiao2 小时前
B4041 [GESP202409 四级] 区间排序
算法·排序
一起吃元宵2 小时前
百度网盘下载不限速的办法_百度网盘不限速
开发语言·百度网盘·下载不限速·不限速·百度网盘不限速
人道领域2 小时前
【LeetCode刷题日记】47.全排列Ⅱ
java·开发语言·算法·leetcode
漂流瓶jz2 小时前
UVA-1606 两亲性分子 题解答案代码 算法竞赛入门经典第二版
数据结构·算法·向量·aoapc·算法竞赛入门经典·atan2·浮点