├── README.md ├── data ├── Caltech10_SURF_L10.mat ├── amazon_SURF_L10.mat ├── dslr_SURF_L10.mat └── webcam_SURF_L10.mat ├── func ├── BDA.m ├── GFK_Map.m ├── GeneralSSL.m ├── GeneralSSL3.m ├── GeneralSSL4.m ├── GraphClassifier.m ├── GraphClassifier3.m ├── GraphClassifier4.m ├── JDA.m ├── JGSA.m ├── L2_distance_1.m ├── LabelFormat.m ├── MEDA.m ├── SolveG1.m ├── SolveG2.m ├── TCA.m ├── VDA.m ├── WUDA1.m ├── WUDA2.m ├── constructKernel.m ├── constructMMD.m ├── estimate_mu.m ├── km_kernel.m ├── lapgraph.m └── select_labeled.m ├── office.m ├── runBDA.m ├── runJDA.m ├── runJGSA.m ├── runMEDA.m ├── runTCA.m └── runVDA.m /README.md: -------------------------------------------------------------------------------- 1 | # SLSA-DA 2 | This is the source code of our paper "Sparsely-Labeled Source Assisted Domain Adaptation" submitted to Pattern Recognition 3 | -------------------------------------------------------------------------------- /data/Caltech10_SURF_L10.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WWLoveTransfer/SLSA-DA/e7aa8204886b4fa9c085e7dc1f1a233ec36f83bf/data/Caltech10_SURF_L10.mat -------------------------------------------------------------------------------- /data/amazon_SURF_L10.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WWLoveTransfer/SLSA-DA/e7aa8204886b4fa9c085e7dc1f1a233ec36f83bf/data/amazon_SURF_L10.mat -------------------------------------------------------------------------------- /data/dslr_SURF_L10.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WWLoveTransfer/SLSA-DA/e7aa8204886b4fa9c085e7dc1f1a233ec36f83bf/data/dslr_SURF_L10.mat -------------------------------------------------------------------------------- /data/webcam_SURF_L10.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WWLoveTransfer/SLSA-DA/e7aa8204886b4fa9c085e7dc1f1a233ec36f83bf/data/webcam_SURF_L10.mat -------------------------------------------------------------------------------- /func/BDA.m: -------------------------------------------------------------------------------- 1 | function [acc_s,acc_t] = BDA(Xs_l,Xs_u,Xt,Ys_l,Ys_u,Yt,options) 2 | 3 | mu = options.mu; 4 | lambda = options.lambda; 5 | dim = options.dim; 6 | T = options.T; 7 | mode = options.mode; 8 | X = [Xs_l',Xs_u',Xt']; 9 | X = X*diag(sparse(1./sqrt(sum(X.^2)))); 10 | [m,n] = size(X); 11 | ns_l = size(Xs_l,1); 12 | ns_u = size(Xs_u,1); 13 | ns = ns_l+ns_u; 14 | nt = size(Xt,1); 15 | e = [1/ns*ones(ns,1);-1/nt*ones(nt,1)]; 16 | C = length(unique(Ys_l)); 17 | 18 | %% Centering matrix H 19 | H = eye(n) - 1/n * ones(n,n); 20 | %%% M0 21 | M = e * e' * C; %multiply C for better normalization 22 | 23 | knn_model = fitcknn(Xs_l,Ys_l,'NumNeighbors',1); 24 | Ys_pseudo = knn_model.predict(Xs_u); 25 | Ys_pseudo = [Ys_l;Ys_pseudo]; 26 | knn_model = fitcknn([Xs_l;Xs_u],Ys_pseudo,'NumNeighbors',1); 27 | Yt_pseudo = knn_model.predict(Xt); 28 | 29 | %% Iteration 30 | for i = 1 : T 31 | %%% Mc 32 | N = 0; 33 | if ~isempty(Yt_pseudo) && length(Yt_pseudo)==nt 34 | for c = reshape(unique(Ys_pseudo),1,C) 35 | e = zeros(n,1); 36 | if strcmp(mode,'W-BDA') 37 | Ps = length(find(Ys_pseudo==c)) / length(Ys_pseudo); 38 | Pt = length(find(Yt_pseudo == c)) / length(Yt_pseudo); 39 | alpha = Pt / Ps; 40 | mu = 1; 41 | else 42 | alpha = 1; 43 | end 44 | e(Ys_pseudo==c) = 1 / length(find(Ys_pseudo==c)); 45 | e(ns+find(Yt_pseudo==c)) = -alpha / length(find(Yt_pseudo==c)); 46 | e(isinf(e)) = 0; 47 | N = N + e*e'; 48 | end 49 | end 50 | M = (1 - mu) * M + N; 51 | M = M / norm(M,'fro'); 52 | 53 | %% Calculation 54 | [A,~] = eigs(X*M*X'+lambda*eye(m),X*H*X',dim,'SM'); 55 | Z = A'*X; 56 | 57 | %normalization for better classification performance 58 | Z = Z*diag(sparse(1./sqrt(sum(Z.^2)))); 59 | Zs_l = Z(:,1:ns_l)'; 60 | Zs_u = Z(:,ns_l+1:ns)'; 61 | Zt = Z(:,ns+1:end)'; 62 | 63 | knn_model = fitcknn(Zs_l,Ys_l,'NumNeighbors',1); 64 | Ys_pseudo = knn_model.predict(Zs_u); 65 | Ys_pseudo = [Ys_l;Ys_pseudo]; 66 | knn_model = fitcknn([Zs_l;Zs_u],Ys_pseudo,'NumNeighbors',1); 67 | Yt_pseudo = knn_model.predict(Zt); 68 | 69 | acc_s = length(find(Ys_pseudo==[Ys_l;Ys_u]))/length(Ys_pseudo); 70 | %fprintf('Iteration [%2d]:BDA+NN=%0.4f\n',i,acc_s); 71 | acc_t = length(find(Yt_pseudo==Yt))/length(Yt_pseudo); 72 | %fprintf('Iteration [%2d]:BDA+NN=%0.4f\n',i,acc_t); 73 | end 74 | end -------------------------------------------------------------------------------- /func/GFK_Map.m: -------------------------------------------------------------------------------- 1 | function [Xs_new,Xt_new,G] = GFK_Map(Xs,Xt,dim) 2 | Ps = pca(Xs); 3 | Pt = pca(Xt); 4 | G = GFK_core([Ps,null(Ps')], Pt(:,1:dim)); 5 | sq_G = real(G^(0.5)); 6 | Xs_new = (sq_G * Xs')'; 7 | Xt_new = (sq_G * Xt')'; 8 | end 9 | 10 | function G = GFK_core(Q,Pt) 11 | % Input: Q = [Ps, null(Ps')], where Ps is the source subspace, column-wise orthonormal 12 | % Pt: target subsapce, column-wise orthonormal, D-by-d, d < 0.5*D 13 | % Output: G = \int_{0}^1 \Phi(t)\Phi(t)' dt 14 | 15 | % ref: Geodesic Flow Kernel for Unsupervised Domain Adaptation. 16 | % B. Gong, Y. Shi, F. Sha, and K. Grauman. 17 | % Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition (CVPR), Providence, RI, June 2012. 18 | 19 | % Contact: Boqing Gong (boqinggo@usc.edu) 20 | 21 | N = size(Q,2); % 22 | dim = size(Pt,2); 23 | 24 | % compute the principal angles 25 | QPt = Q' * Pt; 26 | [V1,V2,V,Gam,Sig] = gsvd(QPt(1:dim,:), QPt(dim+1:end,:)); 27 | V2 = -V2; 28 | theta = real(acos(diag(Gam))); % theta is real in theory. Imaginary part is due to the computation issue. 29 | 30 | % compute the geodesic flow kernel 31 | eps = 1e-20; 32 | B1 = 0.5.*diag(1+sin(2*theta)./2./max(theta,eps)); 33 | B2 = 0.5.*diag((-1+cos(2*theta))./2./max(theta,eps)); 34 | B3 = B2; 35 | B4 = 0.5.*diag(1-sin(2*theta)./2./max(theta,eps)); 36 | G = Q * [V1, zeros(dim,N-dim); zeros(N-dim,dim), V2] ... 37 | * [B1,B2,zeros(dim,N-2*dim);B3,B4,zeros(dim,N-2*dim);zeros(N-2*dim,N)]... 38 | * [V1, zeros(dim,N-dim); zeros(N-dim,dim), V2]' * Q'; 39 | end -------------------------------------------------------------------------------- /func/GeneralSSL.m: -------------------------------------------------------------------------------- 1 | function F = GeneralSSL(A, T, is_normalize) 2 | 3 | n = size(A,2); 4 | ns = length(find(sum(T,2) == 1)); 5 | D = sum(A,2); 6 | invD = spdiags(1./D,0,n,n); 7 | if is_normalize == 1 % normalized weights 8 | D1 = sqrt(invD); 9 | norA = D1*A*D1; 10 | norD = sum(norA,2); 11 | end 12 | 13 | L=spdiags(norD,0,n,n)-norA; 14 | Fs=T(1:ns,:); 15 | Lst=L(1:ns,ns+1:end); 16 | Lts=L(ns+1:end,1:ns); 17 | Ltt=L(ns+1:end,ns+1:end); 18 | F=-(2*Ltt)\(Lts*Fs+Lst'*Fs); -------------------------------------------------------------------------------- /func/GeneralSSL3.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WWLoveTransfer/SLSA-DA/e7aa8204886b4fa9c085e7dc1f1a233ec36f83bf/func/GeneralSSL3.m -------------------------------------------------------------------------------- /func/GeneralSSL4.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WWLoveTransfer/SLSA-DA/e7aa8204886b4fa9c085e7dc1f1a233ec36f83bf/func/GeneralSSL4.m -------------------------------------------------------------------------------- /func/GraphClassifier.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WWLoveTransfer/SLSA-DA/e7aa8204886b4fa9c085e7dc1f1a233ec36f83bf/func/GraphClassifier.m -------------------------------------------------------------------------------- /func/GraphClassifier3.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WWLoveTransfer/SLSA-DA/e7aa8204886b4fa9c085e7dc1f1a233ec36f83bf/func/GraphClassifier3.m -------------------------------------------------------------------------------- /func/GraphClassifier4.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WWLoveTransfer/SLSA-DA/e7aa8204886b4fa9c085e7dc1f1a233ec36f83bf/func/GraphClassifier4.m -------------------------------------------------------------------------------- /func/JDA.m: -------------------------------------------------------------------------------- 1 | function [acc_s,acc_t] = JDA(Xs_l,Xs_u,Xt,Ys_l,Ys_u,Yt,options) 2 | 3 | lambda = options.lambda; 4 | dim = options.dim; 5 | T = options.T; 6 | X = [Xs_l',Xs_u',Xt']; 7 | X = X*diag(sparse(1./sqrt(sum(X.^2)))); 8 | [m,n] = size(X); 9 | ns_l = size(Xs_l,1); 10 | ns_u = size(Xs_u,1); 11 | ns = ns_l+ns_u; 12 | nt = size(Xt,1); 13 | e = [1/ns*ones(ns,1);-1/nt*ones(nt,1)]; 14 | C = length(unique(Ys_l)); 15 | 16 | %% Centering matrix H 17 | H = eye(n) - 1/n * ones(n,n); 18 | %%% M0 19 | M = e * e' * C; %multiply C for better normalization 20 | 21 | knn_model = fitcknn(Xs_l,Ys_l,'NumNeighbors',1); 22 | Ys_pseudo = knn_model.predict(Xs_u); 23 | Ys_pseudo = [Ys_l;Ys_pseudo]; 24 | knn_model = fitcknn([Xs_l;Xs_u],Ys_pseudo,'NumNeighbors',1); 25 | Yt_pseudo = knn_model.predict(Xt); 26 | 27 | %% Iteration 28 | for i = 1 : T 29 | %%% Mc 30 | N = 0; 31 | if ~isempty(Yt_pseudo) && length(Yt_pseudo)==nt 32 | for c = reshape(unique(Ys_pseudo),1,C) 33 | e = zeros(n,1); 34 | e(Ys_pseudo==c) = 1 / length(find(Ys_pseudo==c)); 35 | e(ns+find(Yt_pseudo==c)) = -1 / length(find(Yt_pseudo==c)); 36 | e(isinf(e)) = 0; 37 | N = N + e*e'; 38 | end 39 | end 40 | M = M + N; 41 | M = M / norm(M,'fro'); 42 | 43 | %% Calculation 44 | [A,~] = eigs(X*M*X'+lambda*eye(m),X*H*X',dim,'SM'); 45 | Z = A'*X; 46 | 47 | % normalization for better classification performance 48 | Z = Z*diag(sparse(1./sqrt(sum(Z.^2)))); 49 | Zs_l = Z(:,1:ns_l)'; 50 | Zs_u = Z(:,ns_l+1:ns)'; 51 | Zt = Z(:,ns+1:end)'; 52 | 53 | knn_model = fitcknn(Zs_l,Ys_l,'NumNeighbors',1); 54 | Ys_pseudo = knn_model.predict(Zs_u); 55 | Ys_pseudo = [Ys_l;Ys_pseudo]; 56 | knn_model = fitcknn([Zs_l;Zs_u],Ys_pseudo,'NumNeighbors',1); 57 | Yt_pseudo = knn_model.predict(Zt); 58 | 59 | acc_s = length(find(Ys_pseudo==[Ys_l;Ys_u]))/length(Ys_pseudo); 60 | acc_t = length(find(Yt_pseudo==Yt))/length(Yt_pseudo); 61 | end 62 | end -------------------------------------------------------------------------------- /func/JGSA.m: -------------------------------------------------------------------------------- 1 | function [acc_s,acc_t] = JGSA(Xs_l,Xs_u,Xt,Ys_l,Ys_u,Yt,options); 2 | 3 | % Joint Geometrical and Statistical Alignment for Visual Domain Adaptation. 4 | % IEEE Conference on Computer Vision and Pattern Recognition (CVPR), 2017. 5 | % Jing Zhang, Wanqing Li, Philip Ogunbona. 6 | 7 | alpha = options.alpha; 8 | mu = options.mu; 9 | beta = options.beta; 10 | gamma = options.gamma; 11 | ker = options.ker; 12 | k = options.k; 13 | T = options.T; 14 | Xs = [Xs_l,Xs_u]; 15 | m = size(Xs,1); 16 | ns = size(Xs,2); 17 | nt = size(Xt,2); 18 | 19 | class = unique(Ys_l); 20 | C = length(class); 21 | 22 | knn_model = fitcknn(Xs_l',Ys_l,'NumNeighbors',1); 23 | Ys_pseudo = knn_model.predict(Xs_u'); 24 | Ys_pseudo = [Ys_l;Ys_pseudo]; 25 | knn_model = fitcknn([Xs_l';Xs_u'],Ys_pseudo,'NumNeighbors',1); 26 | Yt_pseudo = knn_model.predict(Xt'); 27 | 28 | if strcmp(ker,'primal') 29 | 30 | %-------------------------------------------------------------------------- 31 | 32 | for t = 1:T 33 | 34 | % compute LDA 35 | dim = size(Xs,1); 36 | meanTotal = mean(Xs,2); 37 | 38 | Sw = zeros(dim, dim); 39 | Sb = zeros(dim, dim); 40 | for i=1:C 41 | Xi = Xs(:,find(Ys_pseudo==class(i))); 42 | meanClass = mean(Xi,2); 43 | Hi = eye(size(Xi,2))-1/(size(Xi,2))*ones(size(Xi,2),size(Xi,2)); 44 | Sw = Sw + Xi*Hi*Xi'; % calculate within-class scatter 45 | Sb = Sb + size(Xi,2)*(meanClass-meanTotal)*(meanClass-meanTotal)'; % calculate between-class scatter 46 | end 47 | P = zeros(2*m,2*m); 48 | P(1:m,1:m) = Sb; 49 | Q = Sw; 50 | 51 | % Construct MMD matrix 52 | [Ms, Mt, Mst, Mts] = constructMMD(ns,nt,Ys_pseudo,Yt_pseudo,C); 53 | 54 | Ts = Xs*Ms*Xs'; 55 | Tt = Xt*Mt*Xt'; 56 | Tst = Xs*Mst*Xt'; 57 | Tts = Xt*Mts*Xs'; 58 | 59 | % Construct centering matrix 60 | Ht = eye(nt)-1/(nt)*ones(nt,nt); 61 | 62 | X = [zeros(m,ns) zeros(m,nt); zeros(m,ns) Xt]; 63 | H = [zeros(ns,ns) zeros(ns,nt); zeros(nt,ns) Ht]; 64 | 65 | Smax = mu*X*H*X'+beta*P; 66 | Smin = [Ts+alpha*eye(m)+beta*Q, Tst-alpha*eye(m) ; ... 67 | Tts-alpha*eye(m), Tt+(alpha+mu)*eye(m)]; 68 | [W,~] = eigs(Smax, Smin+1e-9*eye(2*m), k, 'LM'); 69 | A = W(1:m, :); 70 | Att = W(m+1:end, :); 71 | 72 | Zs = A'*Xs; 73 | Zt = Att'*Xt; 74 | 75 | if T>1 76 | ns_l = size(Xs_l,2); 77 | Zs_l = Zs(:,1:ns_l); 78 | Zs_u = Zs(:,ns_l+1:end); 79 | knn_model = fitcknn(Zs_l',Ys_l,'NumNeighbors',1); 80 | Ys_pseudo = knn_model.predict(Zs_u'); 81 | Ys_pseudo = [Ys_l;Ys_pseudo]; 82 | knn_model = fitcknn([Zs_l';Zs_u'],Ys_pseudo,'NumNeighbors',1); 83 | Yt_pseudo = knn_model.predict(Zt'); 84 | acc_s = length(find(Ys_pseudo==[Ys_l;Ys_u]))/length(Ys_pseudo); 85 | acc_t = length(find(Yt_pseudo==Yt))/length(Yt); 86 | end 87 | end 88 | else 89 | 90 | Xst = [Xs, Xt]; 91 | nst = size(Xst,2); 92 | [Ks, Kt, Kst] = constructKernel(Xs,Xt,ker,gamma); 93 | %-------------------------------------------------------------------------- 94 | % compute LDA 95 | dim = size(Ks,2); 96 | C = length(class); 97 | meanTotal = mean(Ks,1); 98 | 99 | Sw = zeros(dim, dim); 100 | Sb = zeros(dim, dim); 101 | for i=1:C 102 | Xi = Ks(find(Ys==class(i)),:); 103 | meanClass = mean(Xi,1); 104 | Hi = eye(size(Xi,1))-1/(size(Xi,1))*ones(size(Xi,1),size(Xi,1)); 105 | Sw = Sw + Xi'*Hi*Xi; % calculate within-class scatter 106 | Sb = Sb + size(Xi,1)*(meanClass-meanTotal)'*(meanClass-meanTotal); % calculate between-class scatter 107 | end 108 | P = zeros(2*nst,2*nst); 109 | P(1:nst,1:nst) = Sb; 110 | Q = Sw; 111 | 112 | for t = 1:T 113 | 114 | % Construct MMD matrix 115 | [Ms, Mt, Mst, Mts] = constructMMD(ns,nt,Ys,Yt0,C); 116 | 117 | Ts = Ks'*Ms*Ks; 118 | Tt = Kt'*Mt*Kt; 119 | Tst = Ks'*Mst*Kt; 120 | Tts = Kt'*Mts*Ks; 121 | 122 | K = [zeros(ns,nst), zeros(ns,nst); zeros(nt,nst), Kt]; 123 | Smax = mu*K'*K+beta*P; 124 | 125 | Smin = [Ts+alpha*Kst+beta*Q, Tst-alpha*Kst;... 126 | Tts-alpha*Kst, Tt+mu*Kst+alpha*Kst]; 127 | [W,~] = eigs(Smax, Smin+1e-9*eye(2*nst), k, 'LM'); 128 | W = real(W); 129 | 130 | A = W(1:nst, :); 131 | Att = W(nst+1:end, :); 132 | 133 | Zs = A'*Ks'; 134 | Zt = Att'*Kt'; 135 | 136 | if T>1 137 | Yt0 = knnclassify(Zt',Zs',Ys,1); 138 | acc = length(find(Yt0==Yt))/length(Yt); 139 | fprintf('acc of iter %d: %0.4f\n',t, full(acc)); 140 | end 141 | end 142 | end 143 | 144 | Xs = Zs; 145 | Xt = Zt; 146 | 147 | -------------------------------------------------------------------------------- /func/L2_distance_1.m: -------------------------------------------------------------------------------- 1 | % compute squared Euclidean distance 2 | % ||A-B||^2 = ||A||^2 + ||B||^2 - 2*A'*B 3 | function d = L2_distance_1(a,b) 4 | % a,b: two matrices. each column is a data 5 | % d: distance matrix of a and b 6 | 7 | 8 | 9 | if (size(a,1) == 1) 10 | a = [a; zeros(1,size(a,2))]; 11 | b = [b; zeros(1,size(b,2))]; 12 | end 13 | 14 | aa=sum(a.*a); bb=sum(b.*b); ab=a'*b; 15 | d = repmat(aa',[1 size(bb,2)]) + repmat(bb,[size(aa,2) 1]) - 2*ab; 16 | 17 | d = real(d); 18 | d = max(d,0); 19 | 20 | % % force 0 on the diagonal? 21 | % if (df==1) 22 | % d = d.*(1-eye(size(d))); 23 | % end 24 | -------------------------------------------------------------------------------- /func/LabelFormat.m: -------------------------------------------------------------------------------- 1 | function Y1 = LabelFormat(Y) 2 | % Y should be n*1 or n*c 3 | 4 | [m n] = size(Y); 5 | if m == 1 6 | Y = Y'; 7 | [m n] = size(Y); 8 | end; 9 | 10 | if n == 1 11 | class_num = length(unique(Y)); 12 | Y1 = zeros(m,class_num); 13 | for i=1:class_num 14 | Y1(Y==i,i) = 1; 15 | end; 16 | else 17 | [temp Y1] = max(Y,[],2); 18 | end; -------------------------------------------------------------------------------- /func/MEDA.m: -------------------------------------------------------------------------------- 1 | function [acc_s,acc_t] = MEDA(Xs_l,Xs_u,Xt,Ys_l,Ys_u,Yt,options) 2 | 3 | % Reference: 4 | %% Jindong Wang, Wenjie Feng, Yiqiang Chen, Han Yu, Meiyu Huang, Philip S. 5 | %% Yu. Visual Domain Adaptation with Manifold Embedded Distribution 6 | %% Alignment. ACM Multimedia conference 2018. 7 | 8 | %% Inputs: 9 | %%% Xs : Source domain feature matrix, n * dim 10 | %%% Ys : Source domain label matrix, n * 1 11 | %%% Xt : Target domain feature matrix, m * dim 12 | %%% Yt : Target domain label matrix, m * 1 (only used for testing accuracy) 13 | %%% options : algorithm options: 14 | %%%%% options.d : dimension after manifold feature learning (default: 20) 15 | %%%%% options.T : number of iteration (default: 10) 16 | %%%%% options.lambda : lambda in the paper (default: 10) 17 | %%%%% options.eta : eta in the paper (default: 0.1) 18 | %%%%% options.rho : rho in the paper (default: 1.0) 19 | %%%%% options.base : base classifier for soft labels (default: NN) 20 | 21 | %% Outputs: 22 | %%%% Acc : Final accuracy value 23 | %%%% acc_iter : Accuracy value list of all iterations, T * 1 24 | %%%% Beta : Cofficient matrix 25 | %%%% Yt_pred : Prediction labels for target domain 26 | 27 | %% Algorithm starts here 28 | %fprintf('MEDA starts...\n'); 29 | 30 | %% Load algorithm options 31 | if ~isfield(options,'p') 32 | options.p = 10; 33 | end 34 | if ~isfield(options,'eta') 35 | options.eta = 0.1; 36 | end 37 | if ~isfield(options,'lambda') 38 | options.lambda = 1.0; 39 | end 40 | if ~isfield(options,'rho') 41 | options.rho = 1.0; 42 | end 43 | if ~isfield(options,'T') 44 | options.T = 10; 45 | end 46 | if ~isfield(options,'d') 47 | options.d = 20; 48 | end 49 | 50 | % Manifold feature learning 51 | Xs = [Xs_l;Xs_u]; 52 | ns_l = size(Xs_l,1); 53 | ns_u = size(Xs_u,1); 54 | 55 | [Xs_new,Xt_new,~] = GFK_Map(Xs,Xt,options.d); 56 | Xs = double(Xs_new'); 57 | Xt = double(Xt_new'); 58 | Xs_l = Xs(:,1:ns_l); 59 | Xs_u = Xs(:,ns_l+1:end); 60 | X = [Xs,Xt]; 61 | n = size(Xs,2); 62 | m = size(Xt,2); 63 | C = length(unique(Yt)); 64 | 65 | %% Data normalization 66 | X = X * diag(sparse(1 ./ sqrt(sum(X.^2)))); 67 | 68 | % Generate soft labels for the target domain 69 | knn_model = fitcknn(Xs_l',Ys_l,'NumNeighbors',1); 70 | Ys_pseudo = knn_model.predict(Xs_u'); 71 | Ys_pseudo = [Ys_l;Ys_pseudo]; 72 | knn_model = fitcknn([Xs_l';Xs_u'],Ys_pseudo,'NumNeighbors',1); 73 | Yt_pseudo = knn_model.predict(Xt'); 74 | 75 | %% Construct graph Laplacian 76 | if options.rho > 0 77 | manifold.k = options.p; 78 | manifold.Metric = 'Cosine'; 79 | manifold.NeighborMode = 'KNN'; 80 | manifold.WeightMode = 'Cosine'; 81 | W = lapgraph(X',manifold); 82 | Dw = diag(sparse(sqrt(1 ./ sum(W)))); 83 | L = eye(n + m) - Dw * W * Dw; 84 | else 85 | L = 0; 86 | end 87 | 88 | % Construct kernel 89 | K = kernel_meda('rbf',X,sqrt(sum(sum(X .^ 2).^0.5)/(n + m))); 90 | E = diag(sparse([ones(n,1);zeros(m,1)])); 91 | 92 | for t = 1 : options.T 93 | YY = []; 94 | for c = 1 : C 95 | YY = [YY,Ys_pseudo==c]; 96 | end 97 | YY = [YY;zeros(m,C)]; 98 | % Estimate mu 99 | mu = estimate_mu(Xs',Ys_pseudo,Xt',Yt_pseudo); 100 | % Construct MMD matrix 101 | e = [1 / n * ones(n,1); -1 / m * ones(m,1)]; 102 | M = e * e' * length(unique(Ys_pseudo)); 103 | N = 0; 104 | for c = reshape(unique(Ys_pseudo),1,length(unique(Ys_pseudo))) 105 | e = zeros(n + m,1); 106 | e(Ys_pseudo == c) = 1 / length(find(Ys_pseudo == c)); 107 | e(n + find(Yt_pseudo == c)) = -1 / length(find(Yt_pseudo == c)); 108 | e(isinf(e)) = 0; 109 | N = N + e * e'; 110 | end 111 | M = (1 - mu) * M + mu * N; 112 | M = M / norm(M,'fro'); 113 | 114 | % Compute coefficients vector Beta 115 | Beta = ((E + options.lambda * M + options.rho * L) * K + options.eta * speye(n + m,n + m)) \ (E * YY); 116 | F = K * Beta; 117 | [~,Cls] = max(F,[],2); 118 | 119 | %% Compute accuracy 120 | Ys_pseudo = Cls(1:n); 121 | Yt_pseudo = Cls(n+1:end); 122 | acc_s = numel(find(Cls(1:n)==[Ys_l;Ys_u])) / n; 123 | acc_t = numel(find(Cls(n+1:end)==Yt)) / m; 124 | end 125 | end 126 | 127 | function K = kernel_meda(ker,X,sigma) 128 | switch ker 129 | case 'linear' 130 | K = X' * X; 131 | case 'rbf' 132 | n1sq = sum(X.^2,1); 133 | n1 = size(X,2); 134 | D = (ones(n1,1)*n1sq)' + ones(n1,1)*n1sq -2*X'*X; 135 | K = exp(-D/(2*sigma^2)); 136 | case 'sam' 137 | D = X'*X; 138 | K = exp(-acos(D).^2/(2*sigma^2)); 139 | otherwise 140 | error(['Unsupported kernel ' ker]) 141 | end 142 | end -------------------------------------------------------------------------------- /func/SolveG1.m: -------------------------------------------------------------------------------- 1 | % Non-nagetive spectral clustering: min_{Q>=0} trace(Q'*L*Q) + r*trace((Q'*Q-I)'(Q'*Q-I)) 2 | function [Gs] = SolveG1(As, At, Gs, Gt, Fs, mu1) 3 | 4 | ITER = 100; 5 | if nargout > 1 6 | obj = zeros(ITER,1); 7 | end; 8 | 9 | G_pos1=As'*As; 10 | G_pos1_pos=(abs(G_pos1)+G_pos1)/2; 11 | G_pos1_neg=(abs(G_pos1)-G_pos1)/2; 12 | G_pos2=mu1*As'*As; 13 | G_pos2_pos=(abs(G_pos2)+G_pos2)/2; 14 | G_pos2_neg=(abs(G_pos2)-G_pos2)/2; 15 | G_neg1=As'*At; 16 | G_neg1_pos=(abs(G_neg1)+G_neg1)/2; 17 | G_neg1_neg=(abs(G_neg1)-G_neg1)/2; 18 | G_neg2=mu1*As'*As; 19 | G_neg2_pos=(abs(G_neg2)+G_neg2)/2; 20 | G_neg2_neg=(abs(G_neg2)-G_neg2)/2; 21 | 22 | for iter = 1:ITER 23 | obj(iter)=trace((As*Gs-At*Gt)*(As*Gs-At*Gt)')+mu1*trace((As-As*Gs*Fs)*(As-As*Gs*Fs)'); 24 | if iter>1 25 | noi=obj(iter-1)-obj(iter); 26 | if noi<1e-4 27 | break; 28 | end 29 | end 30 | S=(G_pos1_neg*Gs+G_pos2_neg*Gs*Fs*Fs'+G_neg1_pos*Gt+G_neg2_pos*Fs'+eps)./... 31 | (G_pos1_pos*Gs+G_pos2_pos*Gs*Fs*Fs'+G_neg1_neg*Gt+G_neg2_neg*Fs'+eps); 32 | S=sqrt(S); 33 | Gs = Gs.*S; 34 | Gs = Gs*diag(sparse(1./sum(Gs,1))); 35 | end 36 | %Gs = Gs*diag(sparse(1./sum(Gs,1))); -------------------------------------------------------------------------------- /func/SolveG2.m: -------------------------------------------------------------------------------- 1 | % Non-nagetive spectral clustering: min_{Q>=0} trace(Q'*L*Q) + r*trace((Q'*Q-I)'(Q'*Q-I)) 2 | function [Gt] = SolveG2(As, At, Gs, Gt, Ft, mu2) 3 | 4 | ITER = 100; 5 | if nargout > 1 6 | obj = zeros(ITER,1); 7 | end; 8 | G_pos1=At'*At; 9 | G_pos1_pos=(abs(G_pos1)+G_pos1)/2; 10 | G_pos1_neg=(abs(G_pos1)-G_pos1)/2; 11 | G_pos2=mu2*At'*At; 12 | G_pos2_pos=(abs(G_pos2)+G_pos2)/2; 13 | G_pos2_neg=(abs(G_pos2)-G_pos2)/2; 14 | G_neg1=At'*As; 15 | G_neg1_pos=(abs(G_neg1)+G_neg1)/2; 16 | G_neg1_neg=(abs(G_neg1)-G_neg1)/2; 17 | G_neg2=mu2*At'*At; 18 | G_neg2_pos=(abs(G_neg2)+G_neg2)/2; 19 | G_neg2_neg=(abs(G_neg2)-G_neg2)/2; 20 | 21 | for iter = 1:ITER 22 | obj(iter)=trace((As*Gs-At*Gt)*(As*Gs-At*Gt)')+mu2*trace((At-At*Gt*Ft)*(At-At*Gt*Ft)'); 23 | if iter>1 24 | noi=obj(iter-1)-obj(iter); 25 | if noi<1e-4 26 | break; 27 | end 28 | end 29 | S=(G_pos1_neg*Gt+G_pos2_neg*Gt*Ft*Ft'+G_neg1_pos*Gs+G_neg2_pos*Ft'+eps)./... 30 | (G_pos1_pos*Gt+G_pos2_pos*Gt*Ft*Ft'+G_neg1_neg*Gs+G_neg2_neg*Ft'+eps); 31 | S=sqrt(S); 32 | Gt = Gt.*S; 33 | Gt = Gt*diag(sparse(1./sum(Gt,1))); 34 | end 35 | %Gt = Gt*diag(sparse(1./sum(Gt,1))); -------------------------------------------------------------------------------- /func/TCA.m: -------------------------------------------------------------------------------- 1 | function [acc_s,acc_t] = TCA(Xs_l,Xs_u,Xt,Ys_l,Ys_u,Yt,options) 2 | 3 | lambda = options.lambda; 4 | dim = options.dim; 5 | X = [Xs_l',Xs_u',Xt']; 6 | X = X*diag(sparse(1./sqrt(sum(X.^2)))); 7 | [m,n] = size(X); 8 | ns_l = size(Xs_l,1); 9 | ns_u = size(Xs_u,1); 10 | ns = ns_l+ns_u; 11 | nt = size(Xt,1); 12 | e = [1/ns*ones(ns,1);-1/nt*ones(nt,1)]; 13 | 14 | %% Centering matrix H 15 | H = eye(n) - 1/n * ones(n,n); 16 | %%% M0 17 | M = e * e'; %multiply C for better normalization 18 | M = M / norm(M,'fro'); 19 | knn_model = fitcknn(Xs_l,Ys_l,'NumNeighbors',1); 20 | Ys_pseudo = knn_model.predict(Xs_u); 21 | Ys_pseudo = [Ys_l;Ys_pseudo]; 22 | knn_model = fitcknn([Xs_l;Xs_u],Ys_pseudo,'NumNeighbors',1); 23 | Yt_pseudo = knn_model.predict(Xt); 24 | 25 | %% Iteration 26 | 27 | %% Calculation 28 | [A,~] = eigs(X*M*X'+lambda*eye(m),X*H*X',dim,'SM'); 29 | Z = A'*X; 30 | 31 | %normalization for better classification performance 32 | Z = Z*diag(sparse(1./sqrt(sum(Z.^2)))); 33 | Zs_l = Z(:,1:ns_l)'; 34 | Zs_u = Z(:,ns_l+1:ns)'; 35 | Zt = Z(:,ns+1:end)'; 36 | 37 | knn_model = fitcknn(Zs_l,Ys_l,'NumNeighbors',1); 38 | Ys_pseudo = knn_model.predict(Zs_u); 39 | Ys_pseudo = [Ys_l;Ys_pseudo]; 40 | knn_model = fitcknn([Zs_l;Zs_u],Ys_pseudo,'NumNeighbors',1); 41 | Yt_pseudo = knn_model.predict(Zt); 42 | 43 | acc_s = length(find(Ys_pseudo==[Ys_l;Ys_u]))/length(Ys_pseudo); 44 | acc_t = length(find(Yt_pseudo==Yt))/length(Yt_pseudo); 45 | end -------------------------------------------------------------------------------- /func/VDA.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WWLoveTransfer/SLSA-DA/e7aa8204886b4fa9c085e7dc1f1a233ec36f83bf/func/VDA.m -------------------------------------------------------------------------------- /func/WUDA1.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WWLoveTransfer/SLSA-DA/e7aa8204886b4fa9c085e7dc1f1a233ec36f83bf/func/WUDA1.m -------------------------------------------------------------------------------- /func/WUDA2.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WWLoveTransfer/SLSA-DA/e7aa8204886b4fa9c085e7dc1f1a233ec36f83bf/func/WUDA2.m -------------------------------------------------------------------------------- /func/constructKernel.m: -------------------------------------------------------------------------------- 1 | function [Ks, Kt, Kst] = constructKernel(Xs,Xt,ker,gamma) 2 | 3 | Xst = [Xs, Xt]; 4 | ns = size(Xs,2); 5 | nt = size(Xt,2); 6 | nst = size(Xst,2); 7 | Kst0 = km_kernel(Xst',Xst',ker,gamma); 8 | Ks0 = km_kernel(Xs',Xst',ker,gamma); 9 | Kt0 = km_kernel(Xt',Xst',ker,gamma); 10 | 11 | oneNst = ones(nst,nst)/nst; 12 | oneN=ones(ns,nst)/nst; 13 | oneMtrN=ones(nt,nst)/nst; 14 | Ks=Ks0-oneN*Kst0-Ks0*oneNst+oneN*Kst0*oneNst; 15 | Kt=Kt0-oneMtrN*Kst0-Kt0*oneNst+oneMtrN*Kst0*oneNst; 16 | Kst=Kst0-oneNst*Kst0-Kst0*oneNst+oneNst*Kst0*oneNst; -------------------------------------------------------------------------------- /func/constructMMD.m: -------------------------------------------------------------------------------- 1 | function [Ms, Mt, Mst, Mts] = constructMMD(ns,nt,Ys,Yt0,C) 2 | e = [1/ns*ones(ns,1);-1/nt*ones(nt,1)]; 3 | es = 1/ns*ones(ns,1); 4 | et = -1/nt*ones(nt,1); 5 | 6 | M = e*e'*C; 7 | Ms = es*es'*C; 8 | Mt = et*et'*C; 9 | Mst = es*et'*C; 10 | Mts = et*es'*C; 11 | if ~isempty(Yt0) && length(Yt0)==nt 12 | for c = reshape(unique(Ys),1,C) 13 | es = zeros(ns,1); 14 | et = zeros(nt,1); 15 | es(Ys==c) = 1/length(find(Ys==c)); 16 | et(Yt0==c) = -1/length(find(Yt0==c)); 17 | es(isinf(es)) = 0; 18 | et(isinf(et)) = 0; 19 | Ms = Ms + es*es'; 20 | Mt = Mt + et*et'; 21 | Mst = Mst + es*et'; 22 | Mts = Mts + et*es'; 23 | end 24 | end 25 | 26 | Ms = Ms/norm(M,'fro'); 27 | Mt = Mt/norm(M,'fro'); 28 | Mst = Mst/norm(M,'fro'); 29 | Mts = Mts/norm(M,'fro'); -------------------------------------------------------------------------------- /func/estimate_mu.m: -------------------------------------------------------------------------------- 1 | function [mu,adist_m,adist_c] = estimate_mu(Xs,Ys,Xt,Yt) 2 | C = length(unique(Ys)); 3 | list_adist_c = []; 4 | epsilon = 1e-3; 5 | for i = 1 : C 6 | index_i = Ys == i; 7 | Xsi = Xs(index_i,:); 8 | index_j = Yt == i; 9 | Xtj = Xt(index_j,:); 10 | adist_i = adist(Xsi,Xtj); 11 | list_adist_c = [list_adist_c;adist_i]; 12 | end 13 | adist_c = mean(list_adist_c); 14 | 15 | adist_m = adist(Xs,Xt); 16 | mu = adist_c / (adist_c + adist_m); 17 | if mu > 1 % Theoretically mu <= 1, but calculation may be over 1 18 | mu = 1; 19 | elseif mu <= epsilon 20 | mu = 0; 21 | end 22 | end 23 | 24 | function dist = adist(Xs,Xt) 25 | Yss = ones(size(Xs,1),1); 26 | Ytt = ones(size(Xt,1),1) * 2; 27 | 28 | % The results of fitclinear() may vary in a very small range, since Matlab uses SGD to optimize SVM. 29 | % The fluctuation is very small, ignore it 30 | model_linear = fitclinear([Xs;Xt],[Yss;Ytt],'learner','svm'); 31 | ypred = model_linear.predict([Xs;Xt]); 32 | error = mae([Yss;Ytt],ypred); 33 | dist = 2 * (1 - 2 * error); 34 | end -------------------------------------------------------------------------------- /func/km_kernel.m: -------------------------------------------------------------------------------- 1 | function K = km_kernel(X1,X2,ktype,kpar) 2 | % KM_KERNEL calculates the kernel matrix between two data sets. 3 | % Input: - X1, X2: data matrices in row format (data as rows) 4 | % - ktype: string representing kernel type 5 | % - kpar: vector containing the kernel parameters 6 | % Output: - K: kernel matrix 7 | % USAGE: K = km_kernel(X1,X2,ktype,kpar) 8 | % 9 | % Author: Steven Van Vaerenbergh (steven *at* gtas.dicom.unican.es), 2012. 10 | % 11 | % This file is part of the Kernel Methods Toolbox for MATLAB. 12 | % https://github.com/steven2358/kmbox 13 | 14 | switch ktype 15 | case 'gauss' % Gaussian kernel 16 | sgm = kpar; % kernel width 17 | 18 | dim1 = size(X1,1); 19 | dim2 = size(X2,1); 20 | 21 | norms1 = sum(X1.^2,2); 22 | norms2 = sum(X2.^2,2); 23 | 24 | mat1 = repmat(norms1,1,dim2); 25 | mat2 = repmat(norms2',dim1,1); 26 | 27 | distmat = mat1 + mat2 - 2*X1*X2'; % full distance matrix 28 | sgm = sgm / mean(mean(distmat)); % added by jing 24/09/2016, median-distance 29 | K = exp(-distmat/(2*sgm^2)); 30 | 31 | case 'gauss-diag' % only diagonal of Gaussian kernel 32 | sgm = kpar; % kernel width 33 | K = exp(-sum((X1-X2).^2,2)/(2*sgm^2)); 34 | 35 | case 'poly' % polynomial kernel 36 | % p = kpar(1); % polynome order 37 | % c = kpar(2); % additive constant 38 | p = kpar; % jing 39 | c = 1; % jing 40 | 41 | K = (X1*X2' + c).^p; 42 | 43 | case 'linear' % linear kernel 44 | K = X1*X2'; 45 | 46 | otherwise % default case 47 | error ('unknown kernel type') 48 | end 49 | -------------------------------------------------------------------------------- /func/lapgraph.m: -------------------------------------------------------------------------------- 1 | function [W, elapse] = lapgraph(fea,options) 2 | % Usage: 3 | % W = graph(fea,options) 4 | % 5 | % fea: Rows of vectors of data points. Each row is x_i 6 | % options: Struct value in Matlab. The fields in options that can be set: 7 | % Metric - Choices are: 8 | % 'Euclidean' - Will use the Euclidean distance of two data 9 | % points to evaluate the "closeness" between 10 | % them. [Default One] 11 | % 'Cosine' - Will use the cosine value of two vectors 12 | % to evaluate the "closeness" between them. 13 | % A popular similarity measure used in 14 | % Information Retrieval. 15 | % 16 | % NeighborMode - Indicates how to construct the graph. Choices 17 | % are: [Default 'KNN'] 18 | % 'KNN' - k = 0 19 | % Complete graph 20 | % k > 0 21 | % Put an edge between two nodes if and 22 | % only if they are among the k nearst 23 | % neighbors of each other. You are 24 | % required to provide the parameter k in 25 | % the options. Default k=5. 26 | % 'Supervised' - k = 0 27 | % Put an edge between two nodes if and 28 | % only if they belong to same class. 29 | % k > 0 30 | % Put an edge between two nodes if 31 | % they belong to same class and they 32 | % are among the k nearst neighbors of 33 | % each other. 34 | % Default: k=0 35 | % You are required to provide the label 36 | % information gnd in the options. 37 | % 38 | % WeightMode - Indicates how to assign weights for each edge 39 | % in the graph. Choices are: 40 | % 'Binary' - 0-1 weighting. Every edge receiveds weight 41 | % of 1. [Default One] 42 | % 'HeatKernel' - If nodes i and j are connected, put weight 43 | % W_ij = exp(-norm(x_i - x_j)/2t^2). This 44 | % weight mode can only be used under 45 | % 'Euclidean' metric and you are required to 46 | % provide the parameter t. 47 | % 'Cosine' - If nodes i and j are connected, put weight 48 | % cosine(x_i,x_j). Can only be used under 49 | % 'Cosine' metric. 50 | % 51 | % k - The parameter needed under 'KNN' NeighborMode. 52 | % Default will be 5. 53 | % gnd - The parameter needed under 'Supervised' 54 | % NeighborMode. Colunm vector of the label 55 | % information for each data point. 56 | % bLDA - 0 or 1. Only effective under 'Supervised' 57 | % NeighborMode. If 1, the graph will be constructed 58 | % to make LPP exactly same as LDA. Default will be 59 | % 0. 60 | % t - The parameter needed under 'HeatKernel' 61 | % WeightMode. Default will be 1 62 | % bNormalized - 0 or 1. Only effective under 'Cosine' metric. 63 | % Indicates whether the fea are already be 64 | % normalized to 1. Default will be 0 65 | % bSelfConnected - 0 or 1. Indicates whether W(i,i) == 1. Default 1 66 | % if 'Supervised' NeighborMode & bLDA == 1, 67 | % bSelfConnected will always be 1. Default 1. 68 | % 69 | % 70 | % Examples: 71 | % 72 | % fea = rand(50,15); 73 | % options = []; 74 | % options.Metric = 'Euclidean'; 75 | % options.NeighborMode = 'KNN'; 76 | % options.k = 5; 77 | % options.WeightMode = 'HeatKernel'; 78 | % options.t = 1; 79 | % W = constructW(fea,options); 80 | % 81 | % 82 | % fea = rand(50,15); 83 | % gnd = [ones(10,1);ones(15,1)*2;ones(10,1)*3;ones(15,1)*4]; 84 | % options = []; 85 | % options.Metric = 'Euclidean'; 86 | % options.NeighborMode = 'Supervised'; 87 | % options.gnd = gnd; 88 | % options.WeightMode = 'HeatKernel'; 89 | % options.t = 1; 90 | % W = constructW(fea,options); 91 | % 92 | % 93 | % fea = rand(50,15); 94 | % gnd = [ones(10,1);ones(15,1)*2;ones(10,1)*3;ones(15,1)*4]; 95 | % options = []; 96 | % options.Metric = 'Euclidean'; 97 | % options.NeighborMode = 'Supervised'; 98 | % options.gnd = gnd; 99 | % options.bLDA = 1; 100 | % W = constructW(fea,options); 101 | % 102 | % 103 | % For more details about the different ways to construct the W, please 104 | % refer: 105 | % Deng Cai, Xiaofei He and Jiawei Han, "Document Clustering Using 106 | % Locality Preserving Indexing" IEEE TKDE, Dec. 2005. 107 | % 108 | % 109 | % Written by Deng Cai (dengcai2 AT cs.uiuc.edu), April/2004, Feb/2006, 110 | % May/2007 111 | % 112 | 113 | if (~exist('options','var')) 114 | options = []; 115 | else 116 | if ~isstruct(options) 117 | error('parameter error!'); 118 | end 119 | end 120 | 121 | %================================================= 122 | if ~isfield(options,'Metric') 123 | options.Metric = 'Cosine'; 124 | end 125 | 126 | switch lower(options.Metric) 127 | case {lower('Euclidean')} 128 | case {lower('Cosine')} 129 | if ~isfield(options,'bNormalized') 130 | options.bNormalized = 0; 131 | end 132 | otherwise 133 | error('Metric does not exist!'); 134 | end 135 | 136 | %================================================= 137 | if ~isfield(options,'NeighborMode') 138 | options.NeighborMode = 'KNN'; 139 | end 140 | 141 | switch lower(options.NeighborMode) 142 | case {lower('KNN')} %For simplicity, we include the data point itself in the kNN 143 | if ~isfield(options,'k') 144 | options.k = 5; 145 | end 146 | case {lower('Supervised')} 147 | if ~isfield(options,'bLDA') 148 | options.bLDA = 0; 149 | end 150 | if options.bLDA 151 | options.bSelfConnected = 1; 152 | end 153 | if ~isfield(options,'k') 154 | options.k = 0; 155 | end 156 | if ~isfield(options,'gnd') 157 | error('Label(gnd) should be provided under ''Supervised'' NeighborMode!'); 158 | end 159 | if ~isempty(fea) && length(options.gnd) ~= size(fea,1) 160 | error('gnd doesn''t match with fea!'); 161 | end 162 | otherwise 163 | error('NeighborMode does not exist!'); 164 | end 165 | 166 | %================================================= 167 | 168 | if ~isfield(options,'WeightMode') 169 | options.WeightMode = 'Binary'; 170 | end 171 | 172 | bBinary = 0; 173 | switch lower(options.WeightMode) 174 | case {lower('Binary')} 175 | bBinary = 1; 176 | case {lower('HeatKernel')} 177 | if ~strcmpi(options.Metric,'Euclidean') 178 | warning('''HeatKernel'' WeightMode should be used under ''Euclidean'' Metric!'); 179 | options.Metric = 'Euclidean'; 180 | end 181 | if ~isfield(options,'t') 182 | options.t = 1; 183 | end 184 | case {lower('Cosine')} 185 | if ~strcmpi(options.Metric,'Cosine') 186 | warning('''Cosine'' WeightMode should be used under ''Cosine'' Metric!'); 187 | options.Metric = 'Cosine'; 188 | end 189 | if ~isfield(options,'bNormalized') 190 | options.bNormalized = 0; 191 | end 192 | otherwise 193 | error('WeightMode does not exist!'); 194 | end 195 | 196 | %================================================= 197 | 198 | if ~isfield(options,'bSelfConnected') 199 | options.bSelfConnected = 1; 200 | end 201 | 202 | %================================================= 203 | tmp_T = cputime; 204 | 205 | if isfield(options,'gnd') 206 | nSmp = length(options.gnd); 207 | else 208 | nSmp = size(fea,1); 209 | end 210 | maxM = 62500000; %500M 211 | BlockSize = floor(maxM/(nSmp*3)); 212 | 213 | 214 | if strcmpi(options.NeighborMode,'Supervised') 215 | Label = unique(options.gnd); 216 | nLabel = length(Label); 217 | if options.bLDA 218 | G = zeros(nSmp,nSmp); 219 | for idx=1:nLabel 220 | classIdx = options.gnd==Label(idx); 221 | G(classIdx,classIdx) = 1/sum(classIdx); 222 | end 223 | W = sparse(G); 224 | elapse = cputime - tmp_T; 225 | return; 226 | end 227 | 228 | switch lower(options.WeightMode) 229 | case {lower('Binary')} 230 | if options.k > 0 231 | G = zeros(nSmp*(options.k+1),3); 232 | idNow = 0; 233 | for i=1:nLabel 234 | classIdx = find(options.gnd==Label(i)); 235 | D = EuDist2(fea(classIdx,:),[],0); 236 | [dump idx] = sort(D,2); % sort each row 237 | clear D dump; 238 | idx = idx(:,1:options.k+1); 239 | 240 | nSmpClass = length(classIdx)*(options.k+1); 241 | G(idNow+1:nSmpClass+idNow,1) = repmat(classIdx,[options.k+1,1]); 242 | G(idNow+1:nSmpClass+idNow,2) = classIdx(idx(:)); 243 | G(idNow+1:nSmpClass+idNow,3) = 1; 244 | idNow = idNow+nSmpClass; 245 | clear idx 246 | end 247 | G = sparse(G(:,1),G(:,2),G(:,3),nSmp,nSmp); 248 | G = max(G,G'); 249 | else 250 | G = zeros(nSmp,nSmp); 251 | for i=1:nLabel 252 | classIdx = find(options.gnd==Label(i)); 253 | G(classIdx,classIdx) = 1; 254 | end 255 | end 256 | 257 | if ~options.bSelfConnected 258 | for i=1:size(G,1) 259 | G(i,i) = 0; 260 | end 261 | end 262 | 263 | W = sparse(G); 264 | case {lower('HeatKernel')} 265 | if options.k > 0 266 | G = zeros(nSmp*(options.k+1),3); 267 | idNow = 0; 268 | for i=1:nLabel 269 | classIdx = find(options.gnd==Label(i)); 270 | D = EuDist2(fea(classIdx,:),[],0); 271 | [dump idx] = sort(D,2); % sort each row 272 | clear D; 273 | idx = idx(:,1:options.k+1); 274 | dump = dump(:,1:options.k+1); 275 | dump = exp(-dump/(2*options.t^2)); 276 | 277 | nSmpClass = length(classIdx)*(options.k+1); 278 | G(idNow+1:nSmpClass+idNow,1) = repmat(classIdx,[options.k+1,1]); 279 | G(idNow+1:nSmpClass+idNow,2) = classIdx(idx(:)); 280 | G(idNow+1:nSmpClass+idNow,3) = dump(:); 281 | idNow = idNow+nSmpClass; 282 | clear dump idx 283 | end 284 | G = sparse(G(:,1),G(:,2),G(:,3),nSmp,nSmp); 285 | else 286 | G = zeros(nSmp,nSmp); 287 | for i=1:nLabel 288 | classIdx = find(options.gnd==Label(i)); 289 | D = EuDist2(fea(classIdx,:),[],0); 290 | D = exp(-D/(2*options.t^2)); 291 | G(classIdx,classIdx) = D; 292 | end 293 | end 294 | 295 | if ~options.bSelfConnected 296 | for i=1:size(G,1) 297 | G(i,i) = 0; 298 | end 299 | end 300 | 301 | W = sparse(max(G,G')); 302 | case {lower('Cosine')} 303 | if ~options.bNormalized 304 | [nSmp, nFea] = size(fea); 305 | if issparse(fea) 306 | fea2 = fea'; 307 | feaNorm = sum(fea2.^2,1).^.5; 308 | for i = 1:nSmp 309 | fea2(:,i) = fea2(:,i) ./ max(1e-10,feaNorm(i)); 310 | end 311 | fea = fea2'; 312 | clear fea2; 313 | else 314 | feaNorm = sum(fea.^2,2).^.5; 315 | for i = 1:nSmp 316 | fea(i,:) = fea(i,:) ./ max(1e-12,feaNorm(i)); 317 | end 318 | end 319 | 320 | end 321 | 322 | if options.k > 0 323 | G = zeros(nSmp*(options.k+1),3); 324 | idNow = 0; 325 | for i=1:nLabel 326 | classIdx = find(options.gnd==Label(i)); 327 | D = fea(classIdx,:)*fea(classIdx,:)'; 328 | [dump idx] = sort(-D,2); % sort each row 329 | clear D; 330 | idx = idx(:,1:options.k+1); 331 | dump = -dump(:,1:options.k+1); 332 | 333 | nSmpClass = length(classIdx)*(options.k+1); 334 | G(idNow+1:nSmpClass+idNow,1) = repmat(classIdx,[options.k+1,1]); 335 | G(idNow+1:nSmpClass+idNow,2) = classIdx(idx(:)); 336 | G(idNow+1:nSmpClass+idNow,3) = dump(:); 337 | idNow = idNow+nSmpClass; 338 | clear dump idx 339 | end 340 | G = sparse(G(:,1),G(:,2),G(:,3),nSmp,nSmp); 341 | else 342 | G = zeros(nSmp,nSmp); 343 | for i=1:nLabel 344 | classIdx = find(options.gnd==Label(i)); 345 | G(classIdx,classIdx) = fea(classIdx,:)*fea(classIdx,:)'; 346 | end 347 | end 348 | 349 | if ~options.bSelfConnected 350 | for i=1:size(G,1) 351 | G(i,i) = 0; 352 | end 353 | end 354 | 355 | W = sparse(max(G,G')); 356 | otherwise 357 | error('WeightMode does not exist!'); 358 | end 359 | elapse = cputime - tmp_T; 360 | return; 361 | end 362 | 363 | 364 | if strcmpi(options.NeighborMode,'KNN') && (options.k > 0) 365 | if strcmpi(options.Metric,'Euclidean') 366 | G = zeros(nSmp*(options.k+1),3); 367 | for i = 1:ceil(nSmp/BlockSize) 368 | if i == ceil(nSmp/BlockSize) 369 | smpIdx = (i-1)*BlockSize+1:nSmp; 370 | dist = EuDist2(fea(smpIdx,:),fea,0); 371 | dist = full(dist); 372 | [dump idx] = sort(dist,2); % sort each row 373 | idx = idx(:,1:options.k+1); 374 | dump = dump(:,1:options.k+1); 375 | if ~bBinary 376 | dump = exp(-dump/(2*options.t^2)); 377 | end 378 | 379 | G((i-1)*BlockSize*(options.k+1)+1:nSmp*(options.k+1),1) = repmat(smpIdx',[options.k+1,1]); 380 | G((i-1)*BlockSize*(options.k+1)+1:nSmp*(options.k+1),2) = idx(:); 381 | if ~bBinary 382 | G((i-1)*BlockSize*(options.k+1)+1:nSmp*(options.k+1),3) = dump(:); 383 | else 384 | G((i-1)*BlockSize*(options.k+1)+1:nSmp*(options.k+1),3) = 1; 385 | end 386 | else 387 | smpIdx = (i-1)*BlockSize+1:i*BlockSize; 388 | dist = EuDist2(fea(smpIdx,:),fea,0); 389 | dist = full(dist); 390 | [dump idx] = sort(dist,2); % sort each row 391 | idx = idx(:,1:options.k+1); 392 | dump = dump(:,1:options.k+1); 393 | if ~bBinary 394 | dump = exp(-dump/(2*options.t^2)); 395 | end 396 | 397 | G((i-1)*BlockSize*(options.k+1)+1:i*BlockSize*(options.k+1),1) = repmat(smpIdx',[options.k+1,1]); 398 | G((i-1)*BlockSize*(options.k+1)+1:i*BlockSize*(options.k+1),2) = idx(:); 399 | if ~bBinary 400 | G((i-1)*BlockSize*(options.k+1)+1:i*BlockSize*(options.k+1),3) = dump(:); 401 | else 402 | G((i-1)*BlockSize*(options.k+1)+1:i*BlockSize*(options.k+1),3) = 1; 403 | end 404 | end 405 | end 406 | 407 | W = sparse(G(:,1),G(:,2),G(:,3),nSmp,nSmp); 408 | else 409 | if ~options.bNormalized 410 | [nSmp, nFea] = size(fea); 411 | if issparse(fea) 412 | fea2 = fea'; 413 | clear fea; 414 | for i = 1:nSmp 415 | fea2(:,i) = fea2(:,i) ./ max(1e-10,sum(fea2(:,i).^2,1).^.5); 416 | end 417 | fea = fea2'; 418 | clear fea2; 419 | else 420 | feaNorm = sum(fea.^2,2).^.5; 421 | for i = 1:nSmp 422 | fea(i,:) = fea(i,:) ./ max(1e-12,feaNorm(i)); 423 | end 424 | end 425 | end 426 | 427 | G = zeros(nSmp*(options.k+1),3); 428 | for i = 1:ceil(nSmp/BlockSize) 429 | if i == ceil(nSmp/BlockSize) 430 | smpIdx = (i-1)*BlockSize+1:nSmp; 431 | dist = fea(smpIdx,:)*fea'; 432 | dist = full(dist); 433 | [dump idx] = sort(-dist,2); % sort each row 434 | idx = idx(:,1:options.k+1); 435 | dump = -dump(:,1:options.k+1); 436 | 437 | G((i-1)*BlockSize*(options.k+1)+1:nSmp*(options.k+1),1) = repmat(smpIdx',[options.k+1,1]); 438 | G((i-1)*BlockSize*(options.k+1)+1:nSmp*(options.k+1),2) = idx(:); 439 | G((i-1)*BlockSize*(options.k+1)+1:nSmp*(options.k+1),3) = dump(:); 440 | else 441 | smpIdx = (i-1)*BlockSize+1:i*BlockSize; 442 | dist = fea(smpIdx,:)*fea'; 443 | dist = full(dist); 444 | [dump idx] = sort(-dist,2); % sort each row 445 | idx = idx(:,1:options.k+1); 446 | dump = -dump(:,1:options.k+1); 447 | 448 | G((i-1)*BlockSize*(options.k+1)+1:i*BlockSize*(options.k+1),1) = repmat(smpIdx',[options.k+1,1]); 449 | G((i-1)*BlockSize*(options.k+1)+1:i*BlockSize*(options.k+1),2) = idx(:); 450 | G((i-1)*BlockSize*(options.k+1)+1:i*BlockSize*(options.k+1),3) = dump(:); 451 | end 452 | end 453 | 454 | W = sparse(G(:,1),G(:,2),G(:,3),nSmp,nSmp); 455 | end 456 | 457 | if strcmpi(options.WeightMode,'Binary') 458 | W(find(W)) = 1; 459 | end 460 | 461 | if isfield(options,'bSemiSupervised') && options.bSemiSupervised 462 | tmpgnd = options.gnd(options.semiSplit); 463 | 464 | Label = unique(tmpgnd); 465 | nLabel = length(Label); 466 | G = zeros(sum(options.semiSplit),sum(options.semiSplit)); 467 | for idx=1:nLabel 468 | classIdx = tmpgnd==Label(idx); 469 | G(classIdx,classIdx) = 1; 470 | end 471 | Wsup = sparse(G); 472 | if ~isfield(options,'SameCategoryWeight') 473 | options.SameCategoryWeight = 1; 474 | end 475 | W(options.semiSplit,options.semiSplit) = (Wsup>0)*options.SameCategoryWeight; 476 | end 477 | 478 | if ~options.bSelfConnected 479 | for i=1:size(W,1) 480 | W(i,i) = 0; 481 | end 482 | end 483 | 484 | W = max(W,W'); 485 | 486 | elapse = cputime - tmp_T; 487 | return; 488 | end 489 | 490 | 491 | % strcmpi(options.NeighborMode,'KNN') & (options.k == 0) 492 | % Complete Graph 493 | 494 | if strcmpi(options.Metric,'Euclidean') 495 | W = EuDist2(fea,[],0); 496 | W = exp(-W/(2*options.t^2)); 497 | else 498 | if ~options.bNormalized 499 | % feaNorm = sum(fea.^2,2).^.5; 500 | % fea = fea ./ repmat(max(1e-10,feaNorm),1,size(fea,2)); 501 | [nSmp, nFea] = size(fea); 502 | if issparse(fea) 503 | fea2 = fea'; 504 | feaNorm = sum(fea2.^2,1).^.5; 505 | for i = 1:nSmp 506 | fea2(:,i) = fea2(:,i) ./ max(1e-10,feaNorm(i)); 507 | end 508 | fea = fea2'; 509 | clear fea2; 510 | else 511 | feaNorm = sum(fea.^2,2).^.5; 512 | for i = 1:nSmp 513 | fea(i,:) = fea(i,:) ./ max(1e-12,feaNorm(i)); 514 | end 515 | end 516 | end 517 | 518 | % W = full(fea*fea'); 519 | W = fea*fea'; 520 | end 521 | 522 | if ~options.bSelfConnected 523 | for i=1:size(W,1) 524 | W(i,i) = 0; 525 | end 526 | end 527 | 528 | W = max(W,W'); 529 | 530 | 531 | 532 | elapse = cputime - tmp_T; 533 | 534 | 535 | function D = EuDist2(fea_a,fea_b,bSqrt) 536 | % Euclidean Distance matrix 537 | % D = EuDist(fea_a,fea_b) 538 | % fea_a: nSample_a * nFeature 539 | % fea_b: nSample_b * nFeature 540 | % D: nSample_a * nSample_a 541 | % or nSample_a * nSample_b 542 | 543 | 544 | if ~exist('bSqrt','var') 545 | bSqrt = 1; 546 | end 547 | 548 | 549 | if (~exist('fea_b','var')) | isempty(fea_b) 550 | [nSmp, nFea] = size(fea_a); 551 | 552 | aa = sum(fea_a.*fea_a,2); 553 | ab = fea_a*fea_a'; 554 | 555 | aa = full(aa); 556 | ab = full(ab); 557 | 558 | if bSqrt 559 | D = sqrt(repmat(aa, 1, nSmp) + repmat(aa', nSmp, 1) - 2*ab); 560 | D = real(D); 561 | else 562 | D = repmat(aa, 1, nSmp) + repmat(aa', nSmp, 1) - 2*ab; 563 | end 564 | 565 | D = max(D,D'); 566 | D = D - diag(diag(D)); 567 | D = abs(D); 568 | else 569 | [nSmp_a, nFea] = size(fea_a); 570 | [nSmp_b, nFea] = size(fea_b); 571 | 572 | aa = sum(fea_a.*fea_a,2); 573 | bb = sum(fea_b.*fea_b,2); 574 | ab = fea_a*fea_b'; 575 | 576 | aa = full(aa); 577 | bb = full(bb); 578 | ab = full(ab); 579 | 580 | if bSqrt 581 | D = sqrt(repmat(aa, 1, nSmp_b) + repmat(bb', nSmp_a, 1) - 2*ab); 582 | D = real(D); 583 | else 584 | D = repmat(aa, 1, nSmp_b) + repmat(bb', nSmp_a, 1) - 2*ab; 585 | end 586 | 587 | D = abs(D); 588 | end 589 | 590 | -------------------------------------------------------------------------------- /func/select_labeled.m: -------------------------------------------------------------------------------- 1 | function [Xl, Xu, Yl, Yu, nonL_indx] = select_labeled(X, Y, num) 2 | 3 | c = length(unique(Y)); 4 | Xl=[]; 5 | Yl=[]; 6 | Xu=[]; 7 | Yu=[]; 8 | nonL_indx=[]; 9 | for i=1:c 10 | Ind_c=find(Y==i); 11 | num_c=length(Ind_c); 12 | rand_Ind=randperm(num_c,num); 13 | rand_Ind_non=setdiff(linspace(1,num_c,num_c),rand_Ind); 14 | nonL_indx=[nonL_indx,Ind_c(rand_Ind_non)']; 15 | Xc=X(:,Ind_c(rand_Ind)); 16 | Yc=Y(Ind_c(rand_Ind)); 17 | Xl=[Xl,Xc]; 18 | Yl=[Yl;Yc]; 19 | Xc_non=X(:,Ind_c(rand_Ind_non)); 20 | Yc_non=Y(Ind_c(rand_Ind_non)); 21 | Xu=[Xu,Xc_non]; 22 | Yu=[Yu;Yc_non]; 23 | end 24 | 25 | end 26 | 27 | -------------------------------------------------------------------------------- /office.m: -------------------------------------------------------------------------------- 1 | clc; 2 | close all; 3 | clear all; 4 | 5 | %% data loader 6 | folder_now = pwd; addpath([folder_now, '\data']); 7 | 8 | %% function loader 9 | folder_now = pwd; addpath([folder_now, '\func']); 10 | 11 | %% parameters setting 12 | options.k = 20; % dimensionality 13 | options.lambda = 0.05; % scale regularization 14 | options.gamma = 0.01; % projected clustering 15 | T = 5; % iteration 16 | lp=1; 17 | %% DA tasks 18 | srcStr = {'Caltech10','Caltech10','Caltech10','amazon','amazon','amazon','webcam','webcam','webcam','dslr','dslr','dslr'}; 19 | tgtStr = {'amazon','webcam','dslr','Caltech10','webcam','dslr','Caltech10','amazon','dslr','Caltech10','amazon','webcam'}; 20 | RES=[]; 21 | 22 | for iData = 1:12 23 | wrg=0; 24 | IIDD=[]; 25 | 26 | accTCA_s=[]; accTCA_t=[]; 27 | accJDA_s=[]; accJDA_t=[]; 28 | accBDA_s=[]; accBDA_t=[]; 29 | accVDA_s=[]; accVDA_t=[]; 30 | accJGSA_s=[]; accJGSA_t=[]; 31 | accMEDA_s=[]; accMEDA_t=[]; 32 | accFSDA_s=[]; accFSDA_t=[]; 33 | 34 | for iter=1:1000 35 | 36 | iter 37 | src = char(srcStr{iData}); 38 | tgt = char(tgtStr{iData}); 39 | data = strcat(src,'_vs_',tgt); 40 | 41 | %% source domain 42 | load(['data/' src '_SURF_L10.mat']); 43 | fts = fts ./ repmat(sum(fts,2),1,size(fts,2)); 44 | Xs = zscore(fts,1); 45 | Xs = Xs'; 46 | Ys = labels; 47 | 48 | %% target domain 49 | load(['data/' tgt '_SURF_L10.mat']); 50 | fts = fts ./ repmat(sum(fts,2),1,size(fts,2)); 51 | Xt = zscore(fts,1); 52 | Xt = Xt'; 53 | Yt = labels; 54 | 55 | %% some statistical information 56 | m=size(Xs,1); 57 | ns=size(Xs,2); 58 | nt=size(Xt,2); 59 | n=ns+nt; 60 | C=length(unique(Ys)); 61 | 62 | %% random selection 63 | 64 | num=5; % source labeled number 65 | [Xs_l,Xs_u,Ys_l,Ys_u] = select_labeled(Xs, Ys, num); 66 | 67 | %% run TCA 68 | [acc_s,acc_t] = runTCA(Xs_l',Xs_u',Xt',Ys_l,Ys_u,Yt,lp); 69 | acc_s=acc_s*100; 70 | acc_t=acc_t*100; 71 | fprintf('TCA: \n'); 72 | fprintf('Grap_source+acc_s=%0.1f\n',full(acc_s)); 73 | fprintf('Grap_source+acc_t=%0.1f\n',full(acc_t)); 74 | accTCA_s(1,iter)=acc_s; 75 | accTCA_t(1,iter)=acc_t; 76 | 77 | %% run JDA 78 | [acc_s,acc_t] = runJDA(Xs_l',Xs_u',Xt',Ys_l,Ys_u,Yt,lp); 79 | acc_s=acc_s*100; 80 | acc_t=acc_t*100; 81 | fprintf('JDA: \n'); 82 | fprintf('Grap_source+acc_s=%0.1f\n',full(acc_s)); 83 | fprintf('Grap_source+acc_t=%0.1f\n',full(acc_t)); 84 | accJDA_s(1,iter)=acc_s; 85 | accJDA_t(1,iter)=acc_t; 86 | 87 | %% run BDA 88 | [acc_s,acc_t] = runBDA(Xs_l',Xs_u',Xt',Ys_l,Ys_u,Yt,lp); 89 | acc_s=acc_s*100; 90 | acc_t=acc_t*100; 91 | fprintf('BDA: \n'); 92 | fprintf('Grap_source+acc_s=%0.1f\n',full(acc_s)); 93 | fprintf('Grap_source+acc_t=%0.1f\n',full(acc_t)); 94 | accBDA_s(1,iter)=acc_s; 95 | accBDA_t(1,iter)=acc_t; 96 | 97 | %% run VDA 98 | [acc_s,acc_t] = runVDA(Xs_l',Xs_u',Xt',Ys_l,Ys_u,Yt,lp); 99 | acc_s=acc_s*100; 100 | acc_t=acc_t*100; 101 | fprintf('VDA: \n'); 102 | fprintf('Grap_source+acc_s=%0.1f\n',full(acc_s)); 103 | fprintf('Grap_source+acc_t=%0.1f\n',full(acc_t)); 104 | accVDA_s(1,iter)=acc_s; 105 | accVDA_t(1,iter)=acc_t; 106 | 107 | %% run JGSA 108 | [acc_s,acc_t] = runJGSA(Xs_l',Xs_u',Xt',Ys_l,Ys_u,Yt,lp); 109 | acc_s=acc_s*100; 110 | acc_t=acc_t*100; 111 | fprintf('JGSA: \n'); 112 | fprintf('Grap_source+acc_s=%0.1f\n',full(acc_s)); 113 | fprintf('Grap_source+acc_t=%0.1f\n',full(acc_t)); 114 | accJGSA_s(1,iter)=acc_s; 115 | accJGSA_t(1,iter)=acc_t; 116 | 117 | %% run MEDA 118 | [acc_s,acc_t] = runMEDA(Xs_l',Xs_u',Xt',Ys_l,Ys_u,Yt,lp); 119 | acc_s=acc_s*100; 120 | acc_t=acc_t*100; 121 | fprintf('MEDA: \n'); 122 | fprintf('Grap_source+acc_s=%0.1f\n',full(acc_s)); 123 | fprintf('Grap_source+acc_t=%0.1f\n',full(acc_t)); 124 | accMEDA_s(1,iter)=acc_s; 125 | accMEDA_t(1,iter)=acc_t; 126 | 127 | %% data normalization 128 | X = [Xs_l,Xs_u,Xt]; 129 | X = X*diag(sparse(1./sqrt(sum(X.^2)))); 130 | Xs_l = X(:,1:size(Xs_l,2)); 131 | Xs_u = X(:,size(Xs_l,2)+1:ns); 132 | Xs=[Xs_l,Xs_u]; 133 | Xt = X(:,ns+1:end); 134 | ns_l=size(Xs_l,2); 135 | 136 | %% initialization 137 | fprintf('FSDA: data=%s\n',data); 138 | %% initialize projection 139 | [Z] = WUDA1(Xs,Xt,options); 140 | Z = Z*diag(sparse(1./sqrt(sum(Z.^2)))); 141 | Zs = Z(:,1:size(Xs,2)); 142 | Zt = Z(:,size(Xs,2)+1:end); 143 | Zs_l=Zs(:,1:size(Xs_l,2)); 144 | Zs_u=Zs(:,size(Xs_l,2)+1:ns); 145 | 146 | %% initialize source labels 147 | kk=10; 148 | [Cls] = GraphClassifier(Zs_l,Zs_u,Ys_l,kk); 149 | Cls_su=Cls; 150 | Ys0=[Ys_l;Cls_su]; 151 | acc_su = length(find(Ys0==[Ys_l;Ys_u]))/length(Ys0)*100; 152 | 153 | %% initialize target labels 154 | kk=20; 155 | [Cls] = GraphClassifier([Zs_l,Zs_u],Zt,Ys0,kk); 156 | Cls_tu=Cls; 157 | acc_tu = length(find(Cls_tu==Yt))/length(Yt)*100; 158 | Yt0 = Cls_tu; 159 | 160 | %% initialize cluster centriods 161 | Fs=LabelFormat(Ys0); 162 | Gs=Fs/(Fs'*Fs); 163 | Ft=LabelFormat(Yt0); 164 | Gt=Ft/(Ft'*Ft); 165 | 166 | try 167 | MC=[Gs*Gs',-Gs*Gt'; 168 | -Gt*Gs',Gt*Gt']; 169 | IIDD=[IIDD,iter]; 170 | catch 171 | wrg=wrg+1; 172 | accTCA_s(1,iter)=0; 173 | accTCA_t(1,iter)=0; 174 | accJDA_s(1,iter)=0; 175 | accJDA_t(1,iter)=0; 176 | accBDA_s(1,iter)=0; 177 | accBDA_t(1,iter)=0; 178 | accVDA_s(1,iter)=0; 179 | accVDA_t(1,iter)=0; 180 | accJGSA_s(1,iter)=0; 181 | accJGSA_t(1,iter)=0; 182 | accMEDA_s(1,iter)=0; 183 | accMEDA_t(1,iter)=0; 184 | accFSDA_s(1,iter)=0; 185 | accFSDA_t(1,iter)=0; 186 | continue; 187 | end 188 | MC(isinf(MC)) = 0; 189 | %% Start 190 | for t = 1:T 191 | 192 | %% update projection 193 | [Z,A] = WUDA2(Xs,Xt,Ys0,Yt0,options,MC); 194 | Z = Z*diag(sparse(1./sqrt(sum(Z.^2)))); 195 | Zs = Z(:,1:size(Xs,2)); 196 | Zt = Z(:,size(Xs,2)+1:end); 197 | Zs_l=Zs(:,1:ns_l); 198 | Zs_u=Zs(:,ns_l+1:end); 199 | 200 | %% update cluster centriods 201 | mu1=0.01; mu2=0.01; 202 | Fs=Fs'; 203 | Ft=Ft'; 204 | As=A'*Xs; 205 | At=A'*Xt; 206 | 207 | [Gs] = SolveG1(As, At, Gs, Gt, Fs, mu1); 208 | [Gt] = SolveG2(As, At, Gs, Gt, Ft, mu2); 209 | 210 | try 211 | MC=[Gs*Gs',-Gs*Gt'; 212 | -Gt*Gs',Gt*Gt']; 213 | catch 214 | wrg=wrg+1; 215 | accTCA_s(1,iter)=0; 216 | accTCA_t(1,iter)=0; 217 | accJDA_s(1,iter)=0; 218 | accJDA_t(1,iter)=0; 219 | accBDA_s(1,iter)=0; 220 | accBDA_t(1,iter)=0; 221 | accVDA_s(1,iter)=0; 222 | accVDA_t(1,iter)=0; 223 | accJGSA_s(1,iter)=0; 224 | accJGSA_t(1,iter)=0; 225 | accMEDA_s(1,iter)=0; 226 | accMEDA_t(1,iter)=0; 227 | accFSDA_s(1,iter)=0; 228 | accFSDA_t(1,iter)=0; 229 | break; 230 | end 231 | 232 | MC(isinf(MC)) = 0; 233 | 234 | %% update source soft labels 235 | delta_s=0.01; 236 | Cs=As*Gs; 237 | Asu=As(:,ns_l+1:end); 238 | kk=10; 239 | [Cls] = GraphClassifier3(Zs_l,Zs_u,Ys_l,delta_s,Cs,Asu,kk); 240 | Cls_su=Cls; 241 | Ys0=[Ys_l;Cls_su]; 242 | acc_slu = length(find(Ys0==[Ys_l;Ys_u]))/length(Ys0)*100; 243 | if (t==5) 244 | accFSDA_s(1,iter)=acc_slu; 245 | end 246 | if (t==5) 247 | fprintf('Grap_source+acc_s=%0.1f\n',full(acc_slu)); 248 | end 249 | %% update target soft labels 250 | delta_t=0.01; 251 | Ct=At*Gt; 252 | kk=20; 253 | [Cls] = GraphClassifier4([Zs_l,Zs_u],Zt,Ys0,delta_t,At,Ct,kk); 254 | Cls_tu=Cls; 255 | acc_tu = length(find(Cls_tu==Yt))/length(Yt)*100; 256 | if (t==5) 257 | accFSDA_t(1,iter)=acc_tu; 258 | end 259 | if (t==5) 260 | fprintf('Grap_target+acc_t=%0.1f\n',full(acc_tu)); 261 | end 262 | 263 | Yt0=Cls_tu; 264 | Fs=LabelFormat(Ys0); 265 | Ft=LabelFormat(Yt0); 266 | 267 | end 268 | if (iter-wrg)==10 269 | break; 270 | end 271 | end 272 | accTCA_s=accTCA_s(IIDD); 273 | accTCA_t=accTCA_t(IIDD); 274 | accJDA_s=accJDA_s(IIDD); 275 | accJDA_t=accJDA_t(IIDD); 276 | accBDA_s=accBDA_s(IIDD); 277 | accBDA_t=accBDA_t(IIDD); 278 | accVDA_s=accVDA_s(IIDD); 279 | accVDA_t=accVDA_t(IIDD); 280 | accJGSA_s=accJGSA_s(IIDD); 281 | accJGSA_t=accJGSA_t(IIDD); 282 | accMEDA_s=accMEDA_s(IIDD); 283 | accMEDA_t=accMEDA_t(IIDD); 284 | accFSDA_s=accFSDA_s(IIDD); 285 | accFSDA_t=accFSDA_t(IIDD); 286 | 287 | res1=[mean(accTCA_s),mean(accJDA_s),mean(accBDA_s),mean(accVDA_s),mean(accJGSA_s),mean(accMEDA_s),mean(accFSDA_s)]; 288 | res1=roundn(res1,-1); 289 | res2=[mean(accTCA_t),mean(accJDA_t),mean(accBDA_t),mean(accVDA_t),mean(accJGSA_t),mean(accMEDA_t),mean(accFSDA_t)]; 290 | res2=roundn(res2,-1); 291 | res3=[std(accTCA_s,0,2),std(accJDA_s,0,2),std(accBDA_s,0,2),std(accVDA_s,0,2),std(accJGSA_s,0,2),std(accMEDA_s,0,2),std(accFSDA_s,0,2)]; 292 | res3=roundn(res3,-1); 293 | res4=[std(accTCA_t,0,2),std(accJDA_t,0,2),std(accBDA_t,0,2),std(accVDA_t,0,2),std(accJGSA_t,0,2),std(accMEDA_t,0,2),std(accFSDA_t,0,2)]; 294 | res4=roundn(res4,-1); 295 | res1234=[res1,res2;res3,res4]; 296 | RES=[RES;res1234]; 297 | end -------------------------------------------------------------------------------- /runBDA.m: -------------------------------------------------------------------------------- 1 | function [acc_s,acc_t] = runBDA(Xs_l,Xs_u,Xt,Ys_l,Ys_u,Yt,lp) 2 | 3 | %% Set algorithm options 4 | if lp==1 5 | options.lambda = 0.05; 6 | options.dim = 20; 7 | else 8 | options.lambda = 0.1; 9 | options.dim = 100; 10 | end 11 | 12 | options.T = 5; 13 | options.mu = 0; 14 | options.mode = 'W-BDA'; 15 | %% Run algorithm 16 | [acc_s,acc_t] = BDA(Xs_l,Xs_u,Xt,Ys_l,Ys_u,Yt,options); 17 | end 18 | 19 | -------------------------------------------------------------------------------- /runJDA.m: -------------------------------------------------------------------------------- 1 | function [acc_s,acc_t] = runJDA(Xs_l,Xs_u,Xt,Ys_l,Ys_u,Yt,lp) 2 | 3 | %% Set algorithm options 4 | if lp==1 5 | options.lambda = 0.05; 6 | options.dim = 20; 7 | else 8 | options.lambda = 0.1; 9 | options.dim = 100; 10 | end 11 | options.T = 5; 12 | %% Run algorithm 13 | [acc_s,acc_t] = JDA(Xs_l,Xs_u,Xt,Ys_l,Ys_u,Yt,options); 14 | end -------------------------------------------------------------------------------- /runJGSA.m: -------------------------------------------------------------------------------- 1 | function [acc_s,acc_t] = runJGSA(Xs_l,Xs_u,Xt,Ys_l,Ys_u,Yt,lp) 2 | 3 | % Set algorithm parameters 4 | if lp==1 5 | options.k = 20; 6 | else 7 | options.k = 100; 8 | end % subspace base dimension 9 | options.ker = 'primal'; % kernel type, default='linear' options: linear, primal, gauss, poly 10 | 11 | options.T = 5; % #iterations, default=10 12 | 13 | options.alpha= 1; % the parameter for subspace divergence ||A-B|| 14 | options.mu = 1; % the parameter for target variance 15 | options.beta = 0.1; % the parameter for P and Q (source discriminaiton) 16 | options.gamma = 2; % the parameter for kernel 17 | 18 | Xs = [Xs_l;Xs_u]; 19 | ns_l = size(Xs_l,1); 20 | Xs = normr(Xs)'; 21 | Xt = normr(Xt)'; 22 | Xs_l = Xs(:,1:ns_l); 23 | Xs_u = Xs(:,ns_l+1:end); 24 | [acc_s,acc_t] = JGSA(Xs_l,Xs_u,Xt,Ys_l,Ys_u,Yt,options); 25 | end -------------------------------------------------------------------------------- /runMEDA.m: -------------------------------------------------------------------------------- 1 | function [acc_s,acc_t] = runMEDA(Xs_l,Xs_u,Xt,Ys_l,Ys_u,Yt,lp) 2 | if lp==1 3 | options.d = 20; 4 | else 5 | options.d = 100; 6 | end 7 | options.rho = 1.0; 8 | options.p = 10; 9 | options.lambda = 10.0; 10 | options.eta = 0.1; 11 | options.T = 5; 12 | [acc_s,acc_t] = MEDA(Xs_l,Xs_u,Xt,Ys_l,Ys_u,Yt,options); 13 | 14 | end 15 | 16 | -------------------------------------------------------------------------------- /runTCA.m: -------------------------------------------------------------------------------- 1 | function [acc_s,acc_t] = runTCA(Xs_l,Xs_u,Xt,Ys_l,Ys_u,Yt,lp) 2 | 3 | %% Set algorithm options 4 | if lp==1 5 | options.lambda = 0.05; 6 | options.dim = 20; 7 | else 8 | options.lambda = 0.1; 9 | options.dim = 100; 10 | end 11 | %% Run algorithm 12 | [acc_s,acc_t] = TCA(Xs_l,Xs_u,Xt,Ys_l,Ys_u,Yt,options); 13 | end -------------------------------------------------------------------------------- /runVDA.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WWLoveTransfer/SLSA-DA/e7aa8204886b4fa9c085e7dc1f1a233ec36f83bf/runVDA.m --------------------------------------------------------------------------------