matlab练习程序(三阶张量T-QR分解)
这里所谓的张量和黎曼那里的张量是不一样的,那个张量更多的用在物理上,这个张量就是矩阵的扩展。比如零阶张量就是数,一阶张量就是向量,二阶张量就是矩阵,三阶四阶就是更高维的数的集合。这个领域现在在数学上还都是很新的东西,矩阵的秩我们都知道怎么求,但是三维的张量或更高维的张量的秩现在在数学上也没有结果。至于张量的奇异值分解也只是也只是用很早的如用HOSVD来处理,我感觉这并不完全合适,新的分解算法就连老美也都没研究出来,从二维到多维的确有很多基础的理论都不适用了,像两个张量相乘这样基础的算法,现在虽然有,但我感觉也不是通用的,还要继续改进。
下面就是我看的一篇论文的张量相乘和分解方法,她的理论也可能不正确,不过这种新领域,大家都是在探索。
论文在这里:http://www.cs.tufts.edu/tech_reports/reports/2010-5/report.pdf,他主要介绍的是T-svd,T-svd分解后合成的只是原张量的一个近似结果,而T-QR就能得到一个准确的结果,所以我这里用了T-QR。以Matlab角度来看T-SVD和T-QR的代码其实是很类似的。
main.m
clear all; close all; clc; n1=3; n2=3; n3=3; A(:,:,1)=[10 23 34;43 55 63;72 85 96]; A(:,:,2)=[24 17 35;52 36 55;81 94 75]; A(:,:,3)=[65 16 52;21 47 78;92 33 43]; %A=imread('s.jpg'); D=fft(A,[],3); for i=1:n3 [q r]=qr(D(:,:,i)); %[u s v]=svd(D(:,:,i)); Q(:,:,i)=q; R(:,:,i)=r; %S(:,:,i)=s; end Q=ifft(Q,[],3); R=ifft(R,[],3); %S=ifft(S,[],3); B(:,:,1)=eye(n1,n2); B(:,:,2)=zeros(n1,n2); B(:,:,3)=zeros(n1,n2); %c=mul(mul(U,S),transpos(V)); c=mul(Q,R);
mul.m 张量相乘,论文第七页3.3的那个公式
function c=mul(a,b) [a_n1 a_n2 a_n3]=size(a); [b_n1 b_n2 b_n3]=size(b); c=zeros(a_n1,b_n2,a_n3); A=cell(a_n3,1); B=cell(b_n3,1); for i=1:a_n3 A{i}=a(:,:,i); B{i}=b(:,:,i); end index_up=zeros(1,a_n3); index_down=zeros(1,a_n3); for i=1:a_n3 index_up(i)=a_n3-i+1; index_down(i)=i; end s=cell(a_n3,a_n3); for i=1:a_n3 for j=1:a_n3 if i==j s{i,j}=A{1}; end if j>i s{i,j}=A{index_up(j-i)}; end if j<i s{i,j}=A{index_down(i-j+1)}; end end end re=cell(a_n3,1); for i=1:a_n3 re{i}=zeros(a_n1,b_n2); end for i=1:a_n3 for j=1:a_n3 for k=1:1 re{i,k}=re{i,k}+s{i,j}*B{j,k}; end end end for i=1:a_n3 c(:,:,i)=re{i}; end end
transpos.m 张量求转置,论文第十页example3.15的公式
function a=transpos(b) [n1 n2 n3]=size(b); a=zeros(n2,n1,n3); for i=1:n3 a(:,:,i)=b(:,:,i)'; end end