Error: non-constant-expression cannot be narrowed

2020-06-04 09:57发布

问题:

I am trying to run the following model, but it fails during compilation:

import numpy as np
import pymc3 as pm


def sample_data(G=1, K=2):
    # mean proportion ([0,1]) for each g
    p_g = np.random.beta(2, 2, size=G)

    # concentration around each p_g
    c_g = np.random.lognormal(mean=0.5, sigma=1, size=G)

    # reparameterization for standard Beta(a,b)
    a_g = c_g * p_g / np.sqrt(p_g**2 + (1.-p_g)**2)
    b_g = c_g*(1.-p_g) / np.sqrt(p_g**2 + (1.-p_g)**2)

    # for each p_g, sample K proportions
    p_gk = np.random.beta(a_g[:, np.newaxis], b_g[:, np.newaxis], size=(G, K))

    return p_gk

# Data size
G = 3
K = 5

# obtain a G x K array of proportions p_gk in [0,1]
data = sample_data(G, K) 

with pm.Model() as m:

    # Parameters
    p_g = pm.Beta('p_g', 1., 1., shape=G)
    sd_g = pm.HalfNormal('sd_g', sd=1., shape=G)

    # Observed proportions
    p_gk = pm.Beta('p_gk', mu=p_g, sd=sd_g, shape=(G, K), observed=data)

    trace = pm.sample(2000)

with these errors:

Exception: ("Compilation failed (return status=1):

/Users/mfansler/.theano/compiledir_Darwin-17.6.0-x86_64-i386-64bit-i386-3.6.3-64/tmpr58gulp2/mod.cpp:400:27: 
  error: non-constant-expression cannot be narrowed from type 'npy_intp' (aka 'long') to 'int' in initializer list [-Wc++11-narrowing].
     int init_totals[2] = {V3_n0, V3_n1};.
                           ^~~~~.

/Users/mfansler/.theano/compiledir_Darwin-17.6.0-x86_64-i386-64bit-i386-3.6.3-64/tmpr58gulp2/mod.cpp:400:27:
  note: insert an explicit cast to silence this issue.
     int init_totals[2] = {V3_n0, V3_n1};.
                           ^~~~~.
                           static_cast<int>( ).

/Users/mfansler/.theano/compiledir_Darwin-17.6.0-x86_64-i386-64bit-i386-3.6.3-64/tmpr58gulp2/mod.cpp:400:34: 
  error: non-constant-expression cannot be narrowed from type 'npy_intp' (aka 'long') to 'int' in initializer list [-Wc++11-narrowing].
     int init_totals[2] = {V3_n0, V3_n1};.
                                  ^~~~~.

/Users/mfansler/.theano/compiledir_Darwin-17.6.0-x86_64-i386-64bit-i386-3.6.3-64/tmpr58gulp2/mod.cpp:400:34: 
  note: insert an explicit cast to silence this issue.
     int init_totals[2] = {V3_n0, V3_n1};.
                                  ^~~~~.
                                  static_cast<int>( ).

/Users/mfansler/.theano/compiledir_Darwin-17.6.0-x86_64-i386-64bit-i386-3.6.3-64/tmpr58gulp2/mod.cpp:412:9: 
  error: non-constant-expression cannot be narrowed from type 'ssize_t' (aka 'long') to 'int' in initializer list [-Wc++11-narrowing].
         V3_stride0, V3_stride1, .
         ^~~~~~~~~~.

/Users/mfansler/.theano/compiledir_Darwin-17.6.0-x86_64-i386-64bit-i386-3.6.3-64/tmpr58gulp2/mod.cpp:412:9: 
  note: insert an explicit cast to silence this issue.
         V3_stride0, V3_stride1, .
         ^~~~~~~~~~.
         static_cast<int>( ).

/Users/mfansler/.theano/compiledir_Darwin-17.6.0-x86_64-i386-64bit-i386-3.6.3-64/tmpr58gulp2/mod.cpp:412:21: 
  error: non-constant-expression cannot be narrowed from type 'ssize_t' (aka 'long') to 'int' in initializer list [-Wc++11-narrowing].
         V3_stride0, V3_stride1, .
                     ^~~~~~~~~~.

/Users/mfansler/.theano/compiledir_Darwin-17.6.0-x86_64-i386-64bit-i386-3.6.3-64/tmpr58gulp2/mod.cpp:412:21:
  note: insert an explicit cast to silence this issue.
         V3_stride0, V3_stride1, .
                     ^~~~~~~~~~.
                     static_cast<int>( ).

/Users/mfansler/.theano/compiledir_Darwin-17.6.0-x86_64-i386-64bit-i386-3.6.3-64/tmpr58gulp2/mod.cpp:413:1: 
  error: non-constant-expression cannot be narrowed from type 'ssize_t' (aka 'long') to 'int' in initializer list [-Wc++11-narrowing].
 V1_stride0, V1_stride1.
 ^~~~~~~~~~.

/Users/mfansler/.theano/compiledir_Darwin-17.6.0-x86_64-i386-64bit-i386-3.6.3-64/tmpr58gulp2/mod.cpp:413:1: 
  note: insert an explicit cast to silence this issue.
 V1_stride0, V1_stride1.
 ^~~~~~~~~~.
 static_cast<int>( ).

/Users/mfansler/.theano/compiledir_Darwin-17.6.0-x86_64-i386-64bit-i386-3.6.3-64/tmpr58gulp2/mod.cpp:413:13:
  error: non-constant-expression cannot be narrowed from type 'ssize_t' (aka 'long') to 'int' in initializer list [-Wc++11-narrowing].
 V1_stride0, V1_stride1.
             ^~~~~~~~~~.

/Users/mfansler/.theano/compiledir_Darwin-17.6.0-x86_64-i386-64bit-i386-3.6.3-64/tmpr58gulp2/mod.cpp:413:13:
  note: insert an explicit cast to silence this issue.
 V1_stride0, V1_stride1.
             ^~~~~~~~~~.
             static_cast<int>( ).

6 errors generated.. ", '[Elemwise{log,no_inplace}(TensorConstant{[[0.297343..76841722]]})]')

I'm new to PyMC3. I don't see these errors when running existing PyMC3 examples. I suspect that I'm seeing these because I'm using a multidimensional format (i.e., (G,K)), since I haven't seen others using this format (I might be imposing my familiarity with Stan).

Generally, I'm having trouble getting a sense of how to implement multilevel models that have multiple dimensions.

Any idea what is causing the errors I'm seeing?


Versions

  • python 3.6.3
  • numpy 1.14.5
  • Theano 1.0.2
  • pymc3 3.4.1
  • Mac OS 10.13.5

Update

I installed the same package versions (via conda) on an HPC node (CentOS 7), and was able to run the modified version of the model suggested by @colcarroll. However, on my OS X machine, I still see the Theano compilation errors indicated above, even with the model changes. Is this possibly a clang problem? Can one specify the compiler for Theano to use?

回答1:

One workaround is to suppress the compilation errors:

import theano

theano.config.gcc.cxxflags = "-Wno-c++11-narrowing"

The extent to which these errors matter for program correctness is unclear. They do not arise when I compile on CentOS 7 (even when explicitly checking for them with -Wc++11-narrowing). The sampling results on Mac OS X with suppressed errors and CentOS without were comparable.

I would still prefer to see an answer that explains the underlying issue.



回答2:

Yes - You do have to be a bit more explicit about shapes for higher dimensions. The library does a little to be "clever", but if you provide the shape argument, it will use that.

Your example here is syntactically fixed by setting

with pm.Model() as m:

    # Parameters
    p_g = pm.Beta('p_g', 1., 1., shape=(G, 1))
    sd_g = pm.HalfNormal('sd_g', sd=1, shape=(G, 1))

    # Observed proportions
    p_gk = pm.Beta('p_gk', mu=p_g.dot(np.ones((1,K))), sd=sd_g.dot(np.ones((1, K))), shape=(G, K), observed=data)
    trace = pm.sample()

Note that running m.check_test_point() wil show that p_gk has 0 probability. This is because sd_g is too wide, and PyMC3 tries to initialize that at 0.8, which is out of the support of a mu, sd parametrized beta distribution.

Setting sd_g = pm.HalfNormal('sd_g', sd=0.1, shape=(G, 1)) allows you to also sample from the model, though this may not be the prior you intended!