PyMC3分层模型中Theano张量除法长度未知问题解决咨询
解决PyMC3模型中Theano张量与pandas Index运算的长度未知错误
这个问题的核心是pandas Index对象和Theano符号张量之间的运算冲突:periods[periods_idx]返回的pandas结构在和theta(PyMC3随机变量,本质是Theano张量)做除法时,pandas试图迭代符号张量,但Theano张量在模型构建阶段没有确定的长度,从而抛出ValueError: length not known。
快速修复方案
把periods[periods_idx]转换成numpy数组,让它和Theano张量进行正确的符号运算广播,修改出错的那一行代码:
mu_i_t = Ci[cohorts_idx] * (1 - tt.exp(- (np.asarray(periods[periods_idx]) / theta) ** omega))
或者提前在模型外处理好这个数组,让代码更清晰:
# 在factorize之后添加这一行 periods_values = np.asarray(periods[periods_idx]) with pm.Model(coords = coords) as model: # ... 其他参数定义 ... mu_i_t = Ci[cohorts_idx] * (1 - tt.exp(- (periods_values / theta) ** omega)) # ... 后续代码 ...
错误原因详解
你用pd.factorize得到的periods是pandas Index对象,当你执行periods[periods_idx]时,返回的是一个pandas Series/Index,而不是numpy数组。当这个pandas结构和Theano符号张量(比如theta)做除法时:
- pandas的算术运算会尝试将Theano张量包装成pandas Series
- 但Theano张量在模型编译前是符号化的占位符,没有确定的长度,pandas尝试迭代它来构建Series时,就会触发
length not known的错误 - 换成加法时,pandas的内部广播逻辑刚好避开了迭代检查,但这只是巧合,不是正确的解决方式
修改后的完整代码示例
import pymc3 as pm import pandas as pd import numpy as np import matplotlib.pyplot as plt import theano.tensor as tt # 假设inputs是你的Dataframe cohorts_idx, cohorts = pd.factorize(inputs['Cohort'], sort = True) periods_idx, periods = pd.factorize(inputs['Period'], sort = True) # 提前转换为numpy数组 periods_values = np.asarray(periods[periods_idx]) coords = { "cohort": cohorts, "period": periods, "collections": np.arange(len(cohorts_idx)) } with pm.Model(coords = coords) as model: # global model parameters omega = pm.HalfNormal("omega", sigma = 3) theta = pm.HalfNormal("theta", sigma = 5) sigma = pm.HalfNormal("sigma", sigma = 20) # cohort specific parameter Ci = pm.TruncatedNormal("Ci", mu = 60, sigma = 10, lower = 10, upper = 110, dims = "cohort") # 使用numpy数组进行运算 mu_i_t = Ci[cohorts_idx] * (1 - tt.exp(- (periods_values / theta) ** omega)) sigma_i_t = sigma * mu_i_t ** 0.5 _ = pm.Normal("Collections_i_t", mu = mu_i_t, sigma = sigma_i_t, observed = inputs['Collections'], dims = "collections") results = pm.sample(draws = 1000, tune = 1000, cores = 8) print(pm.summary(results))
内容的提问来源于stack exchange,提问作者Alexis Dussault
相关产品推荐
相关产品推荐

