[БЕЗ_ЗВУКА] Познакомимся чуть подробнее с решением оптимизационных задач в библиотеке SkiPy. Ну, для начала импортируем уже известный нам модуль optimize. И определим некоторую функцию, на которой будем всё тестировать. Ну мы воспользуемся функцией Розенброка, которая часто используется для тестирования оптимизационных алгоритмов. У нее минимум в точке (1, 1). Этот минимум находится в продолговатом желобе, поэтому его не так просто найти. Ну и для начала применим какой-нибудь очень примитивный метод, например, перебор. И вот как вы видите, уже находится достаточно хорошо минимум, но иногда бывает важно, сколько раз мы вычисляем функцию. Потому что не все функции можно вычислить быстро. И здесь появляется интерес использовать разные другие методы. Если ваша функция достаточно плохая, ну то есть в ней есть разрывы, ну, может быть она не гладкая, то подойдет дифференциальная эволюция. Это генетический алгоритм, о генетических алгоритмах мы еще поговорим подробнее в дальнейшем. Ну и давайте посмотрим, что получится. Действительно, мы нашли точку минимума, нам потребовалось некоторое приличное количество итераций. Если же у вашей функции есть градиент... Если вы вдруг забыли, что такое градиент, то об этом мы тоже поговорим позднее, когда будем вспоминать ключевые понятия из математического анализа. Так вот, если у функции есть градиент, то можно воспользоваться градиентными методами. Для этого сначала мы определим градиент функции Розенброка, дальше резонно задаться вопросом — а верно ли мы его выписали? Может быть он на самом деле другой? На этот случай есть функция check grad. Она позволяет проверить. Вот мы сравнили наш градиент с численной оценкой для градиента, увидели, что расхождение небольшое. Ну и теперь можем спокойно его использовать. Один из популярных градиентных методов — bfgs. Он достаточно хорошо решает задачу оптимизации. Его мы и применим. Ну вот, как вы видите, здесь нам уже хватило всего 16 итераций, поэтому в случае, если функция достаточно хорошая и можно воспользоваться градиентными методами, не стоит пытаться использовать методы для негладких функций. Ну и вообще есть модуль optimize с функцией minimize, который не обязательно писать, какой метод использовать или передавать градиент. Если градиент нужен, она его оценит, какой метод использовать — тоже ей более-менее понятно. Ну, по умолчанию для достаточно хороших функций будут использоваться как раз bfgs. Ну вот, мы видим, что всё тоже получилось. Ну, на самом деле можно явно специфицировать, какой метод применять. Даже передать градиент, если нужно. Обратите внимание — здесь уже параметр, в который нужно передавать градиент, называется немного по-другому. Раньше для функции fmin bfgs он назывался fprime, ну а здесь он называется jac. Ну, вот запустим, посмотрим. Ну и видим, что всё получилось. На самом деле можно не передавать градиент bfgs, давайте сделаем так. Вот получился немного другой результат. И можно заметить, что он совпадает с результатом функции minimize. Без параметра method. Ну есть, конечно, много других разных методов, подробнее об этом можно посмотреть в документации функции minimize. Но мы, например, в этом курсе еще рассмотрим метод Нелдера — Мида. Он тоже часто используется для решения задач оптимизации.