我正在尝试在RStan中使用潜在空间模型,这是一种完善的(社交)网络模型。 (这意味着这可能是CrossValidated的一个问题,但我有理由相信它不是。)我知道包可用,但我正在努力构建没有包实现的东西,并且想要首先确保我可以做一个可验证的模型工作。
为了给出快速直觉,LSM采用网络,并尝试为节点找到布局,使得紧密连接的节点具有边缘,并且远离节点不具有边缘。节点的位置是潜在变量,模型试图估计(连同截距,对应于形成边缘的整体倾向)。
我的代码(以下所有,在两个文件中)生成一个简单的小杠铃图(两端密集,中间稀疏),来自LSM假设的数据生成过程。然后它将这些数据传递给RStan,它发现了一个无限的渐变,以及包的潜在网络,它工作正常。
错误表明我从一个良好的初始化开始,所以我提供了TRUE生成值,并且采样器仍然找到无限渐变。它还建议在可能的情况下放松对变量的约束,但我的约束只是方差参数的下限。这让我相信我的问题在其他地方,但我还不熟悉斯坦能够看到哪里。任何帮助,包括运行测试的建议,都将非常感激。
首先,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);
}
}
}