# Double-checking a simple single-latent-variable SEM

**URL:** https://discourse.mc-stan.org/t/double-checking-a-simple-single-latent-variable-sem/18817
**Category:** Modeling
**Tags:** specification
**Created:** [October 21, 2020, 10:33pm UTC](https://discourse.mc-stan.org/t/double-checking-a-simple-single-latent-variable-sem/18817 "2020-10-21T22:33:11Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![mike-lawrence](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/mike-lawrence/32/59_2.png) [@mike-lawrence](https://discourse.mc-stan.org/u/mike-lawrence)
#### Post date: [October 21, 2020, 10:33pm UTC](https://discourse.mc-stan.org/t/double-checking-a-simple-single-latent-variable-sem/18817/1 "2020-10-21T22:33:11Z")

</div>

I’m working with some data where I have N observed timeseries of M timepoints each, and I suspect that there’s a common latent variable influencing each observed timeseries to varying degrees. It’s been a while since I last worked with SEM stuff and I want to double-check that I’m going about it properly, especially with respect to ensuring identifiability. I think with this simple model, it’s sufficient to impose the restriction that the latent variable has a mean of zero, sd of 1 and fix the weight on one variable to 1, right? Here’s the code for this:

```stan
data{
	int ncols ;
	int nrows ;
	matrix[nrows,ncols] Y ; // this should be scaled to have columns with mean=0, sd=1
}
parameters{
	vector[ncols-1] weights ;
	vector<lower=0>[ncols] noise ;
	vector[nrows] latent ;
}
model{
	vector[ncols] w = append_row(1,weights) ;
	noise ~ std_normal() ;
	weights ~ std_normal() ;
	latent ~ std_normal() ;
	for(i in 1:ncols){
		Y[,i] ~ normal( latent*w[i], noise[i]) ;
	}
}

```

I feel like I’m missing something however. Something to do with the noise term? Since the latent variable is modelled as having an sd of 1, and it has a 1 weight on the first column, doesn’t that impose a corollary that the observed SD of that column has to be 1 or greater? I can ensure the data match this expectation by scaling it before sampling, but is this appropriate?

Edit: yeah, the more I think of it, this can’t be right as it implies that the first column is perfectly correlated with the latent variable (if I’m also standardizing all observed variables to have sd==1). Ah, I think I just need to fix the sign of the first weight, but let the magnitude remain free:

```stan
data{
	int ncols ;
	int nrows ;
	matrix[nrows,ncols] Y ;
}
parameters{
	real<lower=0> first_weight ;
	vector[ncols-1] other_weights ;
	vector<lower=0>[ncols] noise ;
	vector[nrows] latent ;
}
model{
	vector[ncols] weights = append_row(first_weight,other_weights) ;
	noise ~ std_normal() ;
	first_weight ~ std_normal() ;
	other_weights ~ std_normal() ;
	latent ~ std_normal() ;
	for(i in 1:ncols){
		Y[,i] ~ normal(
			latent*weights[i]
			, noise[i]
		) ;
	}
}

```

Darn, that just yields tons of divergences… Now I’m flummoxed. Anyone have any tips? @Charles_Driver maybe I could impose upon your expertise to show me where I’m going awry here?

---

<div class="post-metadata">

### Author: ![Charles\_Driver](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/charles_driver/32/6524_2.png) [@Charles\_Driver](https://discourse.mc-stan.org/u/Charles_Driver)
#### Post date: [October 22, 2020, 3:41pm UTC](https://discourse.mc-stan.org/t/double-checking-a-simple-single-latent-variable-sem/18817/2 "2020-10-22T15:41:41Z")

</div>

Aside from the lack of intercepts (is Y centered?) it seems roughly sensible… sorry. I remember seeing factor loadings cause some weird sampling behaviour though, if that helps ;)

---

<div class="post-metadata">

### Author: ![mike-lawrence](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/mike-lawrence/32/59_2.png) [@mike-lawrence](https://discourse.mc-stan.org/u/mike-lawrence)
#### Post date: [October 22, 2020, 4:01pm UTC](https://discourse.mc-stan.org/t/double-checking-a-simple-single-latent-variable-sem/18817/3 "2020-10-22T16:01:38Z")

</div>

Thanks, good to know it’s not obviously doing something wrong. I guess from here I’ll do what I should have done in the first place: use dummy data to ensure there’s no blatant misspecification first. I’ll report back if I learn anything useful.

---

<div class="post-metadata">

### Author: ![mike-lawrence](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/mike-lawrence/32/59_2.png) [@mike-lawrence](https://discourse.mc-stan.org/u/mike-lawrence)
#### Post date: [October 23, 2020, 4:43pm UTC](https://discourse.mc-stan.org/t/double-checking-a-simple-single-latent-variable-sem/18817/4 "2020-10-23T16:43:48Z")

</div>

Another vote for the degeneracy of SEMs [here](https://twitter.com/betanalpha/status/1319652080425066497?s=20)

---

<div class="post-metadata">

### Author: ![edm](https://avatars.discourse-cdn.com/v4/letter/e/f08c70/32.png) [@edm](https://discourse.mc-stan.org/u/edm)
#### Post date: [October 26, 2020, 3:56am UTC](https://discourse.mc-stan.org/t/double-checking-a-simple-single-latent-variable-sem/18817/5 "2020-10-26T03:56:47Z")

</div>

Instead of restricting the first weight to be positive, it seems to work better if you leave the weight unrestricted in the parameter block, then “fix” the signs in generated quantities. See here:

> [@Latent factor loadings](https://discourse.mc-stan.org/t/latent-factor-loadings/1483/6):
>
> For a one factor model, I would usually declare the loadings to be unconstrained in the parameters block and in the generated quantities block, multiply stuff by -1 as necessary to force the sign of one loading to be positive. For a multi-factor model with an identity matrix for the correlations among the factors, a cholesky\_factor\_cov can work well as a loadings matrix since it is lower trapezoidal with positive diagonal entries. But that can run into problems like the one you encountered, if …

Or, if you fixed the first weight to 1, the SD of the latent distribution would then typically be free.
