加快Levy运动算法的模拟

Pho*_*ght 5 optimization performance matlab

这是我模拟Levy运动的小脚本:

clear all;
clc; close all;
t = 0; T = 1000; I = T-t;
dT = T/I; t = 0:dT:T; tau = T/I;
alpha = 1.5;
sigma = dT^(1/alpha);
mu = 0; beta = 0;
N = 1000;
X = zeros(N, length(I));
for k=1:N
    L = zeros(1,I);
    for i = 1:I-1
       L( (i + 1) * tau ) = L(i*tau) + stable2( alpha, beta, sigma, mu, 1);
    end
    X(k,1:length(L)) = L;
end

q = 0.1:0.1:0.9;
quant = qlines2(X, q, t(1:length(X)), tau);
hold all
for i = 1:length(quant)
    plot( t, quant(i) * t.^(1/alpha), ':k' );
end
Run Code Online (Sandbox Code Playgroud)

其中stable2返回一个给定参数的稳定随机变量(normrnd(mu, sigma)在这种情况下可以替换它,这并不重要); qlines2返回绘图所需的分位数.

但我不想在这里谈论数学.我的问题是这个实现很慢,我想加快速度.不幸的是,计算机科学不是我的主要领域 - 我听说过有关记忆,矢量化等方法的东西,还有很多其他技术,但我不知道如何使用它们.
例如,我很确定我应该以某种方式替换这个肮脏的双循环,但我不知道该怎么做.
编辑:也许我应该使用(并学习......)另一种语言(Python,C,任何功能)?我总是认为Matlab/OCTAVE是为数值计算而设计的,但如果改变了,那么对于哪一个?

fla*_*awr 4

正如你所说,关键的一点是 for 循环,Matlab 不喜欢那些,所以矢量化确实是关键字。(与预分配空间一起。

我只是稍微改变了 for 循环部分,这样您就不必L一遍又一遍地重置,而是将所有Ls 保存在一个更大的矩阵中(我也消除了该length(L)命令)。

L = zeros(N,I);
for k=1:N
    for i = 1:I-1
       L(k,(i + 1) * tau ) = L(k,i*tau) + normrnd(mu, sigma);
    end
    X(k,1:I) = L(k,1:I);
end
Run Code Online (Sandbox Code Playgroud)

现在你已经可以看到X(k,1:I) = L(k,1:I);in 循环已经过时了,这也意味着我们可以切换循环的顺序。这很重要,因为 -stepsi是递归的(取决于前一步),这意味着我们不能向量化这个循环,我们只能向量化 -loop k

现在你的原始代码在我的机器上需要 9.3 秒,新代码仍然需要大约相同的时间)

L = zeros(N,I);
for i = 1:I-1
    for k=1:N
       L(k,(i + 1) * tau ) = L(k,i*tau) + normrnd(mu, sigma);
    end
end
X = L;
Run Code Online (Sandbox Code Playgroud)

但现在我们可以应用向量化,而不是循环遍历所有行(循环k),我们可以消除此循环,并“一次”执行所有行。

L = zeros(N,I);
for i = 1:I-1
   L(:,(i + 1) * tau ) = L(:,i*tau) + normrnd(mu, sigma); %<- this is not yet what you want, see comment below
end
X = L;
Run Code Online (Sandbox Code Playgroud)

这段代码在我的机器上只需要 0.045 秒。我希望您仍然得到相同的输出,因为我不知道您在计算什么,但我也希望您能够了解如何进行矢量化代码。

PS:我刚刚注意到我们现在在整个列的最后一个示例中使用相同的随机数,这显然不是您想要的。相反,您应该生成一个完整的随机数向量,例如:

L = zeros(N,I);
for i = 1:I-1
   L(:,(i + 1) * tau ) = L(:,i*tau) + normrnd(mu, sigma,N,1);
end
X = L;
Run Code Online (Sandbox Code Playgroud)

PPS:好问题!

  • @PhotonLight 还有一件事,这段代码现在可以工作只是因为 `tau` 恰好是 1。 (2认同)