Pyper: предсказание не возвращается, хотя модель хорошо работает в R - PullRequest
0 голосов
/ 30 января 2020

Я борюсь со следующей проблемой. Я обучил модель и загрузил обученную модель в R следующим образом:

model <- readRDS("C://tests/my_model.rds")
result <- predict(model, trainset, type = "prob")[, 2]

Все работает хорошо, и я могу получить прогнозы.

trainset =
   col1    col2    col2
   1       0       1

Однако, когда я пытаюсь вызвать та же модель, используя pyper от R, я получаю это сообщение:

TypeError: object of type 'NoneType' has no len()

В частности, expr = 'model <- readRDS(rmodel); result <- predict(model, rdata, type="prob")[,2]', кажется, возвращает None.

Это мой код:

import json
import numpy as np
import pandas as pd
from pyper import R

def init():
    global r
    r=R(RCMD="C://Program Files/R/R-3.6.2/bin/x64/R.exe", use_pandas=True)
    rds_path = "C://tests/my_model.rds"
    r.assign("rmodel", rds_path)

def run(raw_data, request_headers):
    data = json.loads(raw_data)["data"]
    cols = json.loads(raw_data)["cols"]
    data = pd.DataFrame(np.array(data), columns = cols)
    r.assign("rdata", data)
    expr = 'model <- readRDS(rmodel); result <- predict(model, rdata, type="prob")[,2]'
    r(expr)
    result = r.get('result')

    print(('{{"RequestId":"{0}", '
       '"TraceParent":"{1}", '
       '"NumberOfPredictions":{2}}}'
       ).format(
           request_headers.get("X-Ms-Request-Id", ""),
           request_headers.get("Traceparent", ""),
           len(result)
       ))

    return {"result": result.tolist()}

Вот как я называю функции:

init()
test_row = '{"data":[[1,0,1]],"cols":[["col1","col2","col3"]]}'
prediction = run(test_row, {})
print("Test result: ", prediction)

Я буду очень признателен за любую помощь в обнаружении проблемы, потому что сообщение об ошибке не очень информативно ...

Я провожу эксперименты в Jupyter Notebook.

Даже когда я пытаюсь заменить expr следующим образом (фиктивный код R):

expr = 'p <- c(1,2); result <- p'

Я получаю ошибку:

OSError                                   Traceback (most recent call last)
<ipython-input-97-240ae868eecb> in <module>
      3 test_row  = json.dumps(input_data)
      4 
----> 5 prediction = run(test_row, {})

<ipython-input-96-370705f72e83> in run(raw_data, request_headers)
     23         print(data.head())
     24 
---> 25     r.assign("rdata", data)
     26     expr = 'p <- rdata[1,1:2]; result <- [p]'
     27     r(expr)

~\AppData\Local\Continuum\anaconda3\lib\site-packages\pyper.py in __setitem__(self, obj, val)
    692         if obj.startswith('_'):
    693             raise RError('Leading underscore ("_") is not permitted in R variable names!')
--> 694         self.__call__('%s <- %s' % (obj, Str4R(val)))
    695 
    696     def __delitem__(self, obj):  # to model a dict: "del r['XXX']"

~\AppData\Local\Continuum\anaconda3\lib\site-packages\pyper.py in __call__(self, CMDS, use_try)
    646         rlt = []
    647         if isinstance(CMDS, basestring):  # a single command
--> 648             rlt.append(self.__runOnce(CMDS, use_try=use_try))
    649         else: # should be a list of commands
    650             # for CMD in CMDS:

~\AppData\Local\Continuum\anaconda3\lib\site-packages\pyper.py in __runOnce(self, CMD, use_try)
    622             fn = fn.replace('\\', '/')
    623             CMD = (use_try and 'try({source("%s")})%sfile.remove(%r)%s%s' or '%s%s%s') % (fn, newline, fn, newline, tail_cmd)
--> 624         self.sendAll(self.prog, CMD)
    625         rlt = ''
    626         while not re_tail.search(rlt):

~\AppData\Local\Continuum\anaconda3\lib\site-packages\pyper.py in sendAll(p, s)
    167         p.stdin.write(_mybytes(s))
    168         #os.write(p.stdin.fileno(), s)
--> 169         p.stdin.flush()
    170 
    171     def readLine(p, dump_stdout=False, *a, **b):

OSError: [Errno 22] Invalid argument

1 Ответ

1 голос
/ 30 января 2020

Хотя я не работал с pyper, я думаю, что ваша ошибка, когда вы делаете r.assign("rmodel", rds_path). Это следует использовать для назначения объекта Python, например, фрейма данных pandas экземпляру R, чтобы сделать его доступным (это то, что вы делаете в функции run()). Однако в init() вы передаете только строку пути, которая не является объектом.

Я думаю, что вы не сможете прочитать вашу модель R непосредственно в Python. Но вместо этого вы должны попробовать загрузить свою модель в экземпляр Python R. Так что переведите это model <- readRDS("C://tests/my_model.rds") к Пайперу. Тогда ваша модель должна быть доступна и способна делать прогнозы.

...