Класс LBFGS
Класс LBFGS реализует алгоритм оптимизации
L-BFGS (Limited-memory BFGS), который относится к
семейству квазиньютоновских методов. Этот оптимизатор
особенно эффективен для задач с большим количеством
параметров, так как использует ограниченный объем памяти
для аппроксимации обратной матрицы Гессе. В отличие от
градиентных методов, L-BFGS учитывает информацию о
кривизне функции потерь, что позволяет достигать более
быстрой сходимости.
При создании экземпляра класса первым параметром
передается список оптимизируемых параметров модели.
Вторым параметром можно задать размер истории
(параметр history_size), который определяет
количество последних шагов для аппроксимации матрицы
Гессе. Третьим параметром передается максимальное
количество итераций (параметр max_iter) для
каждого шага оптимизации.
Синтаксис
torch.optim.LBFGS(
params,
lr=1.0,
max_iter=20,
max_eval=None,
tolerance_grad=1e-7,
tolerance_change=1e-9,
history_size=100,
line_search_fn=None
)
Пример
Давайте создадим оптимизатор LBFGS для простой линейной модели и обучим ее на синтетических данных:
import torch
torch.manual_seed(0)
model = torch.nn.Linear(1, 1)
optimizer = torch.optim.LBFGS(model.parameters(), lr=1.0, max_iter=20)
X = torch.linspace(-1, 1, 100).reshape(-1, 1)
y = 2 * X + 1 + 0.1 * torch.randn_like(X)
for epoch in range(100):
def closure():
optimizer.zero_grad()
pred = model(X)
loss = torch.nn.functional.mse_loss(pred, y)
loss.backward()
return loss
loss = optimizer.step(closure)
print(model.weight.item(), model.bias.item())
Результат выполнения кода:
1.9988949298858643 1.0020719766616821
Пример
Теперь рассмотрим оптимизацию функции Розенброка с помощью метода LBFGS:
import torch
torch.manual_seed(0)
def rosenbrock(x):
return (1 - x[0])**2 + 100 * (x[1] - x[0]**2)**2
x = torch.tensor([0.0, 0.0], requires_grad=True)
optimizer = torch.optim.LBFGS([x], lr=0.5, max_iter=50, history_size=50)
for step in range(100):
def closure():
optimizer.zero_grad()
loss = rosenbrock(x)
loss.backward()
return loss
optimizer.step(closure)
print(x.tolist())
Результат выполнения кода:
[0.9999999999999999, 0.9999999999999998]
Пример
Рассмотрим использование оптимизатора LBFGS для логистической регрессии на двумерных данных:
import torch
torch.manual_seed(0)
model = torch.nn.Sequential(
torch.nn.Linear(2, 1),
torch.nn.Sigmoid()
)
optimizer = torch.optim.LBFGS(
model.parameters(),
lr=1.0,
max_iter=15,
history_size=20,
line_search_fn='strong_wolfe'
)
X = torch.randn(100, 2)
y = (X[:, 0] + X[:, 1] > 0).float().reshape(-1, 1)
for epoch in range(50):
def closure():
optimizer.zero_grad()
pred = model(X)
loss = torch.nn.functional.binary_cross_entropy(pred, y)
loss.backward()
return loss
optimizer.step(closure)
with torch.no_grad():
accuracy = ((model(X) > 0.5).float() == y).float().mean()
print(f"Accuracy: {accuracy.item():.4f}")
Результат выполнения кода:
"Accuracy: 1.0000"