# Efficient orthogonal matrix parameterization

#1

I’m trying to parameterize orthogonal matrix via a series of Givens rotations as follows

data{
int TT;    //TT * TT matrix
}
transformed data{
int dim_theta_i2toQ=TT*(Q-1)-(Q-1)*(Q+2)/2;   //dimentionality of dim_theta_i2toQ
}
parameters {
vector<lower=-pi(),upper=pi()>[TT-1] theta_i1;             //theta[1,j]; j=2,...,TT
vector<lower=0,upper=pi()>[dim_theta_i2toQ] theta_i2toQ;   //theta[i,j]; i=2,...,TT-1; j=i+1,...,TT
}   //There is bijection between theta=[theta_i1,theta_i2toQ] (theta_i1 is in [-pi,pi] and theta_i2 is in [0,pi]) and TT*TT orthogonal matrix U

transformed parameters {
matrix[TT,TT] U_transpose=diag_matrix(rep_vector(1,TT));

{
int index=1;
real cos1;
real sin1;
vector[TT] Ui_tmp;
vector[TT] Uj_tmp;

for(i in 1:(TT-1)){
for(j in (i+1):TT){
cos1=cos(theta_i1[index]);
sin1=sin(theta_i1[index]);
Ui_tmp=cos1*U_transpose[:,i]-sin1*U_transpose[:,j];
Uj_tmp=sin1*U_transpose[:,i]+cos1*U_transpose[:,j];
U_transpose[:,i]=Ui_tmp;
U_transpose[:,j]=Uj_tmp;
index+=1;
}
index=1;
}else{
for(j in (i+1):TT){
cos1=cos(theta_i2toQ[index]);
sin1=sin(theta_i2toQ[index]);
Ui_tmp=cos1*U_transpose[:,i]-sin1*U_transpose[:,j];
Uj_tmp=sin1*U_transpose[:,i]+cos1*U_transpose[:,j];
U_transpose[:,i]=Ui_tmp;
U_transpose[:,j]=Uj_tmp;
index+=1;
}
}
}
}


Mathematics about orthogonal matrix parameterization [1]:

This is part of my program, and I found it runs slowly. Could this orthogonal matrix parameterization be more efficient?

Thanks.

Reference:
[1] Matteson, D. S., & Tsay, R. S. (2017). Independent component analysis via distance covariance. Journal of the American Statistical Association , 112 (518), 623-637.

#2

It doesn’t run slow because it takes a long time to evaluate those loops; it runs slowly because the posterior geometry has a lot of curvature. It probably would be fair to say that we do not know a good transformation into an orthogonal matrix. There are more options (but not necessarily good ones) if you can restrict yourself to rotation matrices.

#3

Thanks Ben.

When I run with warmup=0, it takes very short time.
However, when warmup>=1, the time consumption increases super-linearly:

warmup=10, iter=20, adapt_delta=0.99, 4 chains in parallel 11.587s
warmup=100, iter=200, adapt_delta=0.99, 4 chains in parallel 1022.823s. Many parameters have Rhat>10.
warmup=1000, iter=2000, adapt_delta=0.99, 4 chains in parallel 7860.795s (about 131 minutes). All parameters have Rhat within (0.9992, 1.0068)

Does it indicate that my code is computational good but the model’s statistical efficiency can be improved?

For the final case (warmup=1000, iter=2000, adapt_delta=0.99, 4 chains in parallel), I strive to shorten the time, while keeping Rhat within 1.05 or 1.1. Do you think it a good idea to use less iterations (e.g. warmup=500, iter=1000) or smaller adapt_delta?

Thank you.

#4

All of that indicates that it is a difficult posterior distribution to draw from, so the first priority has to be getting that right, rather than the wall time that it takes to do it.

You have to have a positive warmup value (several hundred at least) to be able to adapt to the posterior distribution that you are drawing from so that you can get a good enough effective sample size to reliably estimate what you are interested in (assuming the mixing is fast enough for the effective sample size estimate to be a well-defined).

You have to eliminate the divergent transitions and often that implies increasing adapt_delta or finding a better parameterization. And we don’t know a universally better parameterization, so you might very well be stuck with waiting two hours.

#5

Dear, it is hard to figure out statistically more efficient parameterization. I just parameterized directly and this parameterization is at least correct.

In addition, the effective sample size of all parameters are above 1000 (1000 * 4 samples are kept), Rhat<1.01, as attached.

Thanks.

#6

There is no parameterization of the space of orthogonal matrix into the real numbers of the same dimension. The Givens rotations define a coordinate system that covers most, but not all, of the orthogonal matrix space as there is a singular line where the coordinates are undefined.

The same thing happens with a circle – you parameterize all but one point of a circle with angles [-pi, pi] but to parameterize the whole thing you need to consider another overlapping parameterization, say with angels [0, 2pi].

This is a basic feature of trying to work with a space that has a topology that isn’t the same as the real numbers, for example spheres, torii, and Steifel manifolds (which are the spaces of orthogonal matrices). In other words you can’t really build a model over orthogonal matrices the way Stan is currently configured.

#7

@betanalpha I think [-pi, pi), (-pi, pi], (0, 2pi], [0, 2pi) cover the whole circle, but cannot reflect the fact that -pi+eps and pi-eps are very close in the circle for small eps>0. Thank you for your enlightenment.

#8

\pi - \epsilon and \pi + \epsilon are far away in the parameterization but close in the circle. That inability of the parameterization to faithfully characterize “closeness” in the original space is one indication of the problem.

To more deeply understand the issue you’ll have to dip your toes into some differential geometry. Wikipedia has some oaky introductions, see for example https://en.wikipedia.org/wiki/Manifold.

#9

We have recently explored an alternative parameterization based on Householder reflections. It is similar to the way that Stan represents a unit circle, i.e. instead of mapping it to angles (which has the problem that Betancourt explained) an over-parameterized full vector is used and then normalized. In our case, a set of such vectors are used and then transformed onto the space of orthogonal matrices via a sequence of Householder reflections. The corresponding Stan code for Bayesian PCA using this method can be found here.
Feel free to try if that works any better in your case.

1 Like
#10

@bertschi Great.
Let me try.
Thanks a lot.