- Для получения количества параметров (весов) модели использовать функцию
utils.weight_util.get_weights_count. - Подготовлен простой класс датасета (
torch.utils.data.Dataset) для загрузки табличных данныхutils.data_utils.TableLoader:
import sys
import numpy as np
sys.path.append("<...>/LewenbergMarkvardt/lib")
from utils.data_utils import TableLoader
x = np.random.randn(5000, 100)
y = np.eye(2)[np.random.randint(0, 2, size=5000)] # OneHot для бинарной переменной
dataset = TableLoader(x, y, device='cpu')- Визуализация процесса обучения (из дампа pickle)
utils.visualisation_utils.plot_train_report- работает сcore.gpu_lm.train_levenbergиcore.lm_distributed_samples
loss_history, val_history, mu_history, ep_time = train_levenberg
pickle.dump(
{"loss": loss_history, "val": val_history, "mu": mu_history, "time": ep_time},
open("<path>", "wb"),
)
plot_train_report("<path>")Реализован алгоритм для обучения любых архитектур без кеширования в файловой системе. Ограничения для GPU 12Gb:
- число весов (параметров) сети
<=7000, - [число обучающих примеров
$\times$ число выходных нейронов]<=7000.
Данный алгоритм может применяться для решения задач с относительно небольшим количеством данных, небольшими моделями и необходимостью быстро переобучать модели.
Использование:
import sys
import torch
sys.path.append("<...>/LewenbergMarkvardt/lib")
from core.gpu_lm import train_levenberg
from utils.visualisation_utils import plot_train_report
from sklearn.metrics import balanced_accuracy_score
# входные данные
x = ... # torch.FloatTensor
y = ... # torch.FloatTensor
# Модель - может быть torch.nn.Sequential или torch.nn.Module -- ограничение только на количество параметров
# модель предварительно поместить на устройство вычислений
model = torch.nn.Sequential(
torch.nn.Linear(x.shape[1], 50),
torch.nn.Sigmoid()
torch.nn.Linear(50, y.shape[1]),
torch.nn.Softmax(dim=1)
).cuda()
# Функкция ошибки, рекомендована MSELoss (исходя из теоретических соображений оптимизации методами 2 порядка)
loss_fn = torch.nn.MSELoss()
# Добавление пользовательских метрик (callback вызывается при валидации)
acc_train = []
acc_val = []
def callback():
"""Пример пользовательской метрики"""
preds_train = net(x).detach().cpu().numpy().argmax(axis=1)
preds_val = net(x_val).detach().cpu().numpy().argmax(axis=1)
acc_train.append(accuracy_score(true_train, preds_train))
acc_val.append(accuracy_score(true_val, preds_val))
loss_history, val_history, mu_history, ep_time = train_levenberg(
model,
x,
y,
loss_fn,
val_loader=None,
snap_folder=None,
mu_init=10,
min_error=1e-2,
max_epochs=10,
inner_steps=10,
demping_coef=10,
device="cuda:0",
metrics_callbacks=[callback],
)
# Сохраняем все метрики
pickle.dump(
{"loss": loss_history, "val": val_history, "mu": mu_history, "time": ep_time},
open("test_run.pkl", "wb"),
)
# Визуализируем
plot_train_report("test_run.pkl")
# Объект model с настроенными весами - если не была указан `snap_folder`, нужно сохранить веса отдельно
torch.save(model.state_dict, 'weights.pkl')Описание аргументов:
model (torch.nn.Module): модель, которая оптимизируетсяx (torch.Tensor): входные данныеy (torch.Tensor): целевые меткиloss_fn (Callable): функция ошибки (потерь)val_loader (Union[torch.utils.data.DataLoader, None]): даталодер с валидационными данными (если есть -min_errorсчиатется на нем).Defaults to None.snap_folder (Union[str, None] = None): папка в которую складывать модели, если нет - не будет чекпоинтовmu_init (float, optional): начальное значение коэффициента регуляризации.Defaults to 10.min_error (float, optional): минимальная ошибка при которой останавливается обучение.Defaults to 1e-2.max_epochs (int, optional): максимльное число эпох при которых останавливается обучение.Defaults to 10.inner_steps (int, optional): количество внутренних шагов.Defaults to 10.demping_coef (float, optional): коэффициент изменения регуляризации.Defaults to 10.device (str, optional): устройство вычислений.Defaults to "cuda:0".metric_callbacks (list[Callable], optional): список callback'ов для вычисления метрик, вызываемых после каждой итерации валидации (включая начальную)
Возвращает:
Tuple[List[float], List[float], List[float], List[float]]: кортеж со списками истории обучения: ошибка, ошибка валидации, регуляризатор (mu), время вычислений на эпоху
Подробнее об алгоритме в разрезе нейронных сетей:
- А. Голубинский, А. Толстых, раздел 3 (статья автора репозитория)
- Hao Yu, Bogdan M. Wilamowski Levenberg–Marquardt Training -- общий случай для плоских (персептрон) сетей
Позволяет снять ограничение с количества обучающих примеров. Кеш имеет достаточно большой размер, для оценки использовать:
Например, для задачи с ~1.2 Gb,
знак не точного равенства, потому что не учитываются индексы и прочая служебная информация из np.save.
Эффективен в табличных задачах для построения бейзлайна, качество сопоставимо с XGBoost/CatBoost с поиском по сетке, однако, сильно меньше параметров. Не рекомендуется применять в задачах типа VAE с большим количеством выходных нейронов!
Использование:
import sys
import torch
from torch.utils.data import DataLoader
sys.path.append("E:/reseach/LewenbergMarkvardt/lib")
from core.lm_distributed_samples import train_distributed_levenberg
from utils.visualisation_utils import plot_train_report
from utils.data_utils import TableLoader
# Батч устанавливаем так, чтобы хватило GPU, перемешивать данные не нужно - они все будут использованы за один шаг оптимизации
train_loader = DataLoader(TableLoader(x_train, y_train), batch_size=5000, shuffle=False)
val_loader = DataLoader(TableLoader(x_test, y_test), batch_size=5000, shuffle=False)
# Модель - может быть torch.nn.Sequential или torch.nn.Module -- ограничение только на количество параметров
# модель предварительно поместить на устройство вычислений
net = torch.nn.Sequential(
torch.nn.Linear(x_train.shape[1], 200),
torch.nn.Sigmoid(),
torch.nn.Linear(200, y_train.shape[1]),
torch.nn.Softmax(dim=1)
).cuda()
loss_history, val_history, mu_history, ep_time = train_distributed_levenberg(
model,
train_loader,
torch.nn.MSELoss(),
val_loader=val_loader,
snap_folder=None,
mu_init=10,
min_error=1e-2,
max_epochs=10,
inner_steps=10,
demping_coef=10,
device="cuda:0",
temp_folder="./temp",
metrics_callbacks=[callback], # см. в примере `Классический Левенберг-Марквардт`
)
# Сохраняем все метрики
pickle.dump(
{"loss": loss_history, "val": val_history, "mu": mu_history, "time": ep_time},
open("test_run.pkl", "wb"),
)
# Визуализируем
plot_train_report("test_run.pkl")
# Объект model с настроенными весами - если не была указан `snap_folder`, нужно сохранить веса отдельно
torch.save(model.state_dict, 'weights.pkl')Описание аргументов:
model (torch.nn.Module): модель, которая оптимизируетсяx_loader (torch.utils.data.DataLoader): объект даталодера torch, batchsize будет соответсвовать размеру чанкаloss_fn (torch.nn.Module): функция ошибкиval_loader (Union[torch.utils.data.DataLoader, None]): даталодер с валидационными данными (если есть -min_errorсчиатется на нем).Defaults to None.snap_folder (Union[str, None] = None): папка в которую складывать модели, если нет - не будет чекпоинтов.Defaults to None.mu_init (int, optional): начальное значение коэффициента регуляризации.Defaults to 10.min_error (float, optional): минимальная ошибка при которой останавливается обучение.Defaults to 1e-2.max_epochs (int, optional): максимльное число эпох при которых останавливается обучение.Defaults to 10.inner_steps (int, optional): количество внутренних шагов.Defaults to 10.demping_coef (float, optional): коэффициент изменения регуляризации.Defaults to 10.device (str, optional): устройство вычислений.Defaults to "cuda:0".temp_folder (str, optional): папка с кешами (удаляется после обучения).Defaults to "./temp".metric_callbacks (list[Callable], optional): список callback'ов для вычисления метрик, вызываемых после каждой итерации валидации (включая начальную)
Возвращает:
Tuple[List[float], List[float], List[float], List[float]]: кортеж со списками истории обучения: ошибка, ошибка валидации, регуляризатор (mu), время вычислений на эпоху