Простое и быстрое кеширование результатов для конвейеров машинного обучения

Это первая часть серии статей: Создание быстрого и эффективного легковесного конвейера машинного обучения с использованием Joblib.

Давайте начнем наше путешествие по разработке конвейеров машинного обучения с помощью Joblib. В этой статье мы увидим сравнительное исследование кэширования результатов с помощью Joblib вместе с кодом.

Наброски

  1. Потребность рынка
  2. Способы сокращения времени вычислений
  3. Зачем использовать Joblib?
  4. Способы кеширования результата в Joblib
  5. Более быстрый поиск в кеше - дальнейшее сокращение общего времени выполнения
  6. Очистка кеша
  7. Резюме - сравнение различных методов кеширования
  8. Перед тем как уйти - полная ссылка на код и следующая в строке

Не стесняйтесь переходить к любому разделу, который вам нравится, но я рекомендую прочитать статью полностью. Вряд ли это займет 10 минут.

Потребность на рынке

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

Способы сокращения времени вычислений

В основном есть два способа сократить общее время обработки конвейера:

  • Кеширование результатов

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

  • Распараллеливание независимых задач

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

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

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

Зачем использовать Joblib?

Вот несколько причин, по которым мне нравится Joblib:

  • Нет кривой обучения
  • Никаких зависимостей кроме Python
  • Подходит для научных вычислений с большими наборами данных
  • Интегрируйте без изменения исходного кода
  • Прозрачное распараллеливание
  • Вычисления по запросу

Способы кеширования результата в Joblib

Давайте углубимся в код и расскажем, как кэшировать результаты с помощью Joblib.

Установить пакет

pip install joblib

Импорт и инициализация

Определите большой ввод

Shape of input1:  (10000, 10000)
Shape of input2:  (5000, 5000)

Кеширование результатов функции: наша основная цель

Memory класс определяет метод cache для кэширования нашей функции. Есть два способа передать функцию Memory.cache

Метод 1 - передача функции непосредственно в Memory.cache

Определите нашу функцию

Давайте вызовем функцию с нашим вводом и запишем время выполнения.

%%time 
input1_result = func_mem(input1)

Давайте вызовем функцию с тем же вводом

%%time 
input1_result = func_mem(input1)

Если вы посмотрите на вывод выше, вы увидите, что операторы печати не были выполнены. Это связано с тем, что вместо повторного вычисления результата был возвращен кешированный результат.

Обратите внимание на разницу во времени выполнения. Время выполнения сократилось в 6 раз. В этом сила кеширования!

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

Метод 2 - Memory.cache в качестве декоратора

Определите нашу функцию

Давайте вызовем функцию с нашим вводом и запишем время выполнения.

%%time 
input1_decorator_result = func_as_decorator(input1)

Давайте снова вызовем функцию с тем же вводом

%%time 
input1_decorator_result = func_as_decorator(input1)

Обратите внимание на разницу во времени выполнения до и после кеширования.

Важно. Знаете ли вы, что мы можем действовать быстрее 😱. Продолжайте читать!

Более быстрый поиск в кеше - дальнейшее сокращение общего времени выполнения

Хорошие новости: мы можем еще больше сократить общее время выполнения за счет сокращения поиска в кеше

При глубоком обучении данные в основном поступают в виде массивов NumPy независимо от того, работаете ли вы над компьютерным зрением, временными рядами или проблемами обработки естественного языка. Умный способ сократить время - использовать memmap (Карта памяти) в NumPy. Карта памяти ускоряет поиск в кеше при перезагрузке больших массивов NumPy.

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

Давайте посмотрим на быстрый код

Давайте вызовем функцию с нашим вводом и запишем время выполнения.

%%time
input1_memmap = func_memmap(x=input1)

Давайте снова вызовем функцию с нашим вводом.

%%time
input1_memmap = func_memmap(x=input1)

Обратите внимание на разницу во времени выполнения до и после кеширования.

Очистка кеша

При построении нашего конвейера нам иногда может потребоваться очистить кеш определенной функции или весь каталог кеша.

Очистка кеша для отдельной функции

Очистим кеш для уже определенных функций func_mem и func_as_decor

func_mem.clear() 
func_as_decorator.clear()

Очистить кеш для всех функций

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

# we will use our memory object for this purpose 
mem.clear()

Резюме

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

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

Ключевые моменты

  • Разница во времени выполнения до и после кеширования.
  • Разница во времени выполнения после кэширования, с использованием карты памяти и без нее.

Перед тем, как ты уйдешь

Полная ссылка на код

Вы можете ознакомиться с полным кодом на Kaggle: Кэширование диска с помощью Joblib.

Следующий в очереди

В следующей статье мы увидим, как распараллелить независимые задачи в Joblib, чтобы ускорить выполнение.

Обратная связь

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

Связаться со мной

Следуй за мной на Medium, чтобы получать мои последние статьи и проекты.

Подключиться на других платформах 🙂:

  • "Персональный сайт"
  • LinkedIn