% This is the demo.m code of LSDT for transfer learning and recognition.

%% 10 classes-DeCAF (CNN deep features)
% parameters tuning:
% 1. feature normalization: norm_type
% 2. linear or nonlinear: ker_type
% 3. for nonlinear, the kernel parameter:kervar1

clc, clear all, close all;
% load data
% randomly select 20 samples per class from source domain (amazon and caltech data)
% randomly select 8 samples per class from source domain (webcam and dslr data)
% randomly select 3 labeled training samples per class from target domain

Class=10; % classes

norm_type=2;

fprintf('-------------Start generating data------------- \n');  
load('DeCAF_Data.mat');
% normalization
amazon_data{1}=amazon_data{1}./repmat(sum(amazon_data{1},2),1,size(amazon_data{1},2)); % layer 6
amazon_data{2}=amazon_data{2}./repmat(sum(amazon_data{2},2),1,size(amazon_data{2},2)); % layer 7
dslr_data{1}=dslr_data{1}./repmat(sum(dslr_data{1},2),1,size(dslr_data{1},2));
dslr_data{2}=dslr_data{2}./repmat(sum(dslr_data{2},2),1,size(dslr_data{2},2));
caltech_data{1}=caltech_data{1}./repmat(sum(caltech_data{1},2),1,size(caltech_data{1},2));
caltech_data{2}=caltech_data{2}./repmat(sum(caltech_data{2},2),1,size(caltech_data{2},2));
webcam_data{1}=webcam_data{1}./repmat(sum(webcam_data{1},2),1,size(webcam_data{1},2));
webcam_data{2}=webcam_data{2}./repmat(sum(webcam_data{2},2),1,size(webcam_data{2},2));
%}
SD=caltech_data;SD_label=caltech_label; % source data
TD=webcam_data;TD_label=webcam_label; % target data
load('DataSplitsOfficeCaltech\SameCategory_caltech-webcam_20RandomTrials_10Categories.mat');

layer_num=6;%7 or 6

for i=1:20 % 20 random splits
    Xs=SD{layer_num-5}(train.source{i},:)';source_label=SD_label(train.source{i});
    Xs_test=SD{layer_num-5}(test.source{i},:)';source_label_test=SD_label(test.source{i});
    Xt=TD{layer_num-5}(train.target{i},:)';target_label_train=TD_label(train.target{i});
    Xt_test=TD{layer_num-5}(test.target{i},:)';target_label_test=TD_label(test.target{i});

    ker_type=0; % 0:linear 1:nonlinear

    if ker_type==0
       Kernel='linear'; 
    else Kernel='gauss';
    end
    kervar1=0.05;% free parameter
    kervar2=10;% no use 

    if ker_type==0;
       X=[Xs Xt]; 
       Xs=[Xs Xt]; 
    else
       X=[Xs Xt Xt_test];
       Xs=[Xs Xt Xt_test];
    end

    dim=size(X,2);
    lambda1=1; 
    lambda2=1;
    maxiter=2;

    [C,A,obj,K,Ks,Kt,Kt_test]=lsdt(Xt,Xs,X,Xt_test,dim,lambda1,lambda2,maxiter,Kernel,kervar1,kervar2);  

% figure;
% imagesc(C); 
% colormap gray;
% plot(obj) 

    switch Kernel
        case 'linear'
             P = A'*X' ; % A'*X'
             Xt_new= P*Xs*C;
             Xt_test_new=P*Xt_test;%Xt_new(:,length(target_label_train)+1:end);
             Xs_new=P*Xs; 
        case 'gauss' 
             P = A'*X' ; % A'*X'
             Xt_new= P*Xs*C;
             Xt_test_new=P*Xt_test;%Xt_new(:,length(target_label_train)+1:end);
             Xs_new=P*Xs; 
    end

 
   % classifier
   % svm: the useage refers to the svmtrain.c file in libsvm toolbox
   Yat=[source_label;target_label_train];%
   Xat=[Xs(:,1:length(source_label)) Xt(:,1:length(target_label_train))]'; %
   model1 = svmtrain(Yat, Xat, '-c 1000 -g 1 -b 1 -t 0'); % -c:penalty coefficient;-t:kernel type;-g:gamma kernel parameter
   [ytest1, test_accuracy, prob_estimates] = svmpredict(target_label_test,Xt_test', model1, '-b 1');
   rate_svm(i)=test_accuracy(1);

   % ls

   Yat=[source_label;target_label_train];%target_label_train
   Xat=[Xs_new(:,1:length(source_label)),Xt_new(:,1:length(target_label_train))]';  % Xt_new
   Y=-1*ones(length(Yat),Class); 
   for j=1:length(Yat)   
       Y(j,Yat(j))=1; 
   end     
   % search the best regularization parameter
   a=[0.00000001,0.0000001,0.000001,0.00001,0.0001,0.001,0.005,0.01,0.05,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1,10,100];
   for j=1:length(a)
       w=(Xat'*Xat+a(j)*eye(size(Xat,2)))\(Xat'*Y);
       yte1=Xt_test_new'*w;
       rate4_1(i,j)=decision_class(yte1,target_label_test); 
   end
   rate_ls(i)=max(rate4_1(i,:));
   fprintf('%f,,%f\n',[rate_svm(i);rate_ls(i)])  
end           

ave_svm=mean(rate_svm)
sigm_svm=sqrt(mean(rate_svm.^2)-mean(rate_svm)^2)/sqrt(20)   
ave_ls=mean(rate_ls)
sigm_ls=sqrt(mean(rate_ls.^2)-mean(rate_ls)^2)/sqrt(20)   