написано в декабре 2019 года.

В моем предыдущем посте от середины 2018 года описан мой опыт обучения с пакетами R для мета пакетов агрегатора машинного обучения: mlr, caret и SuperLerner. Эти пакеты объединяют структуру машинного обучения с несколькими независимыми индивидуальными многомерными моделями / пакетами и предоставляют мета структуру машинного обучения вокруг них для общих задач, таких как повторная выборка, настройка, сравнительный анализ, ансамбль и другие.

С тех пор в экосистеме R произошла пара крупных разработок, которые заменили устаревшие пакеты, которые, кхм, кхм, неудобно признавать, начали страдать от… расползания.

Текущие пакеты рефакторинга, которые я буду обсуждать здесь:

  1. Млр - ›млр3 ( страница , инструкция )
  2. Каретка - ›tidyModels ( github )

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

Снижение объема работ ... вы говорите мне, что ваш "вчерашний современный пакет" на самом деле дерьмо?

Когда я впервые познакомился с mlr, я подумал про себя: «Ничего себе, какие огромные усилия были вложены в этот пакет, не говоря уже о обширной документации, он, вероятно, будет длиться вечно». Оглядываясь назад, я обнаружил, что определенно стоило потратить время на его изучение, несмотря на его нетривиальный «диалект», который отличался от пакета «caret» старого доброго друга, к которому я уже привык.

Затем, в один прекрасный день, я был удивлен, обнаружив, что разработчики mlr на самом деле больше не удовлетворены своей текущей версией mlr и уже работают над разработкой нового пакета mlr3, который в основном состоит из R6, продвинутой системы для объектно-ориентированный класс, выходящий за пределы моей зоны комфорта.

Мои первоначальные опасения были следующие: это конец моего романа с MLR? Как я собираюсь справиться не только с проблемой сложности машинного обучения как таковой, но и с добавлением сложной структуры класса R6 поверх него, о которой я ничего не знаю?

Но после обработки ужасающих новостей в течение некоторого времени возникло новое осознание ... стоит ли R6 настолько радикально изучить кривую обучения разработчиков mlr3, что они собираются выбросить все свои прежние усилия по MLR и никогда не оглядываться назад , у него должна быть какая-то функциональность, дающая некоторые преимущества… возможно, мне пора воспользоваться его преимуществами.

Не поймите меня неправильно! Я всегда хотел изучить и использовать R6, несмотря на то, что уже был большим поклонником системы S4 для объектно-ориентированных классов. Однако, возможно, это было слишком удобно, чтобы получить выгоду от его запуска на основе многих сложных пакетов (в том числе tidyverse), которые удерживали меня от погружения в новый неизведанный мир R6.

Хотя mlr3 все еще находится в разработке, я подумал, что, по крайней мере, смогу заработать некоторое время, пока он официально не превратится в стабильную версию, поэтому мне не придется страдать от болезненного времени роста, и если mlr больше не будет поддерживаться, Я всегда мог вернуться к карете.

Но не только mlr был оставлен разработчиками… Caret испытывал аналогичные проблемы ползучести. Однако в случае Caret его разработчик (и) объединился с экспертами RStudio, чтобы восполнить недостающее звено во фреймворке tidyverse, и выпустил коллекцию пакетов под общим термином tidymodels, в том числе:

  • Rsample и рецепты предварительной обработки данных (преобразование, задерживающая выборка и т. Д.).
  • Пастернак, для создания моделей
  • Эталон, для измерения производительности модели

Tidymodels был разработан с использованием подхода tidyverse, зрелого популярного интуитивного подхода, наряду с большим количеством полезной документации и виньеток. Как заядлый пользователь tidyverse, я не мог желать большего.

О связных машинах…

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

Вы когда-нибудь пытались починить или устранить неполадки в одной из больших копировальных машин, которая делает все, от двусторонней печати, переплета и, возможно, даже чашки молочного коктейля, но с двумя ложками сахара? Так много деликатных деталей в такой сплоченной системе? Иди разберись. Но что вы собираетесь делать в случае случайного замятия бумаги? Как узнать, где именно неисправность? Ожидается ли, что вы вынимаете каждую деталь, пока не диагностируете источник проблемы?

