I am trying to use canonical correlation to predict a set of held out x variables from a multivariable set of X and Y data. In this particular case I am only interested in X. In the real data X is a behavioural variable and Y is a biomarker.

My approach so far involves:

  1. running the training CCA
  2. apply the CCA weights to the held out Y data (V = Y * B)
  3. using linear regression to estimate the unknown U value (assumes V and U are linearly related, as CCA should find)
  4. applying the same CCA weights backwards to find X (X = U / A)

I've pasted some generalized code below using the fisheriris dataset in matlab. It produces high correlations between predicted and real values but I'm unsure if this is correct.

load fisheriris
X = meas(:,1:2);
Y = meas(:,3:4);

N = length(X); %sample size

for subj = 1:N

    trainN = 1:N;
    trainN(subj) = []; % remove left-out subject

    Yheld = Y(subj,:); %held out data used to predict held out X

    %training data
    Xtrain = X(trainN,:); %held in data
    Ytrain = Y(trainN,:);

    %remove mean
    XTrainCentre = mean(Xtrain);
    YTrainCentre = mean(Ytrain);
    Xtrain = Xtrain - XTrainCentre;
    Ytrain = Ytrain - YTrainCentre;

    %This computes CCA on the training data
    [A,B,r,U,V,stats] = canoncorr(Xtrain,Ytrain);

    %Only interested in the first Mode
    Mode = 1;

    % build linear regression model using U and V
    y = U(:,Mode);                          % want to predict U
    x = [ones(length(V(:,1)),1),V(:,Mode)]; % from V
    beta = regress(y,x);                    % get regression coefficient

    % Calculate held-out V using the training data weights
    % see matlab help: V = (Y-repmat(mean(Y),N,1))*B
    Vpred = (Yheld - YTrainCentre) * B(:,Mode);

    % Calculate held-out U via linear regression equation from training set
    Upred = beta(1) + (Vpred * beta(2));

    % Apply weights, in the opposite direction, to get raw behaviour
    % U = X * A
    % X = U / A
    Xpred(subj,:,Mode) = Upred ./ A(:,Mode);

% prediction accuracy (by correlating real and predicted values).
for beh = 1:size(X,2)
        [r,p] = corr(X(:,beh),Xpred(:,beh));
        disp(['For variable: ',num2str(beh),', r = ',num2str(r),', p = ',num2str(p)])


1 Answer 1


The regression model is confusing. The intercept term is going to be zero as you demeaned the data prior to CCA (which is also a requirement). The regression model will give you back the CCA r-value between the first projected columns of U and V. Everything thereon out becomes circular. The assumption that U and V are linearly related is hazy; if anything the cross cov of U and V should produce an identity matrix. An alternate method for cross validation is splitting the data into 75%, 25% parts, and obtain cross-validated r values. That is, find A and B from the training data, apply A and B to held out data and see how correlated U_cv and V_cv are in relation to original model.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.