PyStan维度不匹配报错:y的声明维度与实际维度不符
报错详情
运行PyStan构建伯努利逻辑回归模型时出现维度不匹配错误:
Exception: mismatch in number dimensions declared and found in context; processing stage=data initialization; variable name=y; dims declared=(100); dims found=(100,1) (in '/tmp/httpstan_ii3yhtja/model_776ng6bg.stan', line 7, column 2 to column 35)
问题代码
Python数据处理与拟合代码
import stan import numpy as np # Load data (replace X and y with your actual data) X = np.linspace(1,100,100).reshape([100,1]) y = np.random.randint(0,2,100).reshape([100,1]) N = y.shape[0] K = X.shape[1] data = {'N': N, 'K': K, 'X': X, 'y': y} # Compile Stan model posterior = stan.build(lr_model, data=data, random_seed=1) # Fit the model samples = posterior.sample(data=data, iter=1000, chains=4)
Stan模型脚本
lr_model = """ data { int<lower=0> N; // number of observations int<lower=0> K; // number of predictors matrix[N, K] X; // predictor matrix array[N] int<lower=0, upper=1> y; // binary response } parameters { vector[K] beta; // regression coefficients } model { beta ~ normal(0, 1); y ~ bernoulli_logit(X * beta); } """
原因分析
Stan模型中y被声明为一维数组array[N] int,但Python代码里通过reshape([100,1])生成了二维数组(100,1)。即使把数组转成列表,二维列表(如[[0],[1],...])依然不符合Stan对一维结构的要求——Stan的array[N]对应Python里的一维序列(如[0,1,...]或一维numpy数组)。
另外,模型里的bernoulli_logit分布要求响应变量y是一维的,因为X * beta计算后得到的是N维向量,刚好和一维的y匹配。
解决方法
方法1:修改Python代码,将y转为一维结构
直接去掉reshape操作,或者用numpy的方法把二维数组压平为一维:
# 方式1:生成时直接创建一维数组 y = np.random.randint(0,2,100) # 方式2:将已有的二维数组压平 y = np.random.randint(0,2,100).reshape([100,1]).flatten() # 或用.ravel()/.squeeze() # 转列表的话也要转成一维列表 y = np.random.randint(0,2,100).reshape([100,1]).flatten().tolist()
修改后的数据传入Stan,就能匹配模型里array[N] int y的声明。
方法2:修改Stan模型,适配二维y(不推荐)
如果一定要保留二维的y,可以把Stan模型里的y声明改为二维数组,但需要调整模型里的使用方式:
data { // ... 其他声明不变 array[N, 1] int<lower=0, upper=1> y; // 改为二维数组 } model { beta ~ normal(0, 1); y[:,1] ~ bernoulli_logit(X * beta); // 取第一列作为一维序列 }
这种方式不如方法1简洁,因为模型本身逻辑上响应变量就是一维的,没必要用二维结构。
内容的提问来源于stack exchange,提问作者jbuddy_13

