You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apple M1上TensorFlow Probability二项分布类型错误求助

问题描述

环境:Apple M1设备,tensorflow-macos 2.10.0、tensorflow-probability 0.18.0、numpy 1.23.3,其他TensorFlow模型可正常运行。

模型代码中,berndfs是字典,每个s对应包含样本和调查数据的两个pandas DataFrame,核心代码如下:

def tfdmrp_run():
    n_chains = 4
    dtype = tf.float32
    berndfs = load_tfdmrp_datacache()
    shortnames = list(berndfs.keys())
    
    sample = berndfs[s]['svy']
    age_shape = len(berndfs[s]['census'].agecat.unique())
    gender_shape = len(berndfs[s]['census'].sex.unique())
    edu_shape = len(berndfs[s]['census'].educat.unique())
    counts = sample['count'].values.tolist()
    agecatlist = sample.agecat.values.tolist()
    genderlist = sample.gender.values.tolist()
    edulist = sample.educat.values.tolist()

    modlist = [
        tfd.HalfNormal(1),
        lambda sigma_age: tfd.Sample(tfd.Normal(0,sigma_age),sample_shape=age_shape),
        tfd.HalfNormal(1),
        lambda sigma_gender: tfd.Sample(tfd.Normal(0,sigma_gender),sample_shape=gender_shape),
        tfd.HalfNormal(1),
        lambda sigma_edu: tfd.Sample(tfd.Normal(0,sigma_edu),sample_shape=edu_shape),
        tfd.Normal(0,1), #intercept
        lambda intercept,coef_edu,a,coef_gender,b,coef_age: tfd.Independent(
            tfd.Binomial(
                total_count=tf.cast(counts,tf.int32),
                logits=intercept
                + tf.squeeze(tf.gather(coef_age, tf.cast(agecatlist,tf.int32),axis=-1))
                + tf.squeeze(tf.gather(coef_gender,tf.cast(genderlist,tf.int32),axis=-1))
                + tf.squeeze(tf.gather(coef_edu,tf.cast(edulist,tf.int32),axis=-1))
            ),
            reinterpreted_batch_ndims=1
        )
    ]

    model = tfd.JointDistributionSequential(modlist)
    model.resolve_graph()

调用model.resolve_graph()或sample()方法时,抛出错误:

*** TypeError: Found incompatible dtypes, <class 'numpy.int32'> and <class 'numpy.float32'>. Seen so far: [<class 'numpy.int32'>, <class 'numpy.float32'>, ...]

完整报错栈:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/jacobtucker/Documents/Projects/repos/rutracker/dmrp/dmrptfp.py", line 124, in tfdmrp_run
    model.resolve_graph()
  File "/Users/jacobtucker/miniconda3/envs/tfdmrp/lib/python3.10/site-packages/tensorflow_probability/python/distributions/joint_distribution_sequential.py", line 460, in resolve_graph
    distribution_names = self._flat_resolve_names(
  File "/Users/jacobtucker/miniconda3/envs/tfdmrp/lib/python3.10/site-packages/tensorflow_probability/python/distributions/joint_distribution_sequential.py", line 473, in _flat_resolve_names
    for d in self._get_single_sample_distributions()]
  File "/Users/jacobtucker/miniconda3/envs/tfdmrp/lib/python3.10/site-packages/tensorflow_probability/python/distributions/joint_distribution.py", line 353, in _get_single_sample_distributions
    ds = self._execute_model(
  File "/Users/jacobtucker/miniconda3/envs/tfdmrp/lib/python3.10/site-packages/tensorflow_probability/python/distributions/joint_distribution.py", line 1045, in _execute_model
    d = gen.send(next_value)
  File "/Users/jacobtucker/miniconda3/envs/tfdmrp/lib/python3.10/site-packages/tensorflow_probability/python/distributions/joint_distribution_sequential.py", line 399, in _model_coroutine
    dist = dist_fn(*xs)
  File "/Users/jacobtucker/miniconda3/envs/tfdmrp/lib/python3.10/site-packages/tensorflow_probability/python/distributions/joint_distribution_sequential.py", line 610, in dist_fn_wrapped
    return dist_fn(*reversed(xs[-len(args):]))
  File "/Users/jacobtucker/Documents/Projects/repos/rutracker/dmrp/dmrptfp.py", line 112, in <lambda>
    tfd.Binomial(
  File "/Users/jacobtucker/miniconda3/envs/tfdmrp/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/Users/jacobtucker/miniconda3/envs/tfdmrp/lib/python3.10/site-packages/tensorflow_probability/python/distributions/distribution.py", line 342, in wrapped_init
    default_init(self_, *args, **kwargs)
  File "/Users/jacobtucker/miniconda3/envs/tfdmrp/lib/python3.10/site-packages/tensorflow_probability/python/distributions/binomial.py", line 371, in __init__
    dtype = dtype_util.common_dtype([total_count, logits, probs], tf.float32)
  File "/Users/jacobtucker/miniconda3/envs/tfdmrp/lib/python3.10/site-packages/tensorflow_probability/python/internal/dtype_util.py", line 104, in common_dtype
    raise TypeError(
TypeError: Found incompatible dtypes, <class 'numpy.int32'> and <class 'numpy.float32'>. Seen so far: [<class 'numpy.int32'>, <class 'numpy.float32'>, ...]

用户的困惑:模型输入看似都是Python原生类型,却出现dtype不兼容问题,依赖版本无兼容性问题,求原因及解决办法。

原因分析

错误根源在tfd.Binomial的初始化步骤:

  • counts = sample['count'].values.tolist()得到的列表中,元素是numpy.int32类型(而非Python原生int)。
  • 尽管用了tf.cast(counts, tf.int32),但在JointDistributionSequential解析模型图时,TFP会先尝试用原始numpy类型做类型推断,而logits部分是TensorFlow的float32张量,numpy类型和TensorFlow类型体系不兼容,导致无法找到共同dtype,抛出错误。
解决办法

有两种可行方案:

方案一:直接将counts转为TensorFlow张量

把counts = sample['count'].values.tolist()替换为:

counts = tf.cast(sample['count'].values, tf.int32)

这样total_count直接是TensorFlow的int32张量,TFP能正确处理它和float32类型logits的类型兼容问题。

方案二:将counts转为Python原生int列表

如果需要保留列表形式,先把pandas列的类型转为原生int,再转列表:

counts = sample['count'].astype(int).tolist()

之后再用tf.cast(counts, tf.int32)转换,此时列表元素是Python原生int,TFP的类型推断能正常工作。

内容的提问来源于stack exchange,提问作者user1675330

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 07:25:23