Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Matlab 计算张量的有效方法_Matlab_Tensor - Fatal编程技术网

Matlab 计算张量的有效方法

Matlab 计算张量的有效方法,matlab,tensor,Matlab,Tensor,假设c是一个d维向量。我想计算以下三阶张量 其中,e_i表示欧几里德空间的ith标准基。有没有一种有效的计算方法?我使用以下for loop和Kruskal张量ktensor来计算它,使用Sandia国家实验室管理的: x=ktensor({c,c,c}); I=eye(d); for i=1:d x=x+2*c(i)*ktensor({I(:,i),I(:,i),I(:,i)} end for i=1:d for j=1:d x=x- c(i)*c(j

假设
c
是一个d维向量。我想计算以下三阶张量

其中,
e_i
表示欧几里德空间的
i
th标准基。有没有一种有效的计算方法?我使用以下for loop和Kruskal张量
ktensor
来计算它,使用Sandia国家实验室管理的:

x=ktensor({c,c,c});
I=eye(d);

for i=1:d
    x=x+2*c(i)*ktensor({I(:,i),I(:,i),I(:,i)}
end

for i=1:d
    for j=1:d

         x=x- c(i)*c(j)*(ktensor({I(:,i),I(:,i),I(:,j)})+ktensor({I(:,i),I(:,j),I(:,i)})+ktensor({I(:,i),I(:,j),I(:,j)}))


    end
end
这是一种可能性

  • 我对第二项进行了优化,因为它将
    c
    的值沿张量的“对角线”放置
  • 对于第一项,没有太多的优化空间,因为它是一个密集乘法,所以
    bsxfun
    似乎是合适的
  • 对于第三个术语,我坚持使用
    bsxfun
    ,但是由于结果有些稀疏,如果矩阵的大小很大,您可能会受益于“手动”填充它
代码如下:

dim = 10;
c = [1:dim]';
e = eye(dim);

x = zeros([dim, dim, dim]);
% initialize with second term
x(1:dim*(dim+1)+1:end) = 2 * c;
% add first term
x = x + bsxfun(@times, bsxfun(@times, c, shiftdim(c, -1)), shiftdim(c, -2));
% add third term
x = x - sum(sum(bsxfun(@times, shiftdim(c*c',-3), ...
   bsxfun(@times, bsxfun(@times, permute(e, [1, 3, 4, 2, 5]), permute(e, [3, 1, 4, 2, 5])), permute(e, [3, 4, 1, 5, 2])) +...
   bsxfun(@times, bsxfun(@times, permute(e, [1, 3, 4, 2, 5]), permute(e, [3, 1, 4, 5, 2])), permute(e, [3, 4, 1, 2, 5])) +...
   bsxfun(@times, bsxfun(@times, permute(e, [1, 3, 4, 5, 2]), permute(e, [3, 1, 4, 2, 5])), permute(e, [3, 4, 1, 2, 5]))), 5), 4);
编辑

对第三项进行更有效(特别是记忆方面)的计算:

ec = bsxfun(@times, e, c);
x  = x - ...
  bsxfun(@times, ec, shiftdim(c, -2)) -...
  bsxfun(@times, c', reshape(ec, [dim, 1, dim])) -....
  bsxfun(@times, c, reshape(ec, [1, dim, dim]));
你可以试试这个循环

它只是在单独的线程中运行未接触的
ktensor
命令,因此工具箱负责并行运行代码

由于每个迭代的独立性,这意味着,例如,
c{i+1,j+1}
不依赖于
c{i,j}
,这是可能的


根据系统的内核(和超线程)数量,可能会有多达#个内核的加速次数

你可以试试并行计算工具箱(又称parfor)。由于不同的
i
j
索引之间没有依赖关系,您可以并行计算求和中的每个项。@Yvon:parfor修改后的代码是什么样子的?它比上面的要快得多吗?我猜可能是$d vs ^2$加速之类的。我马上给你一个示例代码。它并没有优化代码,只是让cpu在一个单独的线程上运行每次迭代,这样就可以同时完成初始化为零,但在for循环中它存储了一个完整的张量?@pikachuchameleon oops@pikachuchameleon,所以我从他们的网页上获得了一点知识,但实际上没有得到代码。变量
x
在您的工作区中的维度是多少?什么是
d
x
是一个
d*d*d
张量,
d
是一个自然数。假设你有一个张量
T=a*a*a+b*b*b
,那么语法
T=k传感器({[a,b],[a,b],[a,b]}
的作用完全相同,它代表Kruskal张量。编辑的答案。
x
应该是一个d x d x d矩阵,
y
在前三个下标中包含
x
的所有维度,然后是循环的第四个维度。
z
的作用相同,但包含两个循环索引。很好,编辑的解决方案是与我的方法相比,速度明显加快!
x=ktensor({c,c,c});
I=eye(d);

y = zeros(d,d,d, d);
parfor i=1:d
    y(:,:,:, i) = 2*c(i)*ktensor({I(:,i),I(:,i),I(:,i)};
end
x = x + sum(y, 4);

z = zeros(d,d,d, d,d);
parfor i=1:d
    for j=1:d % only one layer of parallelization is allowed
         z(:,:,:, i,j) = c(i)*c(j)*(ktensor({I(:,i),I(:,i),I(:,j)})+ktensor({I(:,i),I(:,j),I(:,i)})+ktensor({I(:,i),I(:,j),I(:,j)}));
    end
end
x = x - sum(sum(z, 5), 4);
x % is your result