├── 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 | - Tensor completion based on tensor nuclear norm under linear transform [5]
12 |
13 |
14 |
15 |
16 | - 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 | - 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 |
- Misha E.Kilmer, Carla D. Martin. Factorization strategies for third-order tensors. Linear Algebra and its Applications, 435(3):641–658, 2011
36 |
37 |
- 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 |
- Eric Kernfeld, Misha Kilmer, Shuchin Aeron. Tensor-Tensor Products with Invertible Linear Transforms. Linear Algebra and its Applications. 2015.
40 |
41 |
- 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 |
- Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019
44 |
45 |
- 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 |
--------------------------------------------------------------------------------