Увы, не беспокойтесь! Будьте уверены, вам даже не нужно вызывать специалиста! Копировальный аппарат настолько умен, что он автоматически проинструктирует вас, где именно искать возможную проблему, поэтому вам не нужно разбирать все по частям. Подробные инструкции подробно проинструктируют вас, какую именно дверцу / зажим нужно нажать, чтобы открыть еще один скрытый ящик, в котором возможно замятие бумаги. Вуаля. Фиксированный. Осталось только закрыть дверь. Машина автоматически запускает быструю самопроверку и готова к выполнению следующей задачи.

Какая волшебная и элегантная машина. Нам не нужно беспокоиться о грязных чернилах и разрушительных лазерных лучах, стреляющих повсюду. Вместо этого вся магия творится внутри копировального аппарата. То, что происходит в машине, остается в машине. Все, что нужно пользователю, - это получить организованную, чистую, разложенную по корзинам распечатку.

Так почему же объектно-ориентированный? То, что происходит в объекте, остается в объекте!

Для меня объектно-ориентированная система - это ограниченный ограниченный класс, который включает в себя другие вещи (атрибуты, функции / методы), поэтому вещи хранятся ТОЛЬКО там, где они принадлежат, а не повсюду. Да, иметь дело с такими ограничениями очень больно, но с точки зрения разработки программного обеспечения они были намеренно созданы так, чтобы их раздражало «непрерывность» с единственной целью - спасти нас от нашего собственного беспорядка!

S3 и S4 являются общими системами для объектно-ориентированных классов, где S4 является более ограниченным, поддерживающим множественные отправления. В своей предыдущей серии публикаций я описал, как разработчики Bioconductor используют систему S4 для своих собственных сложных задач анализа больших наборов данных с помощью передовых статистических методов. Хотя каретка и mlr не поддерживают гладкую структуру популярного класса S4 SummarizedExperiment от Bioconductor для данных геномного анализа, существуют пакеты Bioconductor, которые пытаются делать такие же вещи, как каретка и mlr, то есть объединять многомерные модели вокруг объекта SummarizedExperiment. Другой подход - пакет Bioc2mlr, идущий другим путем, сводя объекты S4 к стандартному широкому формату фрейма данных, который ожидают mlr и каретка, но с потерей / разрывом тугих узлов, которые удерживали несколько слотов связанными. друг другу.

Почему R6? Самостоятельное назначение, бережливость к объектам:

На собственном опыте я убедился на собственном горьком опыте, что чем меньше объектов управляется в коде, тем меньше беспорядка и когнитивной нагрузки приходится обрабатывать, или, проще говоря, меньше мест для поиска ошибок, когда что-то не так. идет не так, как ожидалось.

В соответствии с этим подходом к объектной бережливости, я большой поклонник работы с оператором конвейера% ›%, который, как я считаю, способствует созданию более чистого кода с минимизацией объектов. Тем не менее, оператор% ‹›% 'self-assignment' даже делает больше, избавляя нас от избыточности использования объекта дважды: один раз в качестве исходного класса для начала, а второй раз в качестве назначения, которое будет назначено с новым исправленным содержанием.

Система R6 поддерживает элегантный способ изменения состояния объекта и семантики ссылок. Это означает, что вам даже не нужно задание. Все, что вам нужно, это вызвать метод (функцию) объекта. Он автоматически обновит назначенный слот внутри объекта новым содержимым, созданным функцией. Вуаля. Чтобы привыкнуть к нему, может потребоваться время, но как только вы это сделаете, традиционный код с присваиванием внезапно покажется излишним, повторяющимся, загроможденным и менее элегантным.

