Запуск glmnet с rpy2 на разреженной матрице дизайна?

У меня есть фрагмент python, который отлично работает для запуска GLMNET на np.array X и y. Однако, когда X представляет собой разреженную матрицу столбцов из scipy, код дает сбой, поскольку rpy2 не может преобразовать X. Я делаю очевидную ошибку?

MCVE — это:

import numpy as np
from scipy import sparse
from rpy2 import robjects
import rpy2.robjects.packages as rpackages
from rpy2.robjects import numpy2ri
from rpy2.robjects import pandas2ri

if __name__ == "__main__":
    X = sparse.rand(5, 20, density=0.1)
    y = np.random.randn(5)
    numpy2ri.activate()
    pandas2ri.activate()

    utils = rpackages.importr('utils')
    utils.chooseCRANmirror(ind=1) 
    if not rpackages.isinstalled('glmnet'):
        utils.install_packages("glmnet")
    glmnet = rpackages.importr('glmnet')

    glmnet = robjects.r['glmnet']
    glmnet_fit = glmnet(X, y, intercept=False, standardize=False)

И когда я запускаю его, я получаю NotImplementedError:

Conversion 'py2ri' not defined for objects of type '<class 'scipy.sparse.csc.csc_matrix'>'

Могу ли я предоставить X по-другому? Я был бы удивлен, если бы rpy2 не мог обрабатывать разреженные матрицы.


person P. Camilleri    schedule 28.01.2018    source источник


Ответы (3)


Вы можете создать разреженную матрицу с помощью rpy2 следующим образом:

import numpy as np
import rpy2.robjects as ro
from rpy2.robjects.packages import importr
from scipy import sparse

X = sparse.rand(5, 20, density=0.1).tocoo()
r_Matrix = importr("Matrix")
r_Matrix.sparseMatrix(
    i=ro.IntVector(X.row + 1),
    j=ro.IntVector(X.col + 1),
    x=ro.FloatVector(X.data),
    dims=ro.IntVector(X.shape))
person Wei Zhang    schedule 24.03.2019

Действительно, в rpy2 нет преобразователя Python -> R для вашего типа объекта. Ваш объект Python представляет собой не обычные массивы, а разреженную матрицу, как вы это заметили (точнее, scipy.sparse.csc.csc_matrix), реализованную как одно из числовых расширений, доступных для numpy. Поскольку сам numpy даже не требуется для использования rpy2, поддержка расширения numpy довольно скудна, за заметным исключением pandas, поскольку таблицы данных распространены повсеместно.

Вы можете написать свой собственный преобразователь из css_matrix в gcCMatrix в пакете R Matrix (https://stat.ethz.ch/R-manual/R-devel/library/Matrix/html/dgCMatrix-class.html), поскольку пакет glmnet выглядит уметь с ними обращаться.

Написание пользовательского конвертера потребует, как отобразить или скопировать содержимое объекта Python в его выбранный аналог R, но после этого вставка кода в rpy2 должна быть довольно простой: https://rpy2.github.io/doc/v2.9.x/html/generated_rst/s4class.html#custom-conversion

Подумайте о том, чтобы открыть проблему как «запрос функции» в системе отслеживания проблем rpy2 и сообщить о прогрессе и результате, надеясь, что это превратится в запрос на включение с модульными тестами.

person lgautier    schedule 28.01.2018

Также быстрым решением, которое может сработать, будет временное сохранение файла разреженной матрицы.

import numpy as np
import rpy2.robjects as ro
import warnings
from rpy2.rinterface import RRuntimeWarning
import rpy2.robjects.numpy2ri as numpy2ri
from scipy.io import mmwrite
mmwrite('temp.mtx',matrix)
ro.r('X <- readMM("temp.mtx")')

Однако мне было бы очень интересно, если бы кто-то придумал специальный конвертер, чтобы избежать копирования на диск.

person eddiemalou    schedule 29.07.2018