Изучение rpy2 для вызова методов R из Python

В этом посте вы узнаете, как вызывать методы R из Python с помощью библиотеки rpy2.

Мы рассмотрим пример, связанный с прогнозированием. Мы определим и запустим функции R, которые объединяют прогнозы, сделанные моделями на основе Python.

Введение

Даже если Python — ваш любимый язык, R все равно иногда может быть полезен.

Я не хочу вступать в дискуссию о Python и R. В настоящее время я в основном использую Python. Но многие замечательные методы доступны только в R. И слишком хлопотно реализовывать их с нуля.

Библиотека rpy2 помогла нам. Это позволяет вам запускать код R в Python. Структуры данных R, такие как matrix или data.frame, преобразуются в объекты numpy или pandas. Также легко интегрировать пользовательские функции R в рабочий процесс Python.

Итак, как же работает rpy2?

Пример с использованием Opera

Мы сосредоточимся на использовании пакета R opera. Вы можете использовать этот пакет для объединения прогнозов.

Прежде чем погрузиться в rpy2, давайте рассмотрим проблему, которую мы решаем.

Учебник по ансамблям прогнозирования

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

Чаще всего комбинация делается с помощью простого среднего. Каждая модель в ансамбле имеет одинаковое значение для окончательного прогноза. Но лучший способ объединения прогнозов — использование динамических весов. Таким образом, веса каждой модели адаптируются к изменениям временного ряда.

Опера

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

Что особенного в опере?

Opera расшифровывается как онлайн-прогнозирование с помощью агрегации экспертов. Некоторые из лучших методов комбинирования прогнозов доступны только в этом пакете R. Они содержат интересные теоретические свойства наихудших сценариев комбинации прогнозов. Это может быть полезно для разработки надежных моделей прогнозирования.

Полный пример того, как работает опера, вы можете найти здесь.

В оставшейся части этой статьи мы будем использовать Opera для объединения прогнозов, сделанных моделями Python.

Тематическое исследование

Как и в предыдущей статье, мы обратимся к временным рядам спроса на энергию в качестве примера.

Этот пример включает три шага:

  • Построение ансамбля;
  • Создание функции R, которую нам нужно запустить;
  • Использование этих функций для динамической комбинации прогнозов.

Давайте углубимся в каждый из этих шагов по очереди.

Создание ансамбля

Во-первых, мы создаем ансамбль, используя методы Python scikit-learn.

Вот как вы можете это сделать:

import pandas as pd

from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.neighbors import KNeighborsRegressor
from sklearn.linear_model import Lasso, Ridge, ElasticNetCV

from pmdarima.datasets import load_taylor

# src module available here: https://github.com/vcerqueira/blog
from src.tde import time_delay_embedding

series = load_taylor(as_series=True)
series.index = pd.date_range(end=pd.Timestamp(day=27, month=8, year=2000), periods=len(series), freq='30min')
series.name = 'Series'
series.index.name = 'Index'

# train test split
train, test = train_test_split(series, test_size=0.1, shuffle=False)

# ts for supervised learning
train_df = time_delay_embedding(train, n_lags=10, horizon=1).dropna()
test_df = time_delay_embedding(test, n_lags=10, horizon=1).dropna()

# creating the predictors and target variables
X_train, y_train = train_df.drop('Series(t+1)', axis=1), train_df['Series(t+1)']
X_test, y_test = test_df.drop('Series(t+1)', axis=1), test_df['Series(t+1)']

# defining four models composing the ensemble
models = {
    'RF': RandomForestRegressor(),
    'KNN': KNeighborsRegressor(),
    'LASSO': Lasso(),
    'EN': ElasticNetCV(),
    'Ridge': Ridge(),
}

# training and getting predictions
test_forecasts = {}
for k in models:
    models[k].fit(X_train, y_train)
    test_forecasts[k] = models[k].predict(X_test)

# predictions as pandas dataframe
forecasts_df = pd.DataFrame(test_forecasts, index=y_test.index)

Мы создали пять моделей: случайный лес, K-ближайший сосед и три линейные модели (Ridge, LASSO и ElasticNet). Их обучают авторегрессивным способом.

Вот пример их прогнозов:

Теперь давайте воспользуемся opera R, чтобы объединить эти прогнозы с помощью rpy2. Мы рассмотрим две полезные вещи об этой библиотеке:

  • как определить и использовать функцию R в Python;
  • как преобразовать структуры данных между двумя языками.

