我正在尝试实现一种迭代算法来估计从蒙特卡罗模拟生成的数据中的分位数。我想让它迭代,因为我有很多迭代和变量,因此存储所有数据点并使用Matlab的分位数函数将占用我实际需要的大部分内存。
我找到了一些基于Robbin-Monro process的方法,由
给出
具有控制序列c t = c / t的实现,其中c是常数非常简单。在引用的论文中,他们表明c = 2 * sqrt(2 * pi)给出了相当好的结果,至少对于中位数而言。但他们也提出了一种基于直方图估计的自适应方法。不幸的是,我还没有想出如何实现这种改编。
我测试了implementation with a constant c,得到了具有10.000个数据点的三个测试样本。值c = 2 * sqrt(2 * pi)对我来说效果不好,但对于测试样本,c = 100看起来相当不错。然而,这种选择并不是非常强大,并且在实际的蒙特卡罗模拟中失败了,结果却很难实现。
probabilities = [0.1, 0.4, 0.7];
controlFactor = 100;
quantile = zeros(size(probabilities));
indicator = zeros(size(probabilities));
for index = 1:length(data)
control = controlFactor / index;
indices = (data(index) >= quantile);
indicator(indices) = probabilities(indices);
indices = (data(index) < quantile);
indicator(indices) = probabilities(indices) - 1;
quantile = quantile + control * indicator;
end
迭代分位数估计是否有更强大的解决方案,或者是否有人实现了内存消耗较小的自适应方法?
答案 0 :(得分:0)
在尝试了一些我在文献中找到的自适应迭代方法之后没有取得很大的成功(不确定,如果我做对了),我想出了一个解决方案,它为我的测试样本提供了良好的结果,也为实际的蒙特卡洛模拟。
我缓冲模拟结果的子集,计算样本分位数并最终对所有子集样本分位数求平均值。这似乎工作得很好,没有调整许多参数。唯一的参数是缓冲区大小,在我的情况下为100。
结果收敛得非常快,增加的样本量并没有显着改善结果。似乎存在小的但是恒定的偏差,可能是子集样本分位数的平均误差。这是我的解决方案的缺点。通过选择缓冲区大小,可以确定可实现的精度。增加缓冲区大小可以减少这种偏差。最后,它似乎是一种记忆和准确性的权衡。
% Generate data
rng('default');
data = sqrt(0.5) * randn(10000, 1) + 5 * rand(10000, 1) + 10;
% Set parameters
probabilities = 0.2;
% Compute reference sample quantiles
quantileEstimation1 = quantile(data, probabilities);
% Estimate quantiles with computing the mean over a number of subset
% sample quantiles
subsetSize = 100;
quantileSum = 0;
for index = 1:length(data) / subsetSize;
quantileSum = quantileSum + quantile(data(((index - 1) * subsetSize + 1):(index * subsetSize)), probabilities);
end
quantileEstimation2 = quantileSum / (length(data) / subsetSize);
% Estimate quantiles with iterative computation
quantileEstimation3 = zeros(size(probabilities));
indicator = zeros(size(probabilities));
controlFactor = 2 * sqrt(2 * pi);
for index = 1:length(data)
control = controlFactor / index;
indices = (data(index) >= quantileEstimation3);
indicator(indices) = probabilities(indices);
indices = (data(index) < quantileEstimation3);
indicator(indices) = probabilities(indices) - 1;
quantileEstimation3 = quantileEstimation3 + control * indicator;
end
fprintf('Reference result: %f\nSubset result: %f\nIterative result: %f\n\n', quantileEstimation1, quantileEstimation2, quantileEstimation3);