Identifiability issues with latent space network model

I’m trying to fit a latent space network model in Stan (loosely based on this Edward model; note that they only care about the MAP). Here’s the model:

data {
    int<lower=0> N;               // number of units
    int<lower=0> N_types;         // number of types
    int<lower=0, upper=1> G[N,N]; // connectivity matrix
    int unit_types[N];            // vector of unit types
    int<lower=0> embedding_dimension;
transformed data {
    row_vector[embedding_dimension] point1 = rep_vector(0, embedding_dimension)';  // an anchoring point for the embedding, at the origin
parameters {
    matrix[N_types, N_types] sbm;      // type-specific connectivity
    row_vector[embedding_dimension] Z[N-1];  // latent embedding
    real baseline;   // intercept
model {
    real dist;
    // likelihood
    for (i in 2:N) {
        dist = distance(point1,Z[i-1]);
        G[1,i] ~ bernoulli_logit(baseline + sbm[unit_types[1],unit_types[i]] - dist);
        G[i,1] ~ bernoulli_logit(baseline + sbm[unit_types[i],unit_types[1]] - dist);
        for (j in (i+1):N) {
            dist = distance(Z[i-1],Z[j-1]);
            G[i,j] ~ bernoulli_logit(baseline + sbm[unit_types[i],unit_types[j]] - dist);
            G[j,i] ~ bernoulli_logit(baseline + sbm[unit_types[j],unit_types[i]] - dist);

    // prior on type-specific connectivity
    for (i in 1:N_types) {
        for (j in 1:N_types) {
            sbm[i,j] ~ std_normal();

    // prior on latent embedding 
    for (i in 1:N-1) {
        Z[i] ~ std_normal();

    // prior on baseline - reflecting overall matrix sparsity 
    baseline ~ normal(-3,2);
generated quantities {
    int G_pred[N,N];
    real dist_pred;
    for (i in 2:N) {
        dist_pred = distance(point1,Z[i-1]);
        G_pred[1,i] = bernoulli_logit_rng(baseline + sbm[unit_types[1],unit_types[i]] - dist_pred);
        G_pred[i,1] = bernoulli_logit_rng(baseline + sbm[unit_types[i],unit_types[1]] - dist_pred);
        for (j in (i+1):N) {
            dist_pred = distance(Z[i-1],Z[j-1]);
            G_pred[i,j] = bernoulli_logit_rng(baseline + sbm[unit_types[i],unit_types[j]] - dist_pred);
            G_pred[j,i] = bernoulli_logit_rng(baseline + sbm[unit_types[j],unit_types[i]] - dist_pred);

My question is - is there any recommended way to deal with the degeneracy in the embedding? I’ve anchored the embedding of the first unit to the origin, which, together with the prior, should help with “translations-related” degeneracy; but is there any recommended way to deal with “rotations-related” degeneracy?

1 Like

I don’t know if there is a recommended way.

Similar to anchoring the first unit to origin, you could remove the rotational degeneracy by anchoring nth unit to an (n-1)-dimensional subspace. The matrix Z then looks like a Cholesky factor.

cholesky_factor_cov[N-1,embedding_dimension] Z;

This is equivalent to taking the QR-decomposition of a general Z and discarding the rotation matrix.

1 Like