Использование rpy2 с классификацией попыток ввода вместо регрессии

У меня есть данные, которые я создал и предварительно обработал в Python, которые я хотел бы импортировать в R и выполнить k-кратную перекрестную проверку LASSO, используя glmnet. Я хочу контролировать, какие наблюдения используются в каждой сгибке, поэтому я хочу использовать для этого caret.

Однако я обнаружил, что caret интерпретирует мои данные как классификацию, а не как проблему регрессии, и сразу терпит неудачу. Вот, надеюсь, воспроизводимый пример:

import numpy as np
import pandas as pd
import rpy2.robjects as robjects
from rpy2.robjects.packages import importr
from rpy2.robjects import pandas2ri
from rpy2.robjects import numpy2ri
from rpy2.robjects.conversion import localconverter

pandas2ri.activate()
numpy2ri.activate()

# Import essential R packages
glmnet = importr('glmnet')
caret = importr('caret')
base = importr('base')

# Define X and y input 
dummy_x = pd.DataFrame(np.random.rand(10000, 5), columns=('a', 'b', 'c', 'd', 'e'))
dummy_y = np.random.rand(10000)

# Convert pandas DataFrame to R data.frame
with localconverter(robjects.default_converter + pandas2ri.converter): 
 dummy_x_R = robjects.conversion.py2rpy(dummy_x) 

# Use caret to perform the fit using default settings 
caret_test = caret.train(**{'x': dummy_x_R, 'y': dummy_y, 'method': 'glmnet'})

rpy2 дает сбой, выдавая это загадочное сообщение об ошибке от R:

RRuntimeError: Error: Metric RMSE not applicable for classification models

Что может быть причиной этого? Согласно этому предыдущему вопросу, возможно, каретка предполагает, что по крайней мере одна из моих переменных имеет целочисленный тип, и поэтому по умолчанию думает, что это классификация, а не проблема регрессии.

Однако я проверил и X, и Y, используя typeof, и они явно удваиваются:

base.sapply(dummy_x_R, 'typeof')                                                                                                                                                     
>>> array(['double', 'double', 'double', 'double', 'double'], dtype='<U6')

base.sapply(dummy_y, 'typeof')                                                                                                                                                       
>>> array(['double', 'double', 'double', ..., 'double', 'double', 'double'],
      dtype='<U6')

Почему я получаю эту ошибку? Все настройки по умолчанию для train предполагают модель регрессии, так почему же caret предполагает модель классификации при таком использовании?


person Electronic Ant    schedule 01.07.2020    source источник
comment
Поскольку вы генерируете случайные данные, можете ли вы успешно выполнить подобное упражнение и вызвать caret только в R? Кроме того, почему бы просто не вызвать train с именованными аргументами: caret.train(x=dummy_x_R, y=dummy_y, method='glmnet')?   -  person Parfait    schedule 01.07.2020
comment
@Parfait: я не знал, что rpy2 такой гибкий. Документация не была мне ясна относительно того, что может быть названо в том, что требуется kwargs. Во всяком случае, я попробовал то, что вы предложили в R, и обнаружил, что поезд работает без ошибок: x <- data.frame(replicate(5, runif(10000))) , y <- runif(10000), caret_test <- caret::train(x = x, y = y, method = 'glmnet') В чем бы ни была проблема, похоже, она связана с тем, как rpy2 передает мои данные в caret. Любые идеи относительно того, как отлаживать это дальше?   -  person Electronic Ant    schedule 01.07.2020


Ответы (2)


В подобных ситуациях первым шагом является определение того, исходит ли неожиданный результат со стороны Python или rpy2, или со стороны R.

Преобразование из pandas в R или numpy в R работает, как и ожидалось, по крайней мере, для типов массивов:

>>> [x.typeof for x in dummy_x_R]                                                         
[<RTYPES.REALSXP: 14>,
 <RTYPES.REALSXP: 14>,
 <RTYPES.REALSXP: 14>,
 <RTYPES.REALSXP: 14>,
 <RTYPES.REALSXP: 14>]

Я предполагаю, что это то, что вы могли сделать для dummy_y.

>>> from rpy2.robjects import numpy2ri                                               
>>> with localconverter(robjects.default_converter + numpy2ri.converter):  
        dummy_y_R = robjects.conversion.py2rpy(dummy_y)
>>> dummy_y_R.typeof                                                                 
<RTYPES.REALSXP: 14>

Однако в основе проблемы лежит довольно тонкая деталь преобразования. dummy_y_R имеет форму (атрибут dim в R), в то время как caret ожидает массив R без формы (вектор в жаргоне R) для выполнения регрессии. Можно заставить dummy_y быть вектором R с помощью:

caret_test = caret.train(**{'x': dummy_x_R,
                            'y': robjects.FloatVector(dummy_y),
                            'method': 'glmnet'})
person lgautier    schedule 01.07.2020

Чтобы использовать методы R, убедитесь, что все входные данные являются объектами R. Поэтому рассмотрите возможность преобразования массива dummy_y numpy в вектор R, который вы можете сделать с base.as_double:

...
dummy_y_R = base.as_double(dummy_y)

caret.train(x=dummy_x_R, y=dummy_y_R, method='glmnet')
person Parfait    schedule 01.07.2020