MLPRegressor learning_rate_init для решателя lbfgs в sklearn - PullRequest
0 голосов
/ 28 марта 2020

Для школьного проекта мне нужно оценить нейронную сеть с разными скоростями обучения. Я выбрал sklearn для реализации нейронной сети (используя класс MLPRegressor). Поскольку обучающие данные довольно малы (20 экземпляров, 2 входа и 1 выход каждый), я решил использовать решатель lbfgs, поскольку стохастические решатели c, такие как sgd и adam для данных такого размера, не имеет смысл.

Проект предусматривает тестирование нейронной сети с различной скоростью обучения. Однако это невозможно при использовании решателя lbfgs в соответствии с документацией:

learning_rate_init double, по умолчанию = 0,001 Используемая начальная скорость обучения. Он контролирует размер шага при обновлении весов. Используется только в том случае, если solver = 'sgd' или 'adam'.

Есть ли способ, с помощью которого я могу каким-то образом получить доступ к скорости обучения решателя lbfgs и изменить ее, или этот вопрос даже не вызывает смысл?

Ответы [ 2 ]

0 голосов
/ 06 апреля 2020

LBFGS - это алгоритм оптимизации, который просто не использует скорость обучения . Для целей вашего школьного проекта вы должны использовать sgd или adam . Относительно того, имеет ли это смысл или нет, я бы сказал, что обучение нейронной сети на 20 точках данных не имеет большого смысла, за исключением изучения основ.

LBFGS - это квазиньютоновская оптимизация метод. Он основан на гипотезе о том, что функция, которую вы стремитесь оптимизировать, может быть аппроксимирована локально с помощью разработки Тейлора второго порядка. Примерно так:

  • Начните с первоначального предположения
  • Используйте матрицу Якоби для вычисления направления наискорейшего спуска
  • Используйте матрицу Гессе для вычисления шаг спуска и достижение следующей точки
  • повторение до сходимости

Разница с методами Ньютона заключается в том, что квазиньютоновские методы используют приближенные значения для якобиана и / или гессиана matrices.

Методы Ньютона и квазиньютона требуют большей плавности от функции для оптимизации, чем градиентный спуск, но сходятся быстрее. Действительно, вычисление шага спуска с помощью матрицы Гессе является более эффективным, поскольку оно может предвидеть расстояние до локального оптимума, таким образом, не заканчивая колебаниями вокруг него или сходясь очень медленно. С другой стороны, при градиентном спуске используется только якобианская матрица (производные первого порядка) для вычисления направления наискорейшего спуска и используется скорость обучения в качестве шага спуска .

Практически градиент Спуск используется в глубоком обучении, потому что вычисление матрицы Гессена было бы слишком дорого.

Здесь нет смысла говорить о скорости обучения для методов Ньютона (или квазиньютоновских методов), это просто не применимо.

0 голосов
/ 01 апреля 2020

Не полный ответ, но, надеюсь, хороший указатель.

В sklearn.neural_network.MLPRegressor реализован multilayer_perceptron модуль на github.

осмотрев модуль, я заметил, что в отличие от других решателей, scitkit реализует алгоритм lbfgs в самом базовом классе. Таким образом, вы можете легко адаптировать его.

Кажется, что они не используют какую-либо скорость обучения, поэтому вы можете адаптировать этот код и умножить потери на скорость обучения, которую вы хотите протестировать. Я просто не совсем уверен, имеет ли смысл добавлять скорость обучения в контексте lbfgs.

Я считаю, что потеря при использовании здесь:

        opt_res = scipy.optimize.minimize(
                self._loss_grad_lbfgs, packed_coef_inter,
                method="L-BFGS-B", jac=True,
                options={
                    "maxfun": self.max_fun,
                    "maxiter": self.max_iter,
                    "iprint": iprint,
                    "gtol": self.tol
                },

код находится в строка 430 модуля _multilayer_perceptron.py

def _fit_lbfgs(self, X, y, activations, deltas, coef_grads,
                   intercept_grads, layer_units):
        # Store meta information for the parameters
        self._coef_indptr = []
        self._intercept_indptr = []
        start = 0

        # Save sizes and indices of coefficients for faster unpacking
        for i in range(self.n_layers_ - 1):
            n_fan_in, n_fan_out = layer_units[i], layer_units[i + 1]

            end = start + (n_fan_in * n_fan_out)
            self._coef_indptr.append((start, end, (n_fan_in, n_fan_out)))
            start = end

        # Save sizes and indices of intercepts for faster unpacking
        for i in range(self.n_layers_ - 1):
            end = start + layer_units[i + 1]
            self._intercept_indptr.append((start, end))
            start = end

        # Run LBFGS
        packed_coef_inter = _pack(self.coefs_,
                                  self.intercepts_)

        if self.verbose is True or self.verbose >= 1:
            iprint = 1
        else:
            iprint = -1

        opt_res = scipy.optimize.minimize(
                self._loss_grad_lbfgs, packed_coef_inter,
                method="L-BFGS-B", jac=True,
                options={
                    "maxfun": self.max_fun,
                    "maxiter": self.max_iter,
                    "iprint": iprint,
                    "gtol": self.tol
                },
                args=(X, y, activations, deltas, coef_grads, intercept_grads))
        self.n_iter_ = _check_optimize_result("lbfgs", opt_res, self.max_iter)
        self.loss_ = opt_res.fun
        self._unpack(opt_res.x)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...