Vespucci  1.0.0
pls.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright (C) 2014-2016 Wright State University - All Rights Reserved
3  Daniel P. Foose - Maintainer/Lead Developer
4 
5  This file is part of Vespucci.
6 
7  Vespucci is free software: you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation, either version 3 of the License, or
10  (at your option) any later version.
11 
12  Vespucci is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with Vespucci. If not, see <http://www.gnu.org/licenses/>.
19 *******************************************************************************/
22 
23 
43 bool Vespucci::Math::DimensionReduction::plsregress(arma::mat X, arma::mat Y,
44  int components, arma::mat &X_loadings,
45  arma::mat &Y_loadings,
46  arma::mat &X_scores,
47  arma::mat &Y_scores,
48  arma::mat &coefficients,
49  arma::mat &percent_variance,
50  arma::mat &fitted)
51 {
52  using namespace arma;
53  uword observations = X.n_rows;
54  uword predictors = X.n_cols;
55  uword responses = Y.n_cols;
56  //Mean centering
57  mat Xmeans = arma::mean(X);
58  mat Ymeans = arma::mean(Y);
59  //Octave does below with bsxfun. After optimization, this should hopefully not
60  // be slower.
61  X.each_row() -= Xmeans; //element-wise subtraction of mean
62  Y.each_row() -= Ymeans; //same
63 
64  mat S = trans(X) * Y;
65  mat R = zeros(predictors, components);
66  mat P = R;
67  mat V = R;
68  mat T = zeros(observations, components);
69  mat U = T;
70  mat Q = zeros(responses, components);
71  mat eigvec;
72  vec eigval;
73 
74  mat q;
75  mat r;
76  mat t;
77  mat nt;
78  mat p;
79  mat u;
80  mat v;
81  double max_eigval;
82  for (int i = 0; i < components; ++i){
83  eig_sym(eigval, eigvec, (trans(S) * S));
84  max_eigval = eigval.max();
85  uvec dom_index = find(eigval >= max_eigval);
86  uword dominant_index = dom_index(0);
87 
88  q = eigvec.col(dominant_index);
89 
90  r = S*q; //X block factor weights
91  t = X*r; //X block factor weights
92  t.each_row() -= mean(t); //center t
93  nt = arma::sqrt(t.t()*t); //compute norm (is arma::norm() the same?)
94  t.each_row() /= nt;
95  r.each_row() /= nt; //normalize
96 
97  p = X.t()*t; //X block factor loadings
98  q = Y.t()*t; //Y block factor loadings
99  u = Y*q; //Y block factor scores
100  v = p;
101 
102  //Ensure orthogonality
103  if (i > 0){
104  v = v - V*(V.t()*p);
105  u = u - T*(T.t()*u);
106  }
107  v.each_row() /= arma::sqrt(trans(v) * v); //normalize orthogonal loadings
108  S = S - v * (trans(v)*S); //deflate S wrt loadings
109  R.col(i) = r;
110  T.col(i) = t;
111  P.col(i) = p;
112  Q.col(i) = q;
113  U.col(i) = u;
114  V.col(i) = v;
115  }
116 
117  //Regression coefficients
118  mat B = R*trans(Q);
119  fitted = T*trans(Q);
120  fitted.each_row() += Ymeans;
121 
122  //Octave creates copies from inputs before sending to output. Doing same
123  //here just to be safe.
124  coefficients = B;
125  X_scores = T;
126  X_loadings = P;
127  Y_scores = U;
128  Y_loadings = Q;
129  //projection = R;
130  percent_variance.set_size(2, P.n_cols);
131  percent_variance.row(0) = sum(arma::abs(P)%arma::abs(P)) / sum(sum(arma::abs(X)%arma::abs(X)));
132  percent_variance.row(1) = sum(arma::abs(Q)%arma::abs(Q)) / sum(sum(arma::abs(Y)%arma::abs(Y)));
133  return true;
134 
135 }
VESPUCCI_EXPORT bool plsregress(arma::mat X, arma::mat Y, int components, arma::mat &X_loadings, arma::mat &Y_loadings, arma::mat &X_scores, arma::mat &Y_scores, arma::mat &coefficients, arma::mat &percent_variance, arma::mat &fitted)
Vespucci::MathDimensionReduction::plsregress PLS Regression Using SIMPLS algorithm. This is essentially a line-for-line rewrite of plsregress from the Octave statistics package. Copyright (C) 2012 Fernando Damian Nieuwveldt fdnieuwveldt@gmail.com This is an implementation of the SIMPLS algorithm: Reference: SIMPLS: An alternative approach to partial least squares regression. Chemometrics and Intelligent Laboratory Systems (1993)
Definition: pls.cpp:43