Ошибка передачи нескольких входов в класс при использовании Numba - PullRequest
0 голосов
/ 22 октября 2018

Я пытаюсь использовать Numba Decorator с моим классом.Однако я получаю следующую ошибку.Я проверил входное измерение, и оно выглядит корректно, но все равно получаю ту же ошибку.Есть идеи, как решить проблему?

   spec = [('w_x', nb.int32), ('w_a', nb.int32),('mu_a', nb.int64[:]), 
      ('sig_a',nb.int64[:]),('mu_x', nb.int64[:]),('sig_x', nb.int32[:]), 
       ('mu_a_a',nb.float64[:,:]),('sig_a_a', nb.float64[:,:]), ('mu_x_a', 
       nb.int32[:]),('sig_x_a', nb.float32[:,:]),('mu_0', nb.boolean), 
       ('sig_0', nb.boolean),('beta', nb.int32),('policy', nb.uint8)]
    @nb.jitclass(spec)        
    class learner(object):
    def __init__ (self, w_x, w_a, beta, policy):
    '''
        initialize: 
        w_x: the dim of customer features
        w_a: the dim of ad features
        mu_a: the prior of mean of weights on ad
        sig_a: the prior of var of weights on ad
        mu_x: the prior of mean of weights on customer
        sig_x: the prior of var of weights on customer
        mu_a_a: the prior of interactions between ad segments
        sig_a_a: the prior of var of interactions between ad segments
        mu_x_a: the prior of mean of interactions between customers and ad 
        segments
        sig_x_a: the prior of var of interactions between customers and ad 
     segments
    '''
    self.w_x = w_x
    self.w_a = w_a
    self.mu_a = np.zeros(self.w_a)
    self.sig_a = np.ones(self.w_a)
    self.mu_x = np.zeros(self.w_x)
    self.sig_x = np.ones(self.w_x)
    self.mu_a_a = np.zeros((self.w_a, self.w_a))
    #self.mu_a_a = np.triu(self.mu_a_a, k=1)
    self.sig_a_a = np.ones((self.w_a, self.w_a))
    #self.sig_a_a = np.triu(self.sig_a_a, k=1)
    self.mu_x_a = np.zeros((self.w_x, self.w_a))
    self.sig_x_a = np.ones((self.w_x, self.w_a))
    #the intercept term w_0
    self.mu_0 = 0
    self.sig_0 = 1
    self.beta = beta
    self.policy = policy

Ниже приведено сообщение об ошибке:

File "C:\Users\MSHAHAB2\AppData\Local\Continuum\anaconda3\lib\site- 
packages\numba\six.py", line 659, in reraise
raise value numba.errors.LoweringError: Failed at nopython (nopython mode 
backend)
Can only insert i64* at [4] in {i8*, i8*, i64, i64, i64*, [1 x i64], [1 x 
i64]}: got double*

File "batch_mode_function.py", line 147:
def __init__ (self, w_x, w_a, beta, policy):
    <source elided>
    self.w_a = w_a
    self.mu_a = np.zeros(self.w_a)
    ^
[1] During: lowering "(self).mu_a = $0.9" at 
W:\GRMOS\MShahabi\MNV\HillClimbSim\batch_mode_function.py (147)
[2] During: resolving callee type: 
jitclass.learner#1e390f65798<w_x:int32,w_a:int32,mu_a:array(int64, 1d, 
A),sig_a:array(int64, 1d, A),mu_x:array(int64, 1d, A),sig_x:array(int32, 1d, 
A),mu_a_a:array(float64, 2d, A),sig_a_a:array(float64, 2d, 
A),mu_x_a:array(int32, 1d, A),sig_x_a:array(float32, 2d, 
A),mu_0:bool,sig_0:bool,beta:int32,policy:uint8>
[3] During: typing of call at <string> (3)

1 Ответ

0 голосов
/ 24 октября 2018

Отображаемое сообщение об ошибке довольно легко устранить.np.zeros создает массив dtype=np.float64 по умолчанию, который равен nb.float64 в numba.Вы должны указать dtype в np.zeros, чтобы получить массив np.int64 или np.int32:

self.mu_a = np.zeros(self.w_a, dtype=np.int64)
self.sig_a = np.ones(self.w_a, dtype=np.int64)
self.mu_x = np.zeros(self.w_x, dtype=np.int64)
self.sig_x = np.ones(self.w_x, dtype=np.int32)

