🔴 Сложный ⏱️ 25 минут

Квазиньютоновские методы: быстрая оптимизация без Гессиана

Квазиньютоновские методы: быстрая оптимизация без Гессиана

🎯 Зачем это нужно?

Представь, что ты тренируешь нейронную сеть с миллионами параметров 🧠. Метод Ньютона требует вычисления и обращения матрицы Гессе размером миллион×миллион - это займёт вечность! А градиентный спуск сходится слишком медленно.

Квазиньютоновские методы - это золотая середина:

  • TensorFlow и PyTorch: L-BFGS для обучения моделей с небольшим числом параметров
  • SciPy optimize: BFGS используется в scipy.optimize.minimize по умолчанию
  • Финтех: оптимизация портфелей в Goldman Sachs и JPMorgan

📚 История вопроса

В 1970 году четыре математика независимо придумали один метод: Бройден, Флетчер, Гольдфарб и Шанно. Получился BFGS - один из самых популярных алгоритмов оптимизации! 🏆

Идея гениальна в простоте: “А что если не вычислять Гессиан точно, а аппроксимировать его по градиентам?”

💡 Интуиция

Метод Ньютона говорит: “Иди в направлении H⁻¹∇f” (обратный Гессиан × градиент) Градиентный спуск: “Иди против градиента: -∇f”

Квазиньютоновские методы: “Будем УГАДЫВАТЬ обратный Гессиан B ≈ H⁻¹, улучшая догадку на каждом шаге!”

[МЕДИА: image_01] Описание: Схема сравнения траекторий сходимости разных методов оптимизации на овражной функции Промпт: “optimization comparison illustration, showing convergence paths of gradient descent (zigzag), Newton method (direct), and quasi-Newton (smooth curve), contour plot background, educational style, clean modern design”

📐 Формальное определение

Квазиньютоновские методы итерационно строят аппроксимацию B_k ≈ H⁻¹(x_k):

Итерация:

  1. Направление: d_k = -B_k ∇f(x_k)
  2. Шаг: x_{k+1} = x_k + α_k d_k (α_k из line search)
  3. Обновление: B_{k+1} = обновить(B_k, s_k, y_k)

где s_k = x_{k+1} - x_k, y_k = ∇f(x_{k+1}) - ∇f(x_k)

Условие кривизны: B_{k+1} y_k = s_k (квазиньютоновское условие)

🔍 Примеры с разбором

BFGS формула обновления

Формула Бройдена-Флетчера-Гольдфарба-Шанно:

B_{k+1} = B_k + (s_k s_k^T)/(s_k^T y_k) - (B_k y_k y_k^T B_k)/(y_k^T B_k y_k)

Интуиция:

  • Первое слагаемое: “добавляем информацию о новом направлении s_k”
  • Второе слагаемое: “вычитаем старую неточную информацию в направлении y_k”

[МЕДИА: image_02] Описание: Пошаговая визуализация обновления аппроксимации Гессиана в BFGS Промпт: “step-by-step BFGS matrix update visualization, before and after matrices shown as heatmaps, arrows showing transformation, mathematical formulas, technical illustration style”

Пример: оптимизация функции Розенброка

f(x,y) = 100(y - x²)² + (1 - x)²

Код реализации:

import numpy as np
from scipy.optimize import minimize

def rosenbrock(x):
    return 100*(x[1] - x[0]**2)**2 + (1 - x[0])**2

def rosenbrock_grad(x):
    return np.array([
        -400*x[0]*(x[1] - x[0]**2) - 2*(1 - x[0]),
        200*(x[1] - x[0]**2)
    ])

# BFGS оптимизация
result = minimize(rosenbrock, [0, 0], method='BFGS', 
                  jac=rosenbrock_grad)
