矩阵形式MATLAB中的正切相关计算
考虑以下在for循环中执行的切线相关性计算矩阵形式MATLAB中的正切相关计算,matlab,matrix-multiplication,Matlab,Matrix Multiplication,考虑以下在for循环中执行的切线相关性计算 v1=rand(25,1); v2=rand(25,1); n=25; nSteps=10; mean_theta = zeros(nSteps,1); for j=1:nSteps theta=[]; for i=1:(n-j) d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]); n1 = norm([v1(i) v2(i)]); n2 = norm([v
v1=rand(25,1);
v2=rand(25,1);
n=25;
nSteps=10;
mean_theta = zeros(nSteps,1);
for j=1:nSteps
theta=[];
for i=1:(n-j)
d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
n1 = norm([v1(i) v2(i)]);
n2 = norm([v1(i+j) v2(i+j)]);
theta = [theta acosd(d/n1/n2)];
end
mean_theta(j)=mean(theta);
end
plot(mean_theta)
如何利用matlab矩阵计算来提高性能?您可以做一些事情来加快代码的速度。首先,永远。这将转换为:
theta = [];
for i = 1:(n-j)
%...
theta = [theta acosd(d/n1/n2)];
end
进入:
接下来,将规范化从循环中移出。无需反复规范化,只需规范化输入:
v = [v1,v2];
v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
%...
theta(i) = acosd(dot(v(i,:),v(i+j,:)));
在数值精度范围内,这对输出的影响非常小,因为不同的操作顺序会导致不同的浮点舍入误差
最后,可以通过矢量化该计算来删除内部循环:
i = 1:(n-j);
theta = acosd(dot(v(i,:),v(i+j,:),2));
计时(n=25
):
- 原件:0.0019 s
- 预分配:0.0013秒
- 正常化一次:0.0011s
- 矢量化:1.4176e-04 s
n=250
):
- 原件:0.0185 s
- 预分配:0.0146秒
- 正常化一次:0.0118秒
- 矢量化:2.5694e-04 s
n
线性增长的代码
定时代码:
function so
n = 25;
v1 = rand(n,1);
v2 = rand(n,1);
nSteps = 10;
mean_theta1 = method1(v1,v2,nSteps);
mean_theta2 = method2(v1,v2,nSteps);
fprintf('diff method1 vs method2: %g\n',max(abs(mean_theta1(:)-mean_theta2(:))));
mean_theta3 = method3(v1,v2,nSteps);
fprintf('diff method1 vs method3: %g\n',max(abs(mean_theta1(:)-mean_theta3(:))));
mean_theta4 = method4(v1,v2,nSteps);
fprintf('diff method1 vs method4: %g\n',max(abs(mean_theta1(:)-mean_theta4(:))));
timeit(@()method1(v1,v2,nSteps))
timeit(@()method2(v1,v2,nSteps))
timeit(@()method3(v1,v2,nSteps))
timeit(@()method4(v1,v2,nSteps))
function mean_theta = method1(v1,v2,nSteps)
n = numel(v1);
mean_theta = zeros(nSteps,1);
for j = 1:nSteps
theta=[];
for i=1:(n-j)
d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
n1 = norm([v1(i) v2(i)]);
n2 = norm([v1(i+j) v2(i+j)]);
theta = [theta acosd(d/n1/n2)];
end
mean_theta(j) = mean(theta);
end
function mean_theta = method2(v1,v2,nSteps)
n = numel(v1);
mean_theta = zeros(nSteps,1);
for j = 1:nSteps
theta = zeros(1,n-j);
for i = 1:(n-j)
d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
n1 = norm([v1(i) v2(i)]);
n2 = norm([v1(i+j) v2(i+j)]);
theta(i) = acosd(d/n1/n2);
end
mean_theta(j) = mean(theta);
end
function mean_theta = method3(v1,v2,nSteps)
v = [v1,v2];
v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
n = numel(v1);
mean_theta = zeros(nSteps,1);
for j = 1:nSteps
theta = zeros(1,n-j);
for i = 1:(n-j)
theta(i) = acosd(dot(v(i,:),v(i+j,:)));
end
mean_theta(j) = mean(theta);
end
function mean_theta = method4(v1,v2,nSteps)
v = [v1,v2];
v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
n = numel(v1);
mean_theta = zeros(nSteps,1);
for j = 1:nSteps
i = 1:(n-j);
theta = acosd(dot(v(i,:),v(i+j,:),2));
mean_theta(j) = mean(theta);
end
以下是一个完整的矢量化解决方案:
i = 1:n-1;
j = (1:nSteps).';
ij= min(i+j,n);
a = cat(3, v1(i).', v2(i).');
b = cat(3, v1(ij), v2(ij));
d = sum(a .* b, 3);
n1 = sum(a .^ 2, 3);
n2 = sum(b .^ 2, 3);
theta = acosd(d./sqrt(n1.*n2));
idx = (1:nSteps).' <= (n-1:-1:1);
mean_theta = sum(theta .* idx ,2) ./ sum(idx,2);
你有计量经济学工具箱吗?如果是这样,您可以查看计算自相关性的
autocorr
。您应该能够调整它以计算切线相关性。当我说adapt时,我的意思是创建一个新的类似函数,而不是改变现有的函数。对于初学者来说,不断增长的数组,就像你使用theta
那样,对MATLAB的性能非常非常不利。只需将其预先分配到正确的大小(在本例中,这是已知的,尽管每次迭代都是可变的),您就可以节省大量时间了。@NickyMattsson,我想继续使用matlab提供的没有工具箱的功能。@Adriaan,如果你能给出一个答案,说明我的例子对matlab有什么坏处,以及你打算如何以不同的方式编写它,那将是非常好的,而且也将有利于其他人。@jarhead,请参阅。我不打算写一个答案,因为预分配在我看来太明显了,因为它应该一直这样做。没有价值。
i = 1:n-1;
j = (1:nSteps).';
ij= min(i+j,n);
a = cat(3, v1(i).', v2(i).');
b = cat(3, v1(ij), v2(ij));
d = sum(a .* b, 3);
n1 = sum(a .^ 2, 3);
n2 = sum(b .^ 2, 3);
theta = acosd(d./sqrt(n1.*n2));
idx = (1:nSteps).' <= (n-1:-1:1);
mean_theta = sum(theta .* idx ,2) ./ sum(idx,2);
Full vectorized : 0.000864983 seconds
Method4(Vectorize) : 0.002774 seconds
Original(loop) : 0.340693 seconds