我正在尝试在 RStan 中拟合潜在空间模型,这是一种成熟的(社交)网络模型。(这意味着这可能是 CrossValidated 的一个问题,但我有理由相信它还不是。)我知道包是可用的,但我正在努力构建一些没有包实现的东西,并且想首先确保我可以制作一个可验证的模型工作。
为了快速直观,LSM 采用一个网络,并尝试找到节点的布局,这样靠近的节点有边,而相距较远的节点没有。节点的位置是模型试图估计的潜在变量(连同截距,对应于形成边缘的总体倾向)。
我的代码(全部在下面,在两个文件中)从 LSM 假定类型的数据生成过程生成一个简单而小的杠铃图(两端密集,中间稀疏)。然后,它将这些数据传递给 RStan,它找到了一个无限的梯度,以及包 latentnet,它工作得很好。
该错误表明我从一个良好的初始化开始,所以我提供了 TRUE 生成值,并且采样器仍然找到一个无限梯度。它还建议尽可能放宽对变量的约束,但我的约束只是方差参数的下限。这让我相信我的问题出在其他地方,但我对 Stan 还不够熟悉,无法看到哪里。任何帮助,包括运行测试的建议,将不胜感激。
首先,R:
# GENERATING LSM DATA #
# The sparse path connecting the dense ends
w <- cbind(0.5*0:8-2, rep(0,9))
# The two dense barbell ends
x <- mvrnorm(10, mu=c(-2,0), Sigma=array(c(.2,0,0,.2),dim=c(2,2)))
y <- mvrnorm(10, mu=c(2,0), Sigma=array(c(.2,0,0,.2),dim=c(2,2)))
z <- rbind(w,x,y)
d <- as.matrix(dist(z))
a <- 1
logit <- function(x) 1/(1+exp(-x))
for(i in 1:N){
for(j in 1:N){
# This is what a LSM assumes
X[i,j] <- (logit(a - d[i,j]) > .5)+0
}
}
mean(X)
N <- nrow(X)
lsm.data <- list(N=N,
edges=X,
sigma_alpha=10,
mu_z=c(0,0),
sigma_z=array(c(1,0,0,1),dim=c(2,2)))
# This initialization provides the TRUE values of the parameters
lsm.init <- function(){
list(alpha=a, z=z)
}
library(rstan)
lsm.fit <- stan("lsm.stan",
model_name="lsm",
data=lsm.data,
init=lsm.init,
verbose=T)
# Here is an independent verification of the data -- this model fits fine,
# and a plot of the result looks exactly as I think it should (a barbell).
library(latentnet)
lsm.ergmm <- ergmm(X ~ euclidean(d=2))
plot(lsm.ergmm)
在这里,斯坦的模型:
data {
int<lower=0> N; // number of nodes
int<lower=0> edges[N,N]; //for now non-blank => 1
real<lower=0> sigma_alpha; // alpha is the density
vector[2] mu_z; // mean of the latent positions
matrix<lower=0>[2,2] sigma_z; // variance of the latent positions
}
parameters {
real alpha; // density intercept
vector[2] z[N]; // latent positions
}
model {
real d; // just a convenience variable, to split up a long line
// prior on alpha
alpha ~ normal(0, sigma_alpha);
// latent variables
for (i in 1:N) {
z[i] ~ multi_normal(mu_z, sigma_z);
}
for(i in 1:N){
for(j in 1:N){
d = sqrt(pow(z[i,1]-z[j,1],2) + pow(z[i,2]-z[j,2],2));
edges[i,j] ~ bernoulli_logit(alpha - d);
}
}
}