├── Frontal2Lateral.m ├── Lateral2Frontal.m ├── PSNR.m ├── README.md ├── RandOrthMat.m ├── demo_image_inpainting.m ├── demo_ltrc_tnn_transform.m ├── demo_trpca_tnn_transform.m ├── inverselineartransform.m ├── lineartransform.m ├── lrtc_tnn.m ├── prox_l1.m ├── prox_tnn.m ├── testimage.jpg ├── tmprod.m ├── tprod.m ├── trpca_tnn.m └── tubalrank.m /Frontal2Lateral.m: -------------------------------------------------------------------------------- 1 | function Y = Frontal2Lateral(X) 2 | 3 | % Convert the frontal slices of a tensor to the lateral slices of a new tensor 4 | % 5 | % version 1.0 - 11/02/2018 6 | % 7 | % Written by Canyi Lu (canyilu@gmail.com) 8 | % 9 | 10 | [n1,n2,n3] = size(X); 11 | Y = zeros(n1,n3,n2); 12 | 13 | for i = 1 : n2 14 | Z = squeeze(X(:,i,:)); 15 | Y(:,:,i) = Z; 16 | end 17 | -------------------------------------------------------------------------------- /Lateral2Frontal.m: -------------------------------------------------------------------------------- 1 | function B = Lateral2Frontal(A) 2 | % 3 | % Written by Canyi Lu (canyilu@gmail.com) 4 | % 5 | [n1,n3,n2] = size(A); 6 | B = zeros(n1,n2,n3); 7 | for i = 1 : n3 8 | slice = A(:,i,:); 9 | B(:,:,i) = reshape(slice,n1,n2); 10 | end 11 | -------------------------------------------------------------------------------- /PSNR.m: -------------------------------------------------------------------------------- 1 | function psnr = PSNR(Xfull,Xrecover,maxP) 2 | % 3 | % Written by Canyi Lu (canyilu@gmail.com) 4 | % 5 | Xrecover = max(0,Xrecover); 6 | Xrecover = min(maxP,Xrecover); 7 | [n1,n2,n3] = size(Xrecover); 8 | MSE = norm(Xfull(:)-Xrecover(:))^2/(n1*n2*n3); 9 | psnr = 10*log10(maxP^2/MSE); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tensor robust PCA (TRPCA) and tensor completion based on tensor nuclear norm under linear transform 2 | 3 | ### Introduction 4 | 5 | In [1], we propose a new tensor nuclear norm induced by the tensor-tensor product (t-product) [2] and apply it to tensor robust PCA (TRPCA) with exact recovery guarantee in theory. We also apply this tensor nuclear norm for tensor completion and provide the theoretical recovery guarantee in [3]. The original t-product [2] uses the discrete Fourier transform and uses the fast Fourier transform (FFT) for efficient computing. It is further generlaized to the t-product under arbitrary invertible linear transform in [4]. 6 | 7 | In [5], we show that if the linear transform satisfies where , then we can define a more general tensor nuclear norm induced by the t-product under this linear transform. We then apply this generalized tensor nuclear norm for tensor completion [5] and tensor robust PCA (TRPCA) [6] under linear transform and provide the exact recovery guarantee in theory. Intuitively, our works, [5] and [6], can be regarded as extensions of our former work [3] and [1], respectively. Howver, we restrict the linear transform to be a real matrix in [5][6] whie [3][1] uses the complex discrete Fourier transform. This makes some key differences in the proofs of the recovery guarantee. 8 | 9 | We provide the codes for the following models: 10 |
    11 |
  1. Tensor completion based on tensor nuclear norm under linear transform [5]
    12 | 13 | 14 | 15 | 16 |
  2. Tensor robust PCA (TRPCA) based on tensor nuclear norm under linear transform [6]
    17 | 18 | 19 |