Определение функций R в Python

Вы можете определить функцию R в многострочной строке Python:

import rpy2.robjects as ro

# polynomially weighted average
method = 'MLpol'

# defining the R function in a Python multi-line string
ro.r(
    """
    define_mixture_r <-
      function(model) {
        library(opera)

        opera_model <- mixture(model = model, loss.type = 'square')

        return(opera_model)
      }
    """
)

# storing the function in the global environment
define_mixture_func = ro.globalenv['define_mixture_r']

# using the function
opera_model = define_mixture_func(method)

Строка, содержащая функцию, передается модулю rpy2.robjects. Затем метод globalenv делает его доступным для использования в Python.

Вы можете определить любую функцию, которую хотите. Обратите внимание, что R и все необходимые пакеты R должны быть установлены в вашей системе, чтобы это работало.

О функции в примере выше. Он используется для создания оперного объекта (называемого mixture). Обязательным параметром является метод, который используется для объединения прогнозов. Мы используем MLpol, основанный на полиномиально взвешенном среднем.

Вот еще несколько полезных альтернатив:

  • EWA: экспоненциально взвешенное среднее;
  • OGD: Градиентный спуск онлайн;
  • FTRL: следуйте за регулярным лидером;
  • Ридж: онлайн-регрессия хребта.

Преобразование данных из pandas в R и наоборот

Вот еще одна функция, которая нам нужна:

from rpy2.robjects import pandas2ri

ro.r(
    """
    update_mixture_r <-
      function(opera_model, predictions,trues) {
        library(opera)
        for (i in 1:length(trues)) {
            opera_model <- predict(opera_model, newexperts = predictions[i, ], newY = trues[i])
        }
        return(opera_model)
      }
    """
)

update_mixture_func = ro.globalenv['update_mixture_r']
# activating automatic data conversions
pandas2ri.activate()

# using the function above
## predictions is a pandas DataFrame and trues is a pandas Series
## opera_model is a rpy2 object that represents a R data structure
new_opera_model = update_mixture_func(opera_model, predictions, trues)

# deactivating automatic data conversions
pandas2ri.deactivate()

Определение функции такое же, как и раньше. Но эта функция требует дополнительных входных данных помимо opera_model (которую мы определили выше). Нам нужно передать R data.frame (прогнозы) и vector (истины) в качестве входных данных.

Вы можете использовать pandas2ri для преобразования структур данных между Python и R. Таким образом вы передаете pd.DataFrame (прогнозы) и pd.Series (истины). rpy2 преобразует их автоматически. После применения функции rpy2 преобразует результаты обратно в структуры данных Python.

Собираем все вместе

Наконец, вернемся к нашему исследованию.

Я обернул приведенные выше функции в класс Python под названием Opera. Вы можете проверить его код на моем Github.

Вот как это использовать:

# https://github.com/vcerqueira/blog/blob/main/src/ensembles/opera_r.py
from src.ensembles.opera_r import Opera

opera = Opera('MLpol')
opera.compute_weights(forecasts_df, y_test)

ensemble = (opera.weights.values * forecasts_df).sum(axis=1)

Вот как распределяются веса, присвоенные каждой модели:

Эти веса меняются со временем, чтобы справиться с динамикой временного ряда:

Ключевые выводы

В этой статье затронуты две темы:

  • Использование библиотеки rpy2 для запуска кода R в Python;
  • Делаем динамическую комбинацию прогнозов с помощью пакета Opera R.

Мы использовали rpy2 для определения и запуска нескольких функций R в Python. Мы сосредоточились на конкретном пакете под названием Opera. Тем не менее, вы можете определить и запустить любую функцию, которую захотите.

В rpy2 есть намного больше. Вот ссылка на документацию:

Пакет Opera полезен для динамических комбинаций прогнозов. Его методы эффективны и обеспечивают ценные теоретические гарантии эффективности прогнозирования.

Спасибо за прочтение и до встречи в следующей истории!

Статьи по Теме

Дальнейшие чтения

[1] Документация rpy2: https://rpy2.github.io/doc/v3.5.x/html/

[2] Документация Opera: https://cran.r-project.org/web/packages/opera/vignettes/opera-vignette.html