昨天我在MATLab中实现了我的第一个引导程序。 (是的,我知道,因为循环是邪恶的。):
%data is an mxn matrix where the data should be sampled per column but there
can be a NaNs Elements
%from the array (a column of data) n values are sampled nReps times
function result = bootstrap_std(data, n, nReps,quantil)
result = zeros(1,size(data,2));
for i=1:size(data,2)
bootstrap_data = zeros(n,nReps);
values = find(~isnan(data(:,i)));
if isempty(values)
bootstrap_data(:,:) = NaN;
else
for k=1:nReps
bootstrap_data(:,k) = datasample(data(values,i),n);
end
end
stat = zeros(1,nReps);
for k=1:nReps
stat(k) = nanstd(bootstrap_data(:,k));
end
sort(stat);
result(i) = quantile(stat,quantil);
end
end
可以看出,此版本按列方式工作。该算法可以实现应有的功能,但在数据大小增加时却非常慢。我现在的问题是:是否可以在不使用for循环的情况下实现此逻辑?我的问题是在这里我找不到以数据为单位进行采样的数据样本。或者是否有更好的功能使用?
我很高兴有任何提示或想法如何加快这种实施。
谢谢和最诚挚的问候!
斯蒂芬
答案 0 :(得分:2)
您的实施中的瓶颈是
nanstd
内花费了大量时间,这是不必要的,因为无论如何都要从样本中排除NaN
值。datasample
,这是一个相对较慢的功能。使用randi
创建索引的随机向量并使用它更快。以下是我将如何编写函数(实际上我可能不会放在这么多注释中,我不会使用这么多的临时变量,但我现在正在这样做,所以你可以看到所有的步骤计算是)。
function result = bootstrap_std_new(data, n, nRep, quantil)
result = zeros(1, size(data,2));
for i = 1:size(data,2)
isbad = isnan(data(:,i)); %// Vector of NaN values
if all(isbad)
result(i) = NaN;
else
data0 = data(~isbad, i); %// Temp copy of this column for indexing
index = randi(size(data0,1), n, nRep); %// Create the indexing vector
bootstrapdata = data0(index); %// Sample the data
stdevs = std(bootstrapdata); %// Stdev of sampled data
result(i) = quantile(stdevs, quantil); %// Find the correct quantile
end
end
end
以下是一些时间
>> data = randn(100,10);
>> data(randi(1000, 50, 1)) = NaN;
>> tic, bootstrap_std(data, 50, 1000, 0.5); toc
Elapsed time is 1.359529 seconds.
>> tic, bootstrap_std_new(data, 50, 1000, 0.5); toc
Elapsed time is 0.038558 seconds.
因此,这为您提供了35倍的加速。
答案 1 :(得分:0)
您的主要问题似乎是每列中的NaN
数量/位置不同,因此除非您也可以对NaN进行采样,否则无法对完整矩阵起作用。但是,一些内部循环可以简化。
for k=1:nReps
bootstrap_data(:,k) = datasample(data(values,i),n);
end
由于您正在使用替换品进行抽样,您应该能够做到:
bootstrap_data = datasample(data(values,i), n*nReps);
bootstrap_data = reshape(bootstrap_data, [n nReps]);
此外nanstd
可以处理完整矩阵,因此无需循环:
stat = nanstd(bootstrap_data); % or nanstd(x,0,2) to change dimension
使用profile
查看代码也值得查看瓶颈所在。