print(f"Решение: {result.x}")  # ≈ [1, 1]
print(f"Итераций: {result.nit}")  # ~30
🎮 Практика
Базовый уровень 🟢
Задание 1: Чем квазиньютоновские методы отличаются от метода Ньютона?
<details>
<summary>💡 Подсказка</summary>
Подумай про вычислительную сложность матрицы Гессе
</details>
<details>
<summary> Ответ</summary>
Квазиньютоновские методы аппроксимируют H⁻¹, не вычисляя точный Гессиан. Это даёт O(n²) вместо O(n³) операций на итерацию.
</details>
Задание 2: Что означает условие кривизны s_k^T y_k > 0?
<details>
<summary>💡 Подсказка</summary>
Связано с выпуклостью функции
</details>
<details>
<summary> Ответ</summary>
Это условие означает, что функция локально выпукла. Нарушение условия может привести к потере положительной определённости B_k.
</details>
Задание 3: Реализуй простое обновление ранга-1 (формула Бройдена):
B_{k+1} = B_k + (s_k - B_k y_k)(s_k - B_k y_k)^T / ||s_k - B_k y_k||²
code
Python
def broyden_update(B, s, y):
    # Твой код здесь
    pass
Продвинутый уровень 🟡
Задание 4: Объясни, почему L-BFGS эффективнее BFGS для больших размерностей?
<details>
<summary> Ответ</summary>
L-BFGS хранит только последние m векторов {s_i, y_i} вместо полной матрицы B. Память: O(mn) вместо O(n²).
</details>
Задание 5: Реализуй двухциклевую рекурсию L-BFGS для вычисления B_k f:
code
Python
def lbfgs_two_loop(grad, s_history, y_history, gamma=1.0):
    """L-BFGS двухциклевая рекурсия"""
    m = len(s_history)  # количество сохранённых пар
    q = grad.copy()
    alpha = np.zeros(m)
    
    # Первый цикл (назад)
    for i in range(m-1, -1, -1):
        # Твой код здесь
        pass
    
    # Начальное приближение
    r = gamma * q
    
    # Второй цикл (вперёд)  
    for i in range(m):
        # Твой код здесь
        pass
    
    return -r  # направление спуска
Челлендж 🔴
Задание 6: Докажи, что если B_k положительно определена и s_k^T y_k > 0, то B_{k+1} (BFGS обновление) тоже положительно определена.
Задание 7: Реализуй адаптивное масштабирование γ_k в L-BFGS:
γ_k = (s_{k-1}^T y_{k-1})/(y_{k-1}^T y_{k-1})
code
Python
def adaptive_scaling(s_prev, y_prev):
    # Вычисли оптимальное начальное приближение
    pass
⚠️ Частые ошибки
 Ошибка: Использование BFGS для невыпуклых функций без проверки условия кривизны
 Правильно: Проверяй s_k^T y_k > 0, иначе переходи к градиентному шагу
💡 Почему: Нарушение условия кривизны делает B_k неположительно определённой
 Ошибка: Хранение полной матрицы B в L-BFGS
 Правильно: Храни только векторы {s_i, y_i} и используй двухциклевую рекурсию
💡 Почему: Иначе теряешь главное преимущество L-BFGS - экономию памяти
 Ошибка: Забывать про line search в квазиньютоновских методах
 Правильно: Всегда используй Wolfe conditions для выбора длины шага
💡 Почему: Без правильного line search может не выполняться условие кривизны
🎓 Главное запомнить
 Квазиньютоновские методы аппроксимируют H⁻¹ без его вычисления
 BFGS: B_{k+1} = B_k + ρs_k s_k^T - B_k y_k y_k^T B_k/(y_k^T B_k y_k)
 L-BFGS экономит память, храня только последние m пар векторов
🔗 Связь с другими темами
Квазиньютоновские методы развивают идеи градиентной оптимизации (урок 287) и готовят к пониманию современных адаптивных методов типа Adam. В глубоком обучении L-BFGS используется для fine-tuning небольших моделей, где точность важнее скорости одной итерации.

Понял тему? Закрепи в боте! 🚀

Попрактикуйся на задачах и получи персональные рекомендации от AI

💪 Начать тренировку
💬 Есть вопрос? Спроси бота!