Найти в Дзене
Машинное обучение

Основы меморизации в Python

Понимание кеширования функций в Python

Фото Kaboompics .com на Pexels
Фото Kaboompics .com на Pexels

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

Давайте начнем!

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

Напоминаем, что факториал определяется для целого числа n, так что он является произведением этого целого числа и всех целых чисел под ним. Например

1! = 1,

2! = 2*1= 2

3! = 3*2*1 = 6

и так далее. Мы можем определить рекурсивную функцию следующим образом:

-2

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

Теперь напечатаем первые 10 факториалов:

-3
-4

Кажется, все работает нормально. Теперь давайте попробуем отобразить первые 5000 терминов:

-5

Это возвращает следующую ошибку, которая является защитой Python от переполнения стека (нехватки памяти):

-6

Это происходит потому, что с каждым последующим вычислением мы повторяем работу.

Рассмотрим, как рекурсивная функция вычисляет каждый член:

1! = 1,

2! = 2*1= 2

3! = 3*2! = 6

4! =4*3! = 24

Обратите внимание, на 4! повторяем расчет 3! и 2 !. Если бы у нас был способ запоминать / сохранять эти значения при их вычислении, мы бы избегали повторения вычислений. Это формирует мотивацию для метода мемоизации.

Теперь давайте пройдемся по этапам реализации метода мемоизации. Чтобы продолжить, давайте инициализируем словарь:

-7

Далее мы определим нашу функцию мемоизации. Сначала мы проверяем, меньше ли введенное значение 2, и возвращаем 1, если это так:

-8

Затем мы проверяем, есть ли входное значение в словаре. Если это не так, мы сохраняем значение факториала в словаре и возвращаем значение для ключа ввода:

-9

Полная функция:

-10

А теперь давайте попробуем отобразить факториалы до 5000! с нашей новой функцией:

-11

И мы видим, что расчет достигает 4999! успешно (вывод усечен):

-12

Есть более простой способ реализовать мемоизацию, используя меньше кода. Давайте рассмотрим нашу исходную рекурсивную функцию:

-13

Мы можем импортировать декоратор из модуля functools, называемого lru_cache, который позволяет нам кэшировать наши значения. Название означает «последний использованный кеш». Мы можем достичь той же производительности, что и наш метод factorial_memo, используя этот декоратор:

-14
-15

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

ВЫВОДЫ

Подводя итог, в этом посте мы обсудили метод мемоизации в Python. Во-первых, мы показали, как простая реализация рекурсивной функции становится очень медленной после вычисления многих факториальных членов. Затем мы определили новый метод, в котором мы сохраняли прошлые значения, которые мы вычислили в словаре. Это приводит к значительному ускорению вычислений. Затем мы обсудили декоратор «lru_cache», который позволил нам достичь производительности, аналогичной нашему методу «factorial_memo», с меньшим количеством кода. Если вы хотите узнать больше о мемоизации, я рекомендую вам ознакомиться с руководствами на YouTube https://www.youtube.com/watch?v=Qk0zUZW-U_M&t=302s. Надеюсь, вы нашли этот пост полезным / интересным. Код в этом посте доступен на GitHub https://github.com/spierre91/medium_code/blob/master/data_structures_and_algorithms/memo_factorial.py. Спасибо за чтение!

Наука
7 млн интересуются