【问题标题】:Using rpy2 w/ caret attempts classification instead of regression使用带有插入符号的 rpy2 尝试分类而不是回归
【发布时间】:2020-10-22 08:14:20
【问题描述】:

我有在 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

这可能是什么原因造成的?根据this previous question 的说法,插入符号可能假设我的变量中至少有一个是整数类型,因此默认认为这是一个分类而不是回归问题。

但是,我使用 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 以这种方式使用时假设一个分类模型?

【问题讨论】:

  • 既然您正在生成随机数据,您能否成功运行类似的练习并仅在 R 中调用caret?另外,为什么不简单地使用命名参数调用traincaret.train(x=dummy_x_R, y=dummy_y, method='glmnet')
  • @Parfait:我没有意识到 rpy2 如此灵活。对于我来说,文档并不清楚在需要 kwargs 时可以命名什么。无论如何,我尝试了您在 R 中的建议,发现火车运行时没有任何错误:x &lt;- data.frame(replicate(5, runif(10000)))y &lt;- runif(10000)caret_test &lt;- caret::train(x = x, y = y, method = 'glmnet') 无论问题是什么,似乎与rpy2 如何将我的数据传递到@987654338 @。关于如何进一步调试的任何想法?

标签: python r r-caret rpy2 glmnet


【解决方案1】:

在这种情况下,第一步是确定意外结果是来自 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'})

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2019-01-16
      • 2018-04-17
      • 2019-04-19
      • 2015-06-09
      • 2017-02-06
      • 2015-09-06
      • 1970-01-01
      • 2016-12-10
      • 2020-02-05
      相关资源
      最近更新 更多