20 | 21 | 22 | ### Related Toolboxes 23 | 29 | 30 | 31 | ### References 32 |
    33 |
  1. Canyi Lu, Jiashi Feng, Yudong Chen, Wei Liu, Zhouchen Lin, Shuicheng Yan. Tensor Robust Principal Component Analysis with A New Tensor Nuclear Norm. TPAMI. 2019 34 | 35 |
  2. Misha E.Kilmer, Carla D. Martin. Factorization strategies for third-order tensors. Linear Algebra and its Applications, 435(3):641–658, 2011 36 | 37 |
  3. Canyi Lu, Jiashi Feng, Zhouchen Lin, Shuicheng Yan. Exact Low Tubal Rank Tensor Recovery from Gaussian Measurements. International Joint Conference on Artificial Intelligence (IJCAI). 2018 38 | 39 |
  4. Eric Kernfeld, Misha Kilmer, Shuchin Aeron. Tensor-Tensor Products with Invertible Linear Transforms. Linear Algebra and its Applications. 2015. 40 | 41 |
  5. Canyi Lu, Xi Peng, Yunchao Wei. Low-Rank Tensor Completion With a New Tensor Nuclear Norm Induced by Invertible Linear Transforms. IEEE International Conference on Computer Vision and Pattern Recognition (CVPR), 2019 42 | 43 |
  6. Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 44 | 45 |
  7. Canyi Lu, Jiashi Feng, Yudong Chen, Wei Liu, Zhouchen Lin, Shuicheng Yan. Tensor Robust Principal Component Analysis: Exact Recovery of Corrupted Low-Rank Tensors via Convex Optimization. CVPR, 2016 46 |
