При оптимизации SVGP с вероятностью Пуассона для большого набора данных я вижу то, что я считаю взрывающимися градиентами.После нескольких эпох я вижу колючее падение ELBO, которое затем очень медленно восстанавливается после избавления от всего достигнутого ранее прогресса.Примерно 21 итерация соответствует эпохе.
Этот всплеск (по крайней мере, второй) привел к полному сдвигу параметров (для векторов параметров я только что построил нормучтобы увидеть изменения):
Как с этим справиться?Мой первый подход заключается в том, чтобы обрезать градиент, но, похоже, для этого нужно копаться в коде gpflow.
Моя настройка:
Обучение работает с помощью естественных градиентов для вариационногопараметры и ADAM для остальных, с медленно (линейно) возрастающим графиком для естественной градиентной гаммы.
Размеры партии и точки индукции являются максимально возможными для моей установки (оба 2 ^ 12, с данныминабор, состоящий из ~ 88 тыс. образцов).Я включаю джиттер 1e-5 и инициализирую точки индукции с помощью kmeans.
Я использую комбинированное ядро, состоящее из комбинации RBF, Matern52, периодического и линейного ядра, в общей сложности 95 функций (многоиз них из-за одного горячего кодирования) все познаваемо.Шкалы длины преобразуются с помощью gpflow.transforms.
with gpflow.defer_build():
k1 = Matern52(input_dim=len(kernel_idxs["coords"]), active_dims=kernel_idxs["coords"], ARD=False)
k2 = Periodic(input_dim=len(kernel_idxs["wday"]), active_dims=kernel_idxs["wday"])
k3 = Linear(input_dim=len(kernel_idxs["onehot"]), active_dims=kernel_idxs["onehot"], ARD=True)
k4 = RBF(input_dim=len(kernel_idxs["rest"]), active_dims=kernel_idxs["rest"], ARD=True)
#
k1.lengthscales.transform = gpflow.transforms.Exp()
k2.lengthscales.transform = gpflow.transforms.Exp()
k3.variance.transform = gpflow.transforms.Exp()
k4.lengthscales.transform = gpflow.transforms.Exp()
m = gpflow.models.SVGP(X, Y, k1 + k2 + k3 + k4, gpflow.likelihoods.Poisson(), Z,
mean_function=gpflow.mean_functions.Constant(c=np.ones(1)),
minibatch_size=MB_SIZE, name=NAME)
m.mean_function.set_trainable(False)
m.compile()
ОБНОВЛЕНИЕ: с использованием только ADAM Следуя совету Марка, я переключился только на ADAM, что помогло мне избавиться от этого внезапного взрыва,Тем не менее, я все еще инициализировался только с натградской эпохой, которая, кажется, экономит много времени.
Кроме того, вариационные параметры меняются гораздо менее резко (с точки зрения их нормы как минимум).Я предполагаю, что они будут сходиться намного медленнее, но, по крайней мере, они стабильны.