Элегантность - это, конечно, личный вкус, но для меня она означает более сильный и менее «уязвимый» код. Он все еще может сломаться, но, поскольку это было очень строго с самого начала, вы будете точно знать, с чего начать поиск причины проблемы в механике объекта, и, как только она будет обнаружена, как локально исправить ее безопасным способом, без случайного повреждения других связанных частей вашего кода.

Хорошо, к настоящему времени вы уже поняли, что я большой поклонник объектно-ориентированных классов, поэтому я могу быть сильно предвзятым в моих следующих разделах :), так что вернемся к ML ...

Старый добрый бензиновый двигатель против красивого электрического…

Вы водите электромобиль? Я не знаю (пока), но я знаю, что он более надежен, и когда он ломается, у традиционной механики может не быть инструментов, чтобы открыть и исправить. Они могут получить очень подробное сообщение журнала с кодом неисправности, но у них может даже не быть инструментов, чтобы открыть крышку электродвигателя. Вместо этого вам может потребоваться отправить его в специальный магазин, специализирующийся на этой новой передовой технологии, и у них будут инструменты, чтобы быстро диагностировать, найти проблему и исправить ее.

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

Сходства:

С одной стороны, и mlr3, и tidymodels используют одни и те же алгоритмы для многомерных моделей, повторной выборки и т. Д. И, вероятно, будут обеспечивать очень похожие характеристики модели (точность). Также могут быть различия в масштабируемости, которые выходят за рамки этой публикации.

Несходства:

На мой взгляд, есть 3 основных принципиальных отличия, первые два прямо вытекают из архитектуры класса R6:

  1. Наличие изолированного, уплотненного, разделенного «пространства» для ML-анализа (mlr3) по сравнению с традиционной функцией R, которая что-то делает и возвращает результат в той или иной структуре (tidymodels).

Я просто считаю более элегантным (то есть стабильным, последовательным, менее хрупким), когда специализированные задачи выполняются в отведенном для них месте, когда тщательно отслеживаются и заботятся только о том, что происходит, а что выплевывается. Больше ничего.

mlr3 R6 может быть нетривиальным для многих пользователей, но для тех, кто ценит такой строгий класс, это рай. tidymodels порадует многих других традиционной системой R S3, которая также извлекает выгоду из гибкости простого запуска функции, не беспокоясь о крайних сценариях, которые случайно нарушают функцию только тогда, когда вы настраиваете ее полностью до ее границ. Для многих пользователей они могут даже не приблизиться к этим границам, так что зачем об этом беспокоиться.

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

Хорошие пакеты, которые служат дольше, имеют очень широкий спектр применения. достаточно широк, чтобы разработчики продемонстрировали, как можно настроить основные функции пакета. В контексте машинного обучения настройка и добавление новых многомерных моделей (учащихся), новых показателей производительности, новых преобразований и т. Д. Как mlr3, так и tidymodels делают это очень хорошо с точки зрения документации (учебник показывает, как добавлять новые методы с нуля), и с точки зрения жестких ограничений (пока что до некоторого уровня).

Однако ограничения R6 mlr3 могут быть более строгими, чем ограничения, налагаемые tidymodels, которые масштабируются, когда вы связываете их вместе с другими частями методов ML. Другими словами, в таком мощном, многофункциональном конвейере, который объединяет передискретизацию + настройку + бенчмаркинг +…, даже небольшой всплеск олова (например, NA в векторе предсказания, которого не должно было быть), который каким-то образом застревает в колесах, может вызвать побочные эффекты, которые могут привести к поломке всей машины. Насколько вероятно это случится? Возможно, этого вообще никогда не произойдет, но лучший способ минимизировать вероятность этого - использовать более ограниченную систему.

Если мне повезет (ну, мне нравится использовать такие методы до предела), такое случается время от времени, и когда это случается, совсем не весело тратить драгоценное время в длительных экспедициях на поиск причины ошибки. Возможно, вас это вообще не волнует, но некоторым это нравится.

3. Предварительная обработка: настройка новых составных преобразований (монад)

