【问题标题】:MLPRegressor learning_rate_init for lbfgs solver in sklearnsklearn 中 lbfgs 求解器的 MLPRegressor learning_rate_init
【发布时间】:2020-07-09 03:43:34
【问题描述】:

对于一个学校项目,我需要评估具有不同学习率的神经网络。我选择sklearn 来实现神经网络(使用MLPRegressor 类)。由于训练数据非常小(20 个实例,每个 2 个输入和 1 个输出),我决定使用 lbfgs 求解器,因为像 sgdadam 这样的随机求解器对于这种大小的数据没有意义。

该项目要求以不同的学习率测试神经网络。但是,根据文档,lbfgs 求解器无法做到这一点:

learning_rate_init 双倍,默认=0.001 使用的初始学习率。它控制更新权重的步长。仅在solver='sgd' 或'adam' 时使用。

有没有一种方法可以让我以某种方式访问​​ lbfgs 求解器的学习率并对其进行修改,或者这个问题甚至没有意义?

【问题讨论】:

  • 如果只是为了学校项目就去随机梯度下降,为什么要使用 lbfgs?
  • 对于 20 个训练数据条目来说,随机指标似乎是一个糟糕的选择。如果没有其他选择,我会这样做,但这似乎有点违背练习的目的。
  • 如果可能的话,我肯定会在这 20 个示例中使用数据增强。
  • @alan.elkin 你介意详细说明吗?
  • @gphilip 使用该数据集,您的网络将倾向于记住您的训练示例,并且可能无法推广到新的未见示例。我不知道您的训练示例是什么,但是如果您可以以某种方式创建从真实示例派生的新合成示例(并且不会丢失您尝试从输入中提取的核心),它可能会帮助您的网络更好地泛化.搜索“数据增强”了解更多详情

标签: python scikit-learn neural-network


【解决方案1】:

LBFGS 是一种不使用学习率的优化算法。对于您的学校项目,您应该使用 sgdadam。至于它是否更有意义,我想说的是,在 20 个数据点上训练一个神经网络并没有多大意义,除了学习基础知识。

LBFGS 是一种准牛顿优化方法。它基于这样一个假设,即您寻求优化的函数可以通过二阶泰勒展开在局部近似。大致是这样进行的:

  • 从最初的猜测开始
  • 使用雅可比矩阵计算最速下降方向
  • 使用 Hessian 矩阵计算下降步数并到达下一个点
  • 重复直到收敛

与牛顿方法的区别在于准牛顿方法使用雅可比矩阵和/或黑森矩阵的近似值。

牛顿法和拟牛顿法需要比梯度下降法更平滑的优化函数,但收敛速度更快。实际上,使用 Hessian 矩阵计算下降步更有效,因为它可以预见到局部最优的距离,因此不会最终围绕它振荡或收敛非常缓慢。另一方面,梯度下降仅使用雅可比矩阵(一阶导数)来计算最速下降的方向,并使用学习率作为下降步骤

实际上,梯度下降用于深度学习,因为计算 Hessian 矩阵的成本太高。

在这里谈论牛顿方法(或准牛顿方法)的学习率是没有意义的,它只是不适用。

【讨论】:

  • 谢谢!这清除了它,其中大部分都超出了我的想象。
【解决方案2】:

不是一个完整的答案,但希望是一个好的指针。

sklearn.neural_network.MLPRegressor 在 github 上实现 multilayer_perceptron 模块。

通过检查模块,我注意到与其他求解器不同的是,scitkit 在 Base 类本身中实现了 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
                },

代码位于_multilayer_perceptron.py模块的第430行

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)

【讨论】:

  • 在使用 LGBFS 时谈论学习率是没有意义的,因为它是 quasi newton method,下降步骤由算法本身计算。对其进行调整会破坏算法收敛的理论保证并使其效率低下。
猜你喜欢
  • 2018-12-06
  • 2018-06-24
  • 2017-06-16
  • 2021-12-24
  • 2019-01-09
  • 1970-01-01
  • 2019-07-19
  • 1970-01-01
  • 2018-12-05
相关资源
最近更新 更多