Какая функция позволяет мне рассчитать совокупную дисперсию по вектору? - PullRequest
0 голосов
/ 11 октября 2019

Мне нужно рассчитать кумулятивную дисперсию вектора. Я пытался построить и написать сценарий, но этот сценарий занимает слишком много времени, чтобы вычислить совокупную дисперсию моих векторов размером 1 * 100000. Знаете ли вы, если существует более быстрый способ найти эту совокупную дисперсию?

Это код, который я использую

%%Creation of the rand vectors. ans calculation of the variances

d=100000; %dimension of the vectors
nv=6 %quantity of vectors
for j=1:nv;
VItimeseries(:,j)=rand(d,1); % Final matrix with vectors
end

%% script to calculate the cumulative variance in the columns of my matrix
VectorVarianza=0;
VectoFinalVar=0;
VectorFinalTotalVAriances=zeros(d,nv);
    for k=1:nv %number of columns
    for j=1:numel(VItimeseries(:,k)) %size of the rows
        Vector=VItimeseries(:,k);       
        VectorVarianza(1:j)= Vector(1:j); % Vector to calculate the variance...
        ...Independently
        VectorFinalVar(j,k)= var(VectorVarianza);%Calculation of variances

    end
    VectorFinalTotalVAriances(:,k)=VectorFinalVar(:,k)% construction of the...
    ...Final Vector with the cumulative variances
end

1 Ответ

2 голосов
/ 14 октября 2019

Цикл по элементам n в x и в цикле, вычисляющем дисперсию всех элементов до i с использованием var(x(1:i)), составляет алгоритм O (n 2 ). Это дорого по своей природе.

Выборочная дисперсия (которую вычисляет var) определяется как sum((x-mean(x)).^2) / (n-1), с n = length(x). Это может быть переписано как (sum(x.^2) - sum(x).^2 / n) / (n-1). Эта формула позволяет нам накапливать sum(x) и sum(x.^2) в одном цикле, а затем вычислять дисперсию. Это также позволяет нам вычислить кумулятивную дисперсию в O (n).

Для вектора x, у нас будет следующий цикл:

x = randn(100,1); % some data

v = zeros(size(x)); % cumulative variance
s = x(1);           % running sum of x
s2 = x(1).^2;       % running sum of square of x
for ii = 2:numel(x) % loop starts at 2, for ii=1 we cannot compute variance
   s = s + x(ii);
   s2 = s2 + x(ii).^2;
   v(ii) = (s2 - s.^2 / ii) / (ii-1);
end

Мы можем избежать явногоцикл с использованием cumsum:

s = cumsum(x);
s2 = cumsum(x.^2);
n = (1:numel(x)).';
v = (s2 - s.^2 ./ n) ./ (n-1); % v(1) will be NaN, rather than 0 as in the first version
v(1) = 0;                      % so we set it to 0 explicitly here

Код в OP вычисляет кумулятивную дисперсию для каждого столбца матрицы. Приведенный выше код может быть тривиально адаптирован для того же:

s = cumsum(VItimeseries,1);     % cumulative sum explicitly along columns
s2 = cumsum(VItimeseries.^2,1);
n = (1:size(VItimeseries,1)).'; % use number of rows, rather than `numel`.
v = (s2 - s.^2 ./ n) ./ (n-1);
v(1,:) = 0;                     % fill first row with zeros, not just first element
...