Как упоминалось в моем предыдущем посте, сложная часть предварительной обработки состоит в том, чтобы гарантировать, что какое бы преобразование (я) ни было применено к набору обучающих данных, нужно применить к набору тестовых данных. Это нетривиальная задача, когда нужно передать параметры, сохраняющие детали преобразования. Оба пакета также поддерживают монадное программирование, что означает возможность компоновки различных преобразований в любом порядке, гарантируя при этом совместимость каналов друг с другом.

Менее тривиальная задача - написать собственное настраиваемое преобразование предварительной обработки. Это совсем не тривиально, несмотря на обширную документацию по recipe и mlr3pipelines. В целом, оба подхода имеют схожие возможности, но каждый разработал свою собственную терминологию и жаргон, к которым может потребоваться некоторое время, чтобы привыкнуть к ним.

4. Модели для выживания и без присмотра

В настоящее время поддерживается mlr3, но похоже, что разработчики tidymodels планируют добавить и его.

5. Не могли бы вы просто показать мне код?

Https://mlr3pipelines.mlr-org.com/articles/comparison_mlr3pipelines_mlr_sklearn.html имеет хорошее сравнение кода между mlr3 и tidymodels (и другими).

Видение:

Как и в моем предыдущем посте, действительно важно, чтобы пользователь чувствовал себя комфортно с документацией и имел доступ к надежным каналам поддержки. Я также предполагаю, что будут разработаны функции «преобразователя» из одного пакета в другой, по крайней мере, для преобразований. Богатая коллекция библиотек преобразований - общий интерес обоих подходов, несмотря на вышеупомянутые различия.

По какой-то причине, не совсем понятной мне, оба подхода еще не предоставляют назначенный пакет / функции для инструментов Interpretable Model-Agnostic, таких как LIME, DALEX и iml (среди прочих). Мне эти инструменты машинного обучения для публикаций кажутся дополнительными к общей структуре машинного обучения, хотя некоторые из упомянутых пакетов могут уже поддерживать их.

Итог:

  1. Уважайте старые добрые устаревшие пакеты. Не переходите на следующий уровень, пока не освоите их!

Сначала я бы посоветовал новым практикам машинного обучения поиграть с устаревшими версиями caret и mlr, чтобы вы познакомились с основными терминами, объемом и функциональностью общих компонентов машинного обучения.

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

2. Если вам не нужно усложнять задачу, сделайте это просто.

Многие практикующие, вероятно, даже не обратят внимания на различия, о которых я упоминал выше. В этом случае, вероятно, предпочтительным вариантом будет использование tidymodels. Он прост, понятен, хорошо документирован и поддерживается.

3. Разве вы не всегда хотели изучать R6, но у вас никогда не было для этого достаточно мотивации?

Не упускайте эту возможность и не отставайте.

4. Когда что-то ломается…

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

К концу дня даже современный инструмент - это завтрашний устаревший устаревший пакет, но, живя настоящим моментом, в настоящее время следует делать ставку на наиболее стабильное решение, которое с меньшей вероятностью сломается.

Почему это сломалось? Если бы он не сломался, не нужно было бы писать этот пост вообще.

Заявление об ограничении ответственности:

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

А что насчет SuperLearner, преобразованного в вселенную? Кстати, это тоже было сделано с R6. Я не знаю. Может быть, в будущем блоге. Однако я хотел бы упомянуть, что академический интерес группы разработчиков, стоящей за этим, в основном мотивирован и склоняется к целевой оценке максимального правдоподобия / минимальных потерь (TMLE), которая является статистическим подходом для оценки параметров, а не двумя другими пакетами. возможно, более инженерные. По этому поводу недавно появилась отличная документация здесь.

Интересный факт: mlr3 никогда не упоминает p-значения. Даже не уверен, что это специально.

Неужели я забыл ключевого игрока в этом (полуобъективном) обзоре? Если да, дайте мне знать. Если у меня нет веской причины исключить его, я не возражаю добавить его.

Посетите мой блог и страницу на github, чтобы узнать о других интересных вещах.

[email protected]

Профиль LinkedIn