使用带插入符号的 rpy2 尝试分类而不是回归

Using rpy2 w/ caret attempts classification instead of regression

我有在 Python 中创建和预处理的数据,我想将其导入 R 并使用 glmnet 执行 k 折交叉验证 LASSO 拟合。我想控制每次折叠中使用哪些观察结果,所以我想使用 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

这可能是什么原因造成的?根据 ,caret 可能假设我的至少一个变量是整数类型,因此默认认为这是一个分类问题而不是回归问题。

但是,我已经使用 typeof 检查了 X 和 y,它们显然是双打:

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 以这种方式使用时假定为分类模型?

在这种情况下,第一步是确定意外结果是来自 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 具有“形状”(R 中的属性 dim),而 caret 需要无形状的 R 数组(R 术语中的“向量”)以执行回归。可以强制 dummy_y 成为一个 R 向量:

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

要使用 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')