47 | -------------------------------------------------------------------------------- /RandOrthMat.m: -------------------------------------------------------------------------------- 1 | function M=RandOrthMat(n, tol) 2 | % M = RANDORTHMAT(n) 3 | % generates a random n x n orthogonal real matrix. 4 | % 5 | % M = RANDORTHMAT(n,tol) 6 | % explicitly specifies a thresh value that measures linear dependence 7 | % of a newly formed column with the existing columns. Defaults to 1e-6. 8 | % 9 | % In this version the generated matrix distribution *is* uniform over the manifold 10 | % O(n) w.r.t. the induced R^(n^2) Lebesgue measure, at a slight computational 11 | % overhead (randn + normalization, as opposed to rand ). 12 | % 13 | % (c) Ofek Shilon , 2006. 14 | 15 | 16 | if nargin==1 17 | tol=1e-6; 18 | end 19 | 20 | M = zeros(n); % prealloc 21 | 22 | % gram-schmidt on random column vectors 23 | 24 | vi = randn(n,1); 25 | % the n-dimensional normal distribution has spherical symmetry, which implies 26 | % that after normalization the drawn vectors would be uniformly distributed on the 27 | % n-dimensional unit sphere. 28 | 29 | M(:,1) = vi ./ norm(vi); 30 | 31 | for i=2:n 32 | nrm = 0; 33 | while nrm0. 17 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 18 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 19 | % 20 | % 21 | % Examples: 22 | % n = 10; A = rand(n,n,n); A = inverselineartransform(A,transform); 23 | % Here transform is defined below: 24 | % 25 | % - linear transform as the funtion handle: 26 | % (1) fft: transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 27 | % A = inverselineartransform(A,transform) is equivalent to A = ifft(A,[],3); 28 | % (2) dct: transform.L = @dct, transform.l = 1, transform.inverseL = @idct. 29 | % A = inverselineartransform(A,transform) is equivalent to A = idct(A,[],3); 30 | % - linear transform as the invertible matrix: transform.L = L, transform.l = l, transform.inverseL = inverseL, where 31 | % (1) matrix corresponding to discrete Fourier transform (equivalent to fft): L = dftmtx(n3); l = n3; inverseL = L'/l; 32 | % (2) matrix corresponding to discrete cosine transform (equivalent to dct): L = dct(eye(n3)); l = 1; inverseL = L'; 33 | % (3) random orthogonal real matrix: L = RandOrthMat(n3); l = 1; inverseL = L'; 34 | % (4) any invertible matrix, i.e., L = randn(n3); l = -1; inverseL = inv(L); 35 | % 36 | % 37 | % 38 | % See also lineartransform 39 | % 40 | % 41 | % References: 42 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 43 | % June, 2018. https://github.com/canyilu/tproduct. 44 | % 45 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 46 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 47 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 48 | % 49 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 50 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 51 | % 52 | % 53 | % version 1.0 - 01/02/2019 54 | % version 1.1 - 29/04/2021 55 | % 56 | % Written by Canyi Lu (canyilu@gmail.com) 57 | % 58 | 59 | if nargin < 2 60 | A = ifft(A,[],3); % fft is the default transform 61 | elseif isa(transform.L,'function_handle') 62 | A = transform.inverseL(A,[],3); 63 | elseif ismatrix(transform.L) 64 | n3 = size(A,3); 65 | [l1,l2] = size(transform.L); 66 | if l1 ~= l2 || l1 ~= n3 67 | error('Inner tensor dimensions must agree.'); 68 | end 69 | if transform.l > 0 70 | % property L'*L=L*L'=l*I, for some l>0, holds. Then, inv(L)=L'/l 71 | A = tmprod(A,transform.L'/transform.l,3); 72 | else 73 | % arbitrary invertible matrix without the above property 74 | if isfield(transform,'inverseL') 75 | A = tmprod(A,transform.inverseL,3); 76 | else 77 | A = tmprod(A,inv(transform.L),3); 78 | end 79 | end 80 | end 81 | 82 | -------------------------------------------------------------------------------- /lineartransform.m: -------------------------------------------------------------------------------- 1 | function A = lineartransform(A,transform) 2 | 3 | % perform linear transform on tensor A along 3rd dim 4 | % 5 | % A - n1*n2*n3 tensor 6 | % transform - a structure which defines the linear transform 7 | % transform.L: the linear transform of two types: 8 | % - type I: function handle, i.e., @fft, @dct 9 | % - type II: invertible matrix of size n3*n3 10 | % 11 | % transform.inverseL: the inverse linear transform of transform.L 12 | % - type I: function handle, i.e., @ifft, @idct 13 | % - type II: inverse matrix of transform.L 14 | % 15 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 16 | % L'*L=L*L'=l*I, for some l>0. 17 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 18 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 19 | % 20 | % 21 | % Examples: 22 | % n = 10; A = rand(n,n,n); A = lineartransform(A,transform); 23 | % Here transform is defined below: 24 | % 25 | % - linear transform as the funtion handle: 26 | % (1) fft: transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 27 | % A = lineartransform(A,transform) is equivalent to A = fft(A,[],3); 28 | % (2) dct: transform.L = @dct, transform.l = 1, transform.inverseL = @idct. 29 | % A = lineartransform(A,transform) is equivalent to A = dct(A,[],3); 30 | % - linear transform as the invertible matrix: transform.L = L, transform.l = l, transform.inverseL = inverseL, where 31 | % (1) matrix corresponding to discrete Fourier transform (equivalent to fft): L = dftmtx(n3); l = n3; inverseL = L'/l; 32 | % (2) matrix corresponding to discrete cosine transform (equivalent to dct): L = dct(eye(n3)); l = 1; inverseL = L'; 33 | % (3) random orthogonal real matrix: L = RandOrthMat(n3); l = 1; inverseL = L'; 34 | % (4) any invertible matrix, i.e., L = randn(n3); l = -1; inverseL = inv(L); 35 | % 36 | % 37 | % 38 | % See also inverselineartransform 39 | % 40 | % 41 | % References: 42 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 43 | % June, 2018. https://github.com/canyilu/tproduct. 44 | % 45 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 46 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 47 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 48 | % 49 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 50 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 51 | % 52 | % 53 | % version 1.0 - 01/02/2019 54 | % version 1.1 - 29/04/2021 55 | % 56 | % Written by Canyi Lu (canyilu@gmail.com) 57 | % 58 | 59 | if nargin < 2 60 | A = fft(A,[],3); % fft is the default transform 61 | elseif isa(transform.L,'function_handle') 62 | A = transform.L(A,[],3); 63 | elseif ismatrix(transform.L) 64 | n3 = size(A,3); 65 | [l1,l2] = size(transform.L); 66 | if l1 ~= l2 || l1 ~= n3 67 | error('Inner tensor dimensions must agree.'); 68 | end 69 | A = tmprod(A,transform.L,3); 70 | end 71 | -------------------------------------------------------------------------------- /lrtc_tnn.m: -------------------------------------------------------------------------------- 1 | function [X,obj,err,iter] = lrtc_tnn(M,omega,transform,opts) 2 | 3 | % Low-Rank Tensor Completion (LRTC) based on Tensor Nuclear Norm 4 | % (TNN) under linear transform 5 | % 6 | % min_X ||X||_*, s.t. P_Omega(X) = P_Omega(M) 7 | % 8 | % --------------------------------------------- 9 | % Input: 10 | % M - d1*d2*d3 tensor 11 | % L - d3*d3 matrix, L'*L=L*L'=l*I, l>0 12 | % omega - index of the observed entries 13 | % opts - Structure value in Matlab. The fields are 14 | % opts.tol - termination tolerance 15 | % opts.max_iter - maximum number of iterations 16 | % opts.mu - stepsize for dual variable updating in ADMM 17 | % opts.max_mu - maximum stepsize 18 | % opts.rho - rho>=1, ratio used to increase mu 19 | % opts.DEBUG - 0 or 1 20 | % 21 | % transform - a structure which defines the linear transform 22 | % transform.L: the linear transform of two types: 23 | % - type I: function handle, i.e., @fft, @dct 24 | % - type II: invertible matrix of size n3*n3 25 | % 26 | % transform.inverseL: the inverse linear transform of transform.L 27 | % - type I: function handle, i.e., @ifft, @idct 28 | % - type II: inverse matrix of transform.L 29 | % 30 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 31 | % L'*L=L*L'=l*I, for some l>0. 32 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 33 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 34 | % 35 | % 36 | % 37 | % Output: 38 | % X - d1*d2*d3 tensor 39 | % err - residual 40 | % obj - objective function value 41 | % iter - number of iterations 42 | % 43 | % version 1.0 - 01/02/2019 44 | % version 1.1 - 29/04/2021 45 | % 46 | % Written by Canyi Lu (canyilu@gmail.com) 47 | % 48 | % References: 49 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 50 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 51 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 52 | % 53 | 54 | tol = 1e-8; 55 | max_iter = 500; 56 | rho = 1.1; 57 | mu = 1e-4; 58 | max_mu = 1e10; 59 | DEBUG = 0; 60 | 61 | if nargin < 3 62 | % fft is the default transform 63 | transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 64 | end 65 | 66 | if ~exist('opts', 'var') 67 | opts = []; 68 | end 69 | if isfield(opts, 'tol'); tol = opts.tol; end 70 | if isfield(opts, 'max_iter'); max_iter = opts.max_iter; end 71 | if isfield(opts, 'rho'); rho = opts.rho; end 72 | if isfield(opts, 'mu'); mu = opts.mu; end 73 | if isfield(opts, 'max_mu'); max_mu = opts.max_mu; end 74 | if isfield(opts, 'DEBUG'); DEBUG = opts.DEBUG; end 75 | 76 | dim = size(M); 77 | X = zeros(dim); 78 | X(omega) = M(omega); 79 | E = zeros(dim); 80 | Y = E; 81 | 82 | for iter = 1 : max_iter 83 | Xk = X; 84 | Ek = E; 85 | % update X 86 | [X,tnnX] = prox_tnn(-E+M+Y/mu,1/mu,transform); 87 | % update E 88 | E = M-X+Y/mu; 89 | E(omega) = 0; 90 | 91 | dY = M-X-E; 92 | chgX = max(abs(Xk(:)-X(:))); 93 | chgE = max(abs(Ek(:)-E(:))); 94 | chg = max([chgX chgE max(abs(dY(:)))]); 95 | if DEBUG 96 | if iter == 1 || mod(iter, 10) == 0 97 | obj = tnnX; 98 | err = norm(dY(:)); 99 | disp(['iter ' num2str(iter) ', mu=' num2str(mu) ... 100 | ', obj=' num2str(obj) ', err=' num2str(err)]); 101 | end 102 | end 103 | 104 | if chg < tol 105 | break; 106 | end 107 | Y = Y + mu*dY; 108 | mu = min(rho*mu,max_mu); 109 | end 110 | obj = tnnX; 111 | err = norm(dY(:)); 112 | 113 | -------------------------------------------------------------------------------- /prox_l1.m: -------------------------------------------------------------------------------- 1 | function x = prox_l1(b,lambda) 2 | x = max(0,b-lambda)+min(0,b+lambda); -------------------------------------------------------------------------------- /prox_tnn.m: -------------------------------------------------------------------------------- 1 | function [X, tnn] = prox_tnn(Y,rho,transform) 2 | 3 | % Tensor singular value thresholding (TSVT) which solves the following 4 | % problem (the proximal operator of the tensor nuclear norm under linear transform) 5 | % 6 | % min_X rho*||X||_*+0.5*||X-Y||_F^2 7 | % 8 | % An error message is printed if the property L'*L=L*L'=l*I, for some l>0, 9 | % of the linear transform does not hold. 10 | % 11 | % 12 | % Input: 13 | % Y - n1*n2*n3 tensor 14 | % rho - a constant > 0 15 | % transform - a structure which defines the linear transform 16 | % transform.L: the linear transform of two types: 17 | % - type I: function handle, i.e., @fft, @dct 18 | % - type II: invertible matrix of size n3*n3 19 | % 20 | % transform.inverseL: the inverse linear transform of transform.L 21 | % - type I: function handle, i.e., @ifft, @idct 22 | % - type II: inverse matrix of transform.L 23 | % 24 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 25 | % L'*L=L*L'=l*I, for some l>0. 26 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 27 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 28 | % If not specified, fft is the default transform, i.e., 29 | % transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 30 | % 31 | % 32 | % Output: 33 | % X - the solution of tensor singular value thresholding 34 | % tnn - tensor nuclear norm of X 35 | % 36 | % 37 | % 38 | % See also tnn, tsvd, lineartransform, inverselineartransform 39 | % 40 | % 41 | % References: 42 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 43 | % June, 2018. https://github.com/canyilu/tproduct. 44 | % 45 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 46 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 47 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 48 | % 49 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 50 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 51 | % 52 | % 53 | % version 1.0 - 01/02/2019 54 | % version 1.1 - 29/04/2021 55 | % 56 | % Written by Canyi Lu (canyilu@gmail.com) 57 | % 58 | 59 | [n1,n2,n3] = size(Y); 60 | if nargin == 3 61 | if transform.l < 0 62 | error("property L'*L=L*L'=l*I does not holds for some l>0."); 63 | end 64 | else 65 | % fft is the default transform 66 | transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 67 | end 68 | 69 | X = zeros(n1,n2,n3); 70 | tnn = 0; 71 | if isequal(transform.L,@fft) 72 | % efficient computing for fft transform 73 | Y = fft(Y,[],3); 74 | % first frontal slice 75 | [U,S,V] = svd(Y(:,:,1),'econ'); 76 | S = diag(S); 77 | r = length(find(S>rho)); 78 | if r >= 1 79 | S = S(1:r)-rho; 80 | X(:,:,1) = U(:,1:r)*diag(S)*V(:,1:r)'; 81 | end 82 | tnn = tnn+sum(S); 83 | % i=2,...,halfn3 84 | halfn3 = round(n3/2); 85 | for i = 2 : halfn3 86 | [U,S,V] = svd(Y(:,:,i),'econ'); 87 | S = diag(S); 88 | r = length(find(S>rho)); 89 | if r >= 1 90 | S = S(1:r)-rho; 91 | X(:,:,i) = U(:,1:r)*diag(S)*V(:,1:r)'; 92 | end 93 | X(:,:,n3+2-i) = conj(X(:,:,i)); 94 | tnn = tnn+sum(S)*2; 95 | end 96 | % if n3 is even 97 | if mod(n3,2) == 0 98 | i = halfn3+1; 99 | [U,S,V] = svd(Y(:,:,i),'econ'); 100 | S = diag(S); 101 | r = length(find(S>rho)); 102 | if r >= 1 103 | S = S(1:r)-rho; 104 | X(:,:,i) = U(:,1:r)*diag(S)*V(:,1:r)'; 105 | end 106 | tnn = tnn+sum(S); 107 | end 108 | tnn = tnn/n3; 109 | X = ifft(X,[],3); 110 | else 111 | % other transform 112 | Y = lineartransform(Y,transform); 113 | for i = 1 : n3 114 | [U,S,V] = svd(Y(:,:,i),'econ'); 115 | S = diag(S); 116 | r = length(find(S>rho)); 117 | if r >= 1 118 | S = S(1:r)-rho; 119 | X(:,:,i) = U(:,1:r)*diag(S)*V(:,1:r)'; 120 | tnn = tnn+sum(S); 121 | end 122 | end 123 | tnn = tnn/transform.l; 124 | X = inverselineartransform(X,transform); 125 | end 126 | -------------------------------------------------------------------------------- /testimage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/canyilu/Tensor-robust-PCA-and-tensor-completion-under-linear-transform/af3e774f549d40c99fcb5cb460ca4caec3b3a717/testimage.jpg -------------------------------------------------------------------------------- /tmprod.m: -------------------------------------------------------------------------------- 1 | function [S,iperm] = tmprod(T,U,mode,transpose,saveperm) 2 | %TMPROD Mode-n tensor-matrix product. 3 | % S = tmprod(T,U,mode) computes the tensor-matrix product of the tensor T 4 | % with the matrices U{1}, ..., U{N} along the modes mode(1), ..., 5 | % mode(N), respectively. Note that in this implementation, the vector 6 | % mode should contain distinct integers. The mode-n tensor-matrix 7 | % products are computed sequentially in a heuristically determined order. 8 | % A mode-n tensor-matrix product results in a new tensor S in which the 9 | % mode-n vectors of a given tensor T are premultiplied by a given matrix 10 | % U{n}, i.e., tens2mat(S,mode(n)) = U{n}*tens2mat(T,mode(n)). 11 | % 12 | % S = tmprod(T,U,mode,'T') and tmprod(T,U,mode,'H') apply the mode-n 13 | % tensor-matrix product using the transposed matrices U{n}.' and 14 | % conjugate transposed matrices U{n}' respectively along mode(n). 15 | % 16 | % [S,iperm] = tmprod(T,U,mode) and S = tmprod(T,U,mode,'saveperm') save 17 | % one permutation operation. In the former case, the tensor-matrix 18 | % product can then be recovered by permute(S,iperm). 19 | % 20 | % See also tens2mat, mat2tens, contract. 21 | 22 | % Authors: Laurent Sorber (Laurent.Sorber@cs.kuleuven.be), 23 | % Nick Vannieuwenhoven (Nick.Vannieuwenhoven@cs.kuleuven.be) 24 | % Marc Van Barel (Marc.VanBarel@cs.kuleuven.be) 25 | % Lieven De Lathauwer (Lieven.DeLathauwer@kuleuven-kulak.be) 26 | 27 | % Check arguments. 28 | if nargin < 4, transpose = 0; end 29 | if nargin < 5, saveperm = false; end 30 | if ischar(saveperm), saveperm = strcmpi(saveperm,'saveperm'); end 31 | switch transpose 32 | case {'T','H'}, m = [2 1]; 33 | otherwise, m = [1 2]; if nargin < 5, saveperm = transpose; end 34 | end 35 | if ~iscell(U), U = {U}; end 36 | if length(U) ~= length(mode) 37 | error('tmprod:NumberOfProducts','length(U) should be length(mode).'); 38 | end 39 | U = U(:)'; mode = mode(:)'; 40 | size_tens = ones(1,max(mode)); 41 | size_tens(1:ndims(T)) = size(T); 42 | if any(cellfun('size',U,m(2)) ~= size_tens(mode)) 43 | error('tmprod:U','size(T,mode(n)) should be size(U{n},%i).',m(2)); 44 | end 45 | 46 | % Sort the order of the mode-n products. 47 | [~,idx] = sort(size_tens(mode)./cellfun('size',U,m(1))); 48 | mode = mode(idx); 49 | U = U(idx); 50 | 51 | % Compute the complement of the set of modes. 52 | n = length(mode); 53 | N = length(size_tens); 54 | bits = ones(1,N); 55 | bits(mode) = 0; 56 | modec = 1:N; 57 | modec = modec(logical(bits(modec))); 58 | 59 | % Prepermute the tensor. 60 | perm = [mode modec]; 61 | size_tens = size_tens(perm); 62 | S = T; if any(mode ~= 1:n), S = permute(S,perm); end 63 | 64 | % Cycle through the n-mode products. 65 | for i = 1:n 66 | size_tens(1) = size(U{i},m(1)); 67 | switch transpose 68 | case 'T' 69 | S = reshape(U{i}.'*reshape(S,size(S,1),[]),size_tens); 70 | case 'H' 71 | S = reshape(U{i}'*reshape(S,size(S,1),[]),size_tens); 72 | otherwise 73 | S = reshape(U{i}*reshape(S,size(S,1),[]),size_tens); 74 | end 75 | if i < n 76 | S = permute(S,[2:N 1]); 77 | size_tens = size_tens([2:N 1]); 78 | end 79 | end 80 | 81 | % Inverse permute the tensor, unless the user intends to do so himself. 82 | iperm(perm([n:N 1:n-1])) = 1:N; 83 | if nargout <= 1 && ~saveperm, S = permute(S,iperm); end 84 | -------------------------------------------------------------------------------- /tprod.m: -------------------------------------------------------------------------------- 1 | function C = tprod(A,B,transform) 2 | 3 | % C = tprod(A,B,transform) computes the tensor-tensor product of two 3 way tensors A and B under linear transform 4 | % 5 | % Input: 6 | % A - n1*n2*n3 tensor 7 | % B - n2*m2*n3 tensor 8 | % transform - a structure which defines the linear transform 9 | % transform.L: the linear transform of two types: 10 | % - type I: function handle, i.e., @fft, @dct 11 | % - type II: invertible matrix of size n3*n3 12 | % 13 | % transform.inverseL: the inverse linear transform of transform.L 14 | % - type I: function handle, i.e., @ifft, @idct 15 | % - type II: inverse matrix of transform.L 16 | % 17 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 18 | % L'*L=L*L'=l*I, for some l>0. 19 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 20 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 21 | % If not specified, fft is the default transform, i.e., 22 | % transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 23 | % 24 | % 25 | % Output: C - n1*m2*n3 tensor, C = A * B 26 | % 27 | % 28 | % 29 | % See also lineartransform, inverselineartransform 30 | % 31 | % 32 | % References: 33 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 34 | % June, 2018. https://github.com/canyilu/tproduct. 35 | % 36 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 37 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 38 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 39 | % 40 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 41 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 42 | % 43 | % 44 | % version 1.0 - 01/02/2019 45 | % version 1.1 - 29/04/2021 46 | % 47 | % Written by Canyi Lu (canyilu@gmail.com) 48 | % 49 | 50 | [n1,n2,n3] = size(A); 51 | [m1,m2,m3] = size(B); 52 | 53 | if n2 ~= m1 || n3 ~= m3 54 | error('Inner tensor dimensions must agree.'); 55 | end 56 | if nargin < 3 57 | % fft is the default transform 58 | transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 59 | end 60 | 61 | C = zeros(n1,m2,n3); 62 | if isequal(transform.L,@fft) 63 | % efficient computing for fft transform 64 | A = fft(A,[],3); 65 | B = fft(B,[],3); 66 | halfn3 = ceil((n3+1)/2); 67 | for i = 1 : halfn3 68 | C(:,:,i) = A(:,:,i)*B(:,:,i); 69 | end 70 | for i = halfn3+1 : n3 71 | C(:,:,i) = conj(C(:,:,n3+2-i)); 72 | end 73 | C = ifft(C,[],3); 74 | else 75 | % other transform 76 | A = lineartransform(A,transform); 77 | B = lineartransform(B,transform); 78 | for i = 1 : n3 79 | C(:,:,i) = A(:,:,i)*B(:,:,i); 80 | end 81 | C = inverselineartransform(C,transform); 82 | end 83 | -------------------------------------------------------------------------------- /trpca_tnn.m: -------------------------------------------------------------------------------- 1 | function [L,S,obj,err,iter] = trpca_tnn(X,lambda,transform,opts) 2 | 3 | % Tensor robust principal component analysis based on tensor nuclear norm 4 | % under linear transform 5 | % 6 | % min_{L,S} ||L||_*+lambda*||S||_1, s.t. X=L+S 7 | % 8 | % --------------------------------------------- 9 | % Input: 10 | % X - d1*d2*d3 tensor 11 | % T - d3*d3 matrix, T'*T=T*T'=l*I, l>0 12 | % lambda - >0, parameter 13 | % opts - Structure value in Matlab. The fields are 14 | % opts.tol - termination tolerance 15 | % opts.max_iter - maximum number of iterations 16 | % opts.mu - stepsize for dual variable updating in ADMM 17 | % opts.max_mu - maximum stepsize 18 | % opts.rho - rho>=1, ratio used to increase mu 19 | % opts.DEBUG - 0 or 1 20 | % transform - a structure which defines the linear transform 21 | % transform.L: the linear transform of two types: 22 | % - type I: function handle, i.e., @fft, @dct 23 | % - type II: invertible matrix of size n3*n3 24 | % 25 | % transform.inverseL: the inverse linear transform of transform.L 26 | % - type I: function handle, i.e., @ifft, @idct 27 | % - type II: inverse matrix of transform.L 28 | % 29 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 30 | % L'*L=L*L'=l*I, for some l>0. 31 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 32 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 33 | % 34 | % 35 | % Output: 36 | % L - d1*d2*d3 tensor 37 | % S - d1*d2*d3 tensor 38 | % obj - objective function value 39 | % err - residual 40 | % iter - number of iterations 41 | % 42 | % version 1.0 - 04/03/2019 43 | % version 1.1 - 29/04/2021 44 | % 45 | % Written by Canyi Lu (canyilu@gmail.com) 46 | % 47 | % References: 48 | % Canyi Lu, Pan Zhou, Exact recovery of tensor robust principal component 49 | % analysis under linear transforms. arXiv preprint arXiv:1907.08288, 2019 50 | % 51 | 52 | tol = 1e-8; 53 | max_iter = 500; 54 | rho = 1.1; 55 | mu = 1e-4; 56 | max_mu = 1e10; 57 | DEBUG = 0; 58 | 59 | if nargin < 3 60 | % fft is the default transform 61 | transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 62 | end 63 | 64 | if ~exist('opts', 'var') 65 | opts = []; 66 | end 67 | if isfield(opts, 'tol'); tol = opts.tol; end 68 | if isfield(opts, 'max_iter'); max_iter = opts.max_iter; end 69 | if isfield(opts, 'rho'); rho = opts.rho; end 70 | if isfield(opts, 'mu'); mu = opts.mu; end 71 | if isfield(opts, 'max_mu'); max_mu = opts.max_mu; end 72 | if isfield(opts, 'DEBUG'); DEBUG = opts.DEBUG; end 73 | 74 | dim = size(X); 75 | L = zeros(dim); 76 | S = L; 77 | Y = L; 78 | 79 | for iter = 1 : max_iter 80 | Lk = L; 81 | Sk = S; 82 | % update L 83 | [L,tnnL] = prox_tnn(-S+X-Y/mu,1/mu,transform); 84 | % L = real(L); % uncomment this line if transform dftmtx(n3) is used to avoid very small complex element 85 | 86 | % update S 87 | S = prox_l1(-L+X-Y/mu,lambda/mu); 88 | 89 | dY = L+S-X; 90 | chgL = max(abs(Lk(:)-L(:))); 91 | chgS = max(abs(Sk(:)-S(:))); 92 | chg = max([ chgL chgS max(abs(dY(:))) ]); 93 | if DEBUG 94 | if iter == 1 || mod(iter, 10) == 0 95 | obj = tnnL+lambda*norm(S(:),1); 96 | err = norm(dY(:)); 97 | disp(['iter ' num2str(iter) ', mu=' num2str(mu) ... 98 | ', obj=' num2str(obj) ', err=' num2str(err) ]); 99 | end 100 | end 101 | 102 | if chg < tol 103 | break; 104 | end 105 | Y = Y + mu*dY; 106 | mu = min(rho*mu,max_mu); 107 | end 108 | obj = tnnL+lambda*norm(S(:),1); 109 | err = norm(dY(:)); 110 | -------------------------------------------------------------------------------- /tubalrank.m: -------------------------------------------------------------------------------- 1 | function trank = tubalrank(A,transform,tol) 2 | 3 | % The tensor tubal rank of a 3 way tensor under linear transform 4 | 5 | % Input: 6 | % A - n1*n2*n3 tensor 7 | % transform - a structure which defines the linear transform 8 | % transform.L: the linear transform of two types: 9 | % - type I: function handle, i.e., @fft, @dct 10 | % - type II: invertible matrix of size n3*n3 11 | % 12 | % transform.inverseL: the inverse linear transform of transform.L 13 | % - type I: function handle, i.e., @ifft, @idct 14 | % - type II: inverse matrix of transform.L 15 | % 16 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 17 | % L'*L=L*L'=l*I, for some l>0. 18 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 19 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 20 | % If not specified, fft is the default transform, i.e., 21 | % transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 22 | % 23 | % 24 | % Output: 25 | % trank - tensor tubal rank 26 | % 27 | % 28 | % 29 | % See also tsvd, lineartransform, inverselineartransform 30 | % 31 | % 32 | % References: 33 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 34 | % June, 2018. https://github.com/canyilu/tproduct. 35 | % 36 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 37 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 38 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 39 | % 40 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 41 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 42 | % 43 | % 44 | % version 1.0 - 01/02/2019 45 | % version 1.1 - 29/04/2021 46 | % 47 | % Written by Canyi Lu (canyilu@gmail.com) 48 | % 49 | 50 | [n1,n2,n3] = size(A); 51 | if nargin < 2 52 | % fft is the default transform 53 | transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 54 | end 55 | 56 | s = zeros(min(n1,n2),1); 57 | if isequal(transform.L,@fft) 58 | % efficient computing for fft transform 59 | A = fft(A,[],3); 60 | % i=1 61 | s = svd(A(:,:,1),'econ'); 62 | % i=2,...,halfn3 63 | halfn3 = round(n3/2); 64 | for i = 2 : halfn3 65 | s = s + svd(A(:,:,i),'econ')*2; 66 | end 67 | % if n3 is even 68 | if mod(n3,2) == 0 69 | i = halfn3+1; 70 | s = s + svd(A(:,:,i),'econ'); 71 | end 72 | s = s/n3^2; 73 | if nargin < 3 74 | tol = max(n1,n2)*eps(max(s)); 75 | end 76 | trank = sum(s > tol); 77 | else 78 | % other transform 79 | A = lineartransform(A,transform); 80 | for i = 1 : n3 81 | s = s + svd(A(:,:,i),'econ'); 82 | end 83 | if transform.l > 0 84 | % property L'*L=L*L'=l*I, for some l>0, holds. 85 | s = s/n3/transform.l; 86 | else 87 | % the above property does not hold for transform L 88 | s = s/n3/norm(transform.L)^2; 89 | end 90 | if nargin < 3 91 | tol = 1e-10; 92 | end 93 | trank = sum(s > tol); 94 | end 95 | 96 | --------------------------------------------------------------------------------