То же самое для массивов self.mu_x_a и self.sig_x_a

self.mu_x_a = np.zeros((self.w_x, self.w_a), dtype=np.int32)
self.sig_x_a = np.ones((self.w_x, self.w_a), dtype=np.float32)

Для self.mu_x_a вы также пропустили второе измерение в spec.Это должно быть:

spec = [('mu_x_a',  nb.int32[:, :])]

Тогда при создании массива возникает ошибка последующих действий self.mu_a_a.Numba выдает ошибку, что кортеж формы (self.w_a, self.w_a) имеет тип (i64, i32).Это, очевидно, ошибка в numba с выводом / приведением типа.Все типы nb.int32 автоматически преобразуются в nb.int64.
Для этого есть два обходных пути:

Обходное решение 1:
Замените сигнатуру типа self.w_a с nb.int64 (а также с self.w_x, поскольку это необходимо для self.mu_x_a и self.sig_x_a):

spec = [('w_x', nb.int64), ('w_a', nb.int64)]

ИЛИ Обходной путь 2: Не использоватькак-то непоследовательно приведенные переменные экземпляра.Вместо этого используйте данные входные данные:

self.mu_a_a = np.zeros((w_a, w_a))
self.sig_a_a = np.ones((w_a, w_a))
self.mu_x_a = np.zeros((w_x, w_a), dtype=np.int32)
self.sig_x_a = np.ones((w_x, w_a), dtype=np.float32)

Я рекомендую использовать обходной путь 1, так как в настоящее время int32 преобразуется в int64 в numba в любом случае.Используя Обходной путь 1 , он должен выглядеть следующим образом:

spec = [('w_x', nb.int64), ('w_a', nb.int64),('mu_a', nb.int64[:]), 
      ('sig_a',nb.int64[:]),('mu_x', nb.int64[:]),('sig_x', nb.int32[:]), 
       ('mu_a_a',nb.float64[:,:]),('sig_a_a', nb.float64[:,:]), ('mu_x_a', 
       nb.int32[:, :]),('sig_x_a', nb.float32[:,:]),('mu_0', nb.boolean), 
       ('sig_0', nb.boolean),('beta', nb.int32),('policy', nb.uint8)]
@nb.jitclass(spec)        
class learner(object):
    def __init__ (self, w_x, w_a, beta, policy):
        '''
            initialize: 
            w_x: the dim of customer features
            w_a: the dim of ad features
            mu_a: the prior of mean of weights on ad
            sig_a: the prior of var of weights on ad
            mu_x: the prior of mean of weights on customer
            sig_x: the prior of var of weights on customer
            mu_a_a: the prior of interactions between ad segments
            sig_a_a: the prior of var of interactions between ad segments
            mu_x_a: the prior of mean of interactions between customers and ad 
            segments
            sig_x_a: the prior of var of interactions between customers and ad 
         segments
        '''
        self.w_x = w_x
        self.w_a = w_a
        self.mu_a = np.zeros(self.w_a, dtype=np.int64)
        self.sig_a = np.ones(self.w_a, dtype=np.int64)
        self.mu_x = np.zeros(self.w_x, dtype=np.int64)
        self.sig_x = np.ones(self.w_x, dtype=np.int32)
        self.mu_a_a = np.zeros((self.w_a, self.w_a))
        #self.mu_a_a = np.triu(self.mu_a_a, k=1)
        self.sig_a_a = np.ones((self.w_a, self.w_a))
        #self.sig_a_a = np.triu(self.sig_a_a, k=1)
        self.mu_x_a = np.zeros((self.w_x, self.w_a), dtype=np.int32)
        self.sig_x_a = np.ones((self.w_x, self.w_a), dtype=np.float32)
        #the intercept term w_0
        self.mu_0 = 0
        self.sig_0 = 1
        self.beta = beta
        self.policy = policy

Для Обходной путь 2 вы можете оставить спецификации для w_x и w_a как nb.int32и просто замените создание массива следующих 4 массивов на:

self.mu_a_a = np.zeros((w_a, w_a))
self.sig_a_a = np.ones((w_a, w_a))
self.mu_x_a = np.zeros((w_x, w_a), dtype=np.int32)
self.sig_x_a = np.ones((w_x, w_a), dtype=np.float32)

Поскольку я предполагаю, что приведение к поведению является ошибкой, я рекомендую сообщить об этом со ссылкой на этот поток.

...