精华内容
下载资源
问答
  • nadam
    千次阅读
    2022-01-14 11:16:14

    1.NAdam集大成

    前面我们讲Adam的时候,提到Adam是Adaptive+Momentum。更前面的时候,我们还提到Nesterov,如果把Nesterov跟Adam结果,就是我们最后的集大成者NAdam。

    class Nadam(Optimizer):
      """Nesterov Adam optimizer.
    
      Much like Adam is essentially RMSprop with momentum,
      Nadam is Adam RMSprop with Nesterov momentum.
    
      Default parameters follow those provided in the paper.
      It is recommended to leave the parameters of this optimizer
      at their default values.
    
      Arguments:
          lr: float >= 0. Learning rate.
          beta_1/beta_2: floats, 0 < beta < 1. Generally close to 1.
          epsilon: float >= 0. Fuzz factor. If `None`, defaults to `K.epsilon()`.
      """
    
      def __init__(self,
                   lr=0.002,
                   beta_1=0.9,
                   beta_2=0.999,
                   epsilon=None,
                   schedule_decay=0.004,
                   **kwargs):
        super(Nadam, self).__init__(**kwargs)
        with K.name_scope(self.__class__.__name__):
          self.iterations = K.variable(0, dtype='int64', name='iterations')
          self.m_schedule = K.variable(1., name='m_schedule')
          self.lr = K.variable(lr, name='lr')
          self.beta_1 = K.variable(beta_1, name='beta_1')
          self.beta_2 = K.variable(beta_2, name='beta_2')
        if epsilon is None:
          epsilon = K.epsilon()
        self.epsilon = epsilon
        self.schedule_decay = schedule_decay
    ...
    

    tensorflow中Nadam源码,开篇两句话就揭示了本质:
    1.Adam的本质是带动量的RMSprop。
    2.Nadam是带Nesterov动量的Adam RMSprop。

    β 1 , β 2 \beta_1, \beta_2 β1,β2等参数与Adam的含义与数值都是一致的。

    2.如何选择优化算法

    1.如果数据稀疏,一般自适应算法比较好,比如AdaGrad, AdaDelta, RMSProp, Adam等。
    2.一般来说,Adam会是一个不错的选择。
    3.可以在训练初始阶段,采用Adam提升收敛速度,后期在切换到SGD进行调优。

    参考文献

    https://zhuanlan.zhihu.com/p/32338983

    更多相关内容
  • 深度学习中的优化算法之Nadam介绍

          之前在https://blog.csdn.net/fengbingchun/article/details/125018001 介绍过深度学习优化算法Adam,这里介绍下深度学习的另一种优化算法Nadam。

          Nadam:Nesterov-accelerated Adaptive Moment Estimation,梯度下降优化算法的扩展,是Adam(Adaptive Moment Estimation)和NAG(Nesterov Accelerated Gradient)两种算法的结合,可以提高优化算法的性能。如下图所示,截图来自:https://arxiv.org/pdf/1609.04747.pdf

         

           Nadam是Adam的扩展,添加了NAG,是一种改进的动量类型。

          Note:公式26对应于带动量的SGD中的公式4;公式27等价于公式26;公式28对应于NAG中的公式5;公式30对应于Adam中的公式19、20、21;公式31等价于公式30

          以下是与Nadam不同的代码片段:

          1. 在原有枚举类Optimization的基础上新增Nadam:

    enum class Optimization {
    	BGD, // Batch Gradient Descent
    	SGD, // Stochastic Gradient Descent
    	MBGD, // Mini-batch Gradient Descent
    	SGD_Momentum, // SGD with Momentum
    	AdaGrad, // Adaptive Gradient
    	RMSProp, // Root Mean Square Propagation
    	Adadelta, // an adaptive learning rate method
    	Adam, // Adaptive Moment Estimation
    	AdaMax, // a variant of Adam based on the infinity norm
    	NAG, // Nesterov Accelerated Gradient
    	Nadam // Nesterov-accelerated Adaptive Moment Estimation
    };

          2. calculate_gradient_descent函数:

    void LogisticRegression2::calculate_gradient_descent(int start, int end)
    {
    	switch (optim_) {
    		case Optimization::Nadam: {
    			int len = end - start;
    			std::vector<float> m(feature_length_, 0.), v(feature_length_, 0.), mhat(feature_length_, 0.), vhat(feature_length_, 0.);
    			std::vector<float> z(len, 0.), dz(len, 0.);
    			float beta1t = 1., beta2t = 1.;
    			for (int i = start, x = 0; i < end; ++i, ++x) {
    				z[x] = calculate_z(data_->samples[random_shuffle_[i]]);
    				dz[x] = calculate_loss_function_derivative(calculate_activation_function(z[x]), data_->labels[random_shuffle_[i]]);
    
    				beta1t *= beta1_;
    				beta2t *= beta2_;
    
    				for (int j = 0; j < feature_length_; ++j) {
    					float dw = data_->samples[random_shuffle_[i]][j] * dz[x];
    					m[j] = beta1_ * m[j] + (1. - beta1_) * dw; // formula 19
    					v[j] = beta2_ * v[j] + (1. - beta2_) * (dw * dw); // formula 19
    
    					mhat[j] = m[j] / (1. - beta1t); // formula 20
    					vhat[j] = v[j] / (1. - beta2t); // formula 20
    
    					w_[j] = w_[j] - alpha_ * (beta1_ * mhat[j] + (1. - beta1_) * dw / (1. - beta1t)) / (std::sqrt(vhat[j]) + eps_); // formula 33
    				}
    
    				b_ -= (alpha_ * dz[x]);
    			}
    		}
    			break;
    		case Optimization::NAG: {
    			int len = end - start;
    			std::vector<float> v(feature_length_, 0.);
    			std::vector<float> z(len, 0), dz(len, 0);
    			for (int i = start, x = 0; i < end; ++i, ++x) {
    				z[x] = calculate_z2(data_->samples[random_shuffle_[i]], v);
    				dz[x] = calculate_loss_function_derivative(calculate_activation_function(z[x]), data_->labels[random_shuffle_[i]]);
    
    				for (int j = 0; j < feature_length_; ++j) {
    					float dw = data_->samples[random_shuffle_[i]][j] * dz[x];
    					v[j] = mu_ * v[j] + alpha_ * dw; // formula 5
    					w_[j] = w_[j] - v[j];
    				}
    
    				b_ -= (alpha_ * dz[x]);
    			}
    		}
    			break;
    		case Optimization::AdaMax: {
    			int len = end - start;
    			std::vector<float> m(feature_length_, 0.), u(feature_length_, 1e-8), mhat(feature_length_, 0.);
    			std::vector<float> z(len, 0.), dz(len, 0.);
    			float beta1t = 1.;
    			for (int i = start, x = 0; i < end; ++i, ++x) {
    				z[x] = calculate_z(data_->samples[random_shuffle_[i]]);
    				dz[x] = calculate_loss_function_derivative(calculate_activation_function(z[x]), data_->labels[random_shuffle_[i]]);
    
    				beta1t *= beta1_;
    
    				for (int j = 0; j < feature_length_; ++j) {
    					float dw = data_->samples[random_shuffle_[i]][j] * dz[x];
    					m[j] = beta1_ * m[j] + (1. - beta1_) * dw; // formula 19
    					u[j] = std::max(beta2_ * u[j], std::fabs(dw)); // formula 24
    
    					mhat[j] = m[j] / (1. - beta1t); // formula 20
    
    					// Note: need to ensure than u[j] cannot be 0.
    					// (1). u[j] is initialized to 1e-8, or
    					// (2). if u[j] is initialized to 0., then u[j] adjusts to (u[j] + 1e-8)
    					w_[j] = w_[j] - alpha_ * mhat[j] / u[j]; // formula 25
    				}
    
    				b_ -= (alpha_ * dz[x]);
    			}
    		}
    			break;
    		case Optimization::Adam: {
    			int len = end - start;
    			std::vector<float> m(feature_length_, 0.), v(feature_length_, 0.), mhat(feature_length_, 0.), vhat(feature_length_, 0.);
    			std::vector<float> z(len, 0.), dz(len, 0.);
    			float beta1t = 1., beta2t = 1.;
    			for (int i = start, x = 0; i < end; ++i, ++x) {
    				z[x] = calculate_z(data_->samples[random_shuffle_[i]]);
    				dz[x] = calculate_loss_function_derivative(calculate_activation_function(z[x]), data_->labels[random_shuffle_[i]]);
    
    				beta1t *= beta1_;
    				beta2t *= beta2_;
    
    				for (int j = 0; j < feature_length_; ++j) {
    					float dw = data_->samples[random_shuffle_[i]][j] * dz[x];
    					m[j] = beta1_ * m[j] + (1. - beta1_) * dw; // formula 19
    					v[j] = beta2_ * v[j] + (1. - beta2_) * (dw * dw); // formula 19
    
    					mhat[j] = m[j] / (1. - beta1t); // formula 20
    					vhat[j] = v[j] / (1. - beta2t); // formula 20
    
    					w_[j] = w_[j] - alpha_ * mhat[j] / (std::sqrt(vhat[j]) + eps_); // formula 21
    				}
    
    				b_ -= (alpha_ * dz[x]);
    			}
    		}
    			break;
    		case Optimization::Adadelta: {
    			int len = end - start;
    			std::vector<float> g(feature_length_, 0.), p(feature_length_, 0.);
    			std::vector<float> z(len, 0.), dz(len, 0.);
    			for (int i = start, x = 0; i < end; ++i, ++x) {
    				z[x] = calculate_z(data_->samples[random_shuffle_[i]]);
    				dz[x] = calculate_loss_function_derivative(calculate_activation_function(z[x]), data_->labels[random_shuffle_[i]]);
    
    				for (int j = 0; j < feature_length_; ++j) {
    					float dw = data_->samples[random_shuffle_[i]][j] * dz[x];
    					g[j] = mu_ * g[j] + (1. - mu_) * (dw * dw); // formula 10
    
    					//float alpha = std::sqrt(p[j] + eps_) / std::sqrt(g[j] + eps_);
    					float change = -std::sqrt(p[j] + eps_) / std::sqrt(g[j] + eps_) * dw; // formula 17
    					w_[j] = w_[j] + change;
    
    					p[j] = mu_ * p[j] +  (1. - mu_) * (change * change); // formula 15
    				}
    
    				b_ -= (eps_ * dz[x]);
    			}
    		}
    			break;
    		case Optimization::RMSProp: {
    			int len = end - start;
    			std::vector<float> g(feature_length_, 0.);
    			std::vector<float> z(len, 0), dz(len, 0);
    			for (int i = start, x = 0; i < end; ++i, ++x) {
    				z[x] = calculate_z(data_->samples[random_shuffle_[i]]);
    				dz[x] = calculate_loss_function_derivative(calculate_activation_function(z[x]), data_->labels[random_shuffle_[i]]);
    
    				for (int j = 0; j < feature_length_; ++j) {
    					float dw = data_->samples[random_shuffle_[i]][j] * dz[x];
    					g[j] = mu_ * g[j] + (1. - mu_) * (dw * dw); // formula 18
    					w_[j] = w_[j] - alpha_ * dw / std::sqrt(g[j] + eps_);
    				}
    
    				b_ -= (alpha_ * dz[x]);
    			}
    		}
    			break;
    		case Optimization::AdaGrad: {
    			int len = end - start;
    			std::vector<float> g(feature_length_, 0.);
    			std::vector<float> z(len, 0), dz(len, 0);
    			for (int i = start, x = 0; i < end; ++i, ++x) {
    				z[x] = calculate_z(data_->samples[random_shuffle_[i]]);
    				dz[x] = calculate_loss_function_derivative(calculate_activation_function(z[x]), data_->labels[random_shuffle_[i]]);
    
    				for (int j = 0; j < feature_length_; ++j) {
    					float dw = data_->samples[random_shuffle_[i]][j] * dz[x];
    					g[j] += dw * dw;
    					w_[j] = w_[j] - alpha_ * dw / std::sqrt(g[j] + eps_); // formula 8
    				}
    
    				b_ -= (alpha_ * dz[x]);
    			}
    		}
    			break;
    		case Optimization::SGD_Momentum: {
    			int len = end - start;
    			std::vector<float> v(feature_length_, 0.);
    			std::vector<float> z(len, 0), dz(len, 0);
    			for (int i = start, x = 0; i < end; ++i, ++x) {
    				z[x] = calculate_z(data_->samples[random_shuffle_[i]]);
    				dz[x] = calculate_loss_function_derivative(calculate_activation_function(z[x]), data_->labels[random_shuffle_[i]]);
    
    				for (int j = 0; j < feature_length_; ++j) {
    					float dw = data_->samples[random_shuffle_[i]][j] * dz[x];
    					v[j] = mu_ * v[j] + alpha_ * dw; // formula 4
    					w_[j] = w_[j] - v[j];
    				}
    
    				b_ -= (alpha_ * dz[x]);
    			}
    		}
    			break;
    		case Optimization::SGD:
    		case Optimization::MBGD: {
    			int len = end - start;
    			std::vector<float> z(len, 0), dz(len, 0);
    			for (int i = start, x = 0; i < end; ++i, ++x) {
    				z[x] = calculate_z(data_->samples[random_shuffle_[i]]);
    				dz[x] = calculate_loss_function_derivative(calculate_activation_function(z[x]), data_->labels[random_shuffle_[i]]);
    
    				for (int j = 0; j < feature_length_; ++j) {
    					float dw = data_->samples[random_shuffle_[i]][j] * dz[x];
    					w_[j] = w_[j] - alpha_ * dw;
    				}
    
    				b_ -= (alpha_ * dz[x]);
    			}
    		}
    			break;
    		case Optimization::BGD:
    		default: // BGD
    			std::vector<float> z(m_, 0), dz(m_, 0);
    			float db = 0.;
    			std::vector<float> dw(feature_length_, 0.);
    			for (int i = 0; i < m_; ++i) {
    				z[i] = calculate_z(data_->samples[i]);
    				o_[i] = calculate_activation_function(z[i]);
    				dz[i] = calculate_loss_function_derivative(o_[i], data_->labels[i]);
    
    				for (int j = 0; j < feature_length_; ++j) {
    					dw[j] += data_->samples[i][j] * dz[i]; // dw(i)+=x(i)(j)*dz(i)
    				}
    				db += dz[i]; // db+=dz(i)
    			}
    
    			for (int j = 0; j < feature_length_; ++j) {
    				dw[j] /= m_;
    				w_[j] -= alpha_ * dw[j];
    			}
    
    			b_ -= alpha_*(db/m_);
    	}
    }

          执行结果如下图所示:测试函数为test_logistic_regression2_gradient_descent,多次执行每种配置,最终结果都相同。图像集使用MNIST,其中训练图像总共10000张,0和1各5000张,均来自于训练集;预测图像总共1800张,0和1各900张,均来自于测试集。Nadam和Adam配置参数相同的情况下,即学习率为0.001,beta1为0.8,beta2为0.8888,eps为1e-8,Adam耗时29秒,Nadam耗时25秒,它们的识别率均为100%

          GitHub: https://github.com/fengbingchun/NN_Test

    展开全文
  • 公式上的变化如下: 可以看出,Adamax学习率的边界范围更简单 Nadam Nadam类似于带有Nesterov动量项的Adam。公式如下: 可以看出,Nadam对学习率有了更强的约束,同时对梯度的更新也有更直接的影响。一般而言,在...

    作者丨ycszen

    来源|https://zhuanlan.zhihu.com/p/22252270

    编辑丨极市平台

    导读

     

    本文仅对一些常见的优化方法进行直观介绍和简单的比较。

    前言 

    本文仅对一些常见的优化方法进行直观介绍和简单的比较,各种优化方法的详细内容及公式只好去认真啃论文了,在此我就不赘述了。

    SGD 

    此处的SGD指mini-batch gradient descent,关于batch gradient descent, stochastic gradient descent, 以及 mini-batch gradient descent的具体区别就不细说了。现在的SGD一般都指mini-batch gradient descent。 

    SGD就是每一次迭代计算mini-batch的梯度,然后对参数进行更新,是最常见的优化方法了。即:

    363972b2e35f1ad147c65e80f9a43494.png

    56bf517337ec22a06924804f950c8340.png

    其中,453c83281f95d2b807f3302bb56f68b4.png是学习率,b8e8343c6093fa35aec19094585794b0.png是梯度 SGD完全依赖于当前batch的梯度,所以 可理解为允许当前batch的梯度多大程度影响参数更新 

    缺点:(正因为有这些缺点才让这么多大神发展出了后续的各种算法) 

    选择合适的learning rate比较困难 - 对所有的参数更新使用同样的learning rate。对于稀疏数据或者特征,有时我们可能想更新快一些对于不经常出现的特征,对于常出现的特征更新慢一些,这时候SGD就不太能满足要求了

    SGD容易收敛到局部最优,并且在某些情况下可能被困在鞍点【原来写的是“容易困于鞍点”,经查阅论文发现,其实在合适的初始化和step size的情况下,鞍点的影响并没这么大。感谢@冰橙的指正】

    Momentum

    momentum是模拟物理里动量的概念,积累之前的动量来替代真正的梯度。公式如下:

    196e43c0c5d1108f1a10768fd068112f.png

    ffdad3f4e18d8753eee41a9afaeeec6f.png

    其中,14033b62f5567257560575f72fd9affc.png是动量因子

    特点:

    • 下降初期时,使用上一次参数更新,下降方向一致,乘上较大的47dbbf976690b1c1f6ba4a64ab1fe31e.png能够进行很好的加速 

    • 下降中后期时,在局部最小值来回震荡的时候,03dbe28ba33bd06fc2cb22055995c779.png, 使得更新幅度增大,跳出陷阱 

    • 在梯度改变方向的时候,996a40cd4c9e7bf6faaffd4560e12ece.png能够减少更新 总而言之,momentum项能够在相关方向加速SGD,抑制振荡,从而加快收敛

    Nesterov

    nesterov项在梯度更新时做一个校正,避免前进太快,同时提高灵敏度。将上一节中的公式展开可得:

    1ad8b17b67d9320b07ae8d4f886fe255.png

    可以看出, 并没有直接改变当前梯度e9080c19419e7356f2dbc6e4a5423581.png,所以Nesterov的改进就是让之前的动量直接影响当前的动量。即: 

    1ad061403b89ff034049a1e8afe1334d.png

    ecce980e189d77845c7bd3ff18efe47c.png

    4d4e8c98173244f61578856a4f9320fb.png

    所以,加上nesterov项后,梯度在大的跳跃后,进行计算对当前梯度进行校正。如下图:

    a3b9738b22cd7bf6d6a890964192ae20.png

    momentum首先计算一个梯度(短的蓝色向量),然后在加速更新梯度的方向进行一个大的跳跃(长的蓝色向量),nesterov项首先在之前加速的梯度方向进行一个大的跳跃(棕色向量),计算梯度然后进行校正(绿色梯向量) 

    其实,momentum项和nesterov项都是为了使梯度更新更加灵活,对不同情况有针对性。但是,人工设置一些学习率总还是有些生硬,接下来介绍几种自适应学习率的方法 

    Adagrad 

    Adagrad其实是对学习率进行了一个约束。即: 

    13a92e183bd16c0e889b008d7edc386f.png

    b94f7a54ef68840322e1688c256b2db1.png

    此处,对bd10f469eb23051e4f7c684cb670d9a7.png从1到57c26027a1bba88e7677df95ff937554.png进行一个递推形成一个约束项regularizer,9caeb2b1ca4b108c754498cf7f1a3b0c.png  , e用来保证分母非0 

    特点

    • 前期3325e1d5e04f824c6c47fe5536722bf9.png较小的时候, regularizer较大,能够放大梯度 

    • 后期083beceb976c736b52e599da3c10ee0b.png较大的时候,regularizer较小,能够约束梯度 

    • 适合处理稀疏梯度 

    缺点

    由公式可以看出,仍依赖于人工设置一个全局学习率 

    89ca1193da2f1abe3b2c9a67c44d2ddf.png设置过大的话,会使regularizer过于敏感,对梯度的调节太大 

    中后期,分母上梯度平方的累加将会越来越大,使6bc0db511a8fb0e9760407e8e1bdf087.png,使得训练提前结束 

    Adadelta 

    Adadelta是对Adagrad的扩展,最初方案依然是对学习率进行自适应约束,但是进行了计算上的简化。Adagrad会累加之前所有的梯度平方,而Adadelta只累加固定大小的项,并且也不直接存储这些项,仅仅是近似计算对应的平均值。即:  

    a6d376c7b9354695e8e444acd2d390c1.png

    在此处Adadelta其实还是依赖于全局学习率的,但是作者做了一定处理,经过近似牛顿迭代法之后: 

    b9a49d404c41fe4ca1e1790c17841bfe.png

    其中,8a3d93797331a83902ceecc8a57d0e74.png代表求期望。 

    此时,可以看出Adadelta已经不用依赖于全局学习率了。 

    特点

    • 训练初中期,加速效果不错,很快 

    • 训练后期,反复在局部最小值附近抖动 

    RMSprop 

    RMSprop可以算作Adadelta的一个特例:

    12bd384babc7b2292acf515c8691529a.png时,1f3f7eaf2c7deb96d40304a701ec598b.png就变为了求梯度平方和的平均数。 

    如果再求根的话,就变成了RMS(均方根): 

    a153149252d2440c3313995329749f7a.png

    此时,这个RMS就可以作为学习率79d1687368b5a6bdbcd1310684c90927.png的一个约束: 

    dfc113563f0e3b8c26728727bffccd97.png

    特点

    • 其实RMSprop依然依赖于全局学习率 

    • RMSprop算是Adagrad的一种发展,和Adadelta的变体,效果趋于二者之间

    • 适合处理非平稳目标 - 对于RNN效果很好 

    Adam 

    Adam(Adaptive Moment Estimation)本质上是带有动量项的RMSprop,它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。Adam的优点主要在于经过偏置校正后,每一次迭代学习率都有个确定范围,使得参数比较平稳。公式如下: 

    61c78672724128d6031bd36d501669ee.png

    其中,134617b60c77031048898f0bb5590980.pngaeb3d4cc3db0f0e4e3599a2cd25a98f7.png分别是对梯度的一阶矩估计和二阶矩估计,可以看作对期望a3b4673f907280925b1388e5dde74007.png5eccb547ad17b23c133ed39c0d3abed5.png的估计;dd0a2610e0edf62b4d9d3ace94aeecad.png278b18b61819a60be5b61b2def7877c8.png是对 a04cf84c161304993d9fbcbc66bcd9c2.png10aa27a22fbc07de95a45cbd3e602833.png 的校正,这样可以近似为对期望的无偏估计。可以看出,直接对梯度的矩估计对内存没有额外的要求,而且可以根据梯度进行动态调整,而 对学习率形成一个动态约束,而且有明确的范围。

    特点

    • 结合了Adagrad善于处理稀疏梯度和RMSprop善于处理非平稳目标的优点 

    • 对内存需求较小 

    • 为不同的参数计算不同的自适应学习率 

    • 也适用于大多非凸优化 - 适用于大数据集和高维空间 

    Adamax 

    Adamax是Adam的一种变体,此方法对学习率的上限提供了一个更简单的范围。公式上的变化如下: 

    236f275c0745f347e71e476033e3e267.png

    可以看出,Adamax学习率的边界范围更简单

    Nadam 

    Nadam类似于带有Nesterov动量项的Adam。公式如下: 

    d35ce81249ab81301b9c9a420941a8c5.png

    可以看出,Nadam对学习率有了更强的约束,同时对梯度的更新也有更直接的影响。一般而言,在想使用带动量的RMSprop,或者Adam的地方,大多可以使用Nadam取得更好的效果。 

    经验之谈 

    对于稀疏数据,尽量使用学习率可自适应的优化方法,不用手动调节,而且最好采用默认值 SGD通常训练时间更长,但是在好的初始化和学习率调度方案的情况下,结果更可靠 如果在意更快的收敛,并且需要训练较深较复杂的网络时,推荐使用学习率自适应的优化方法。Adadelta,RMSprop,Adam是比较相近的算法,在相似的情况下表现差不多。 在想使用带动量的RMSprop,或者Adam的地方,大多可以使用Nadam取得更好的效果

    最后展示两张可厉害的图,一切尽在图中啊,上面的都没啥用了... ... 

    b67bba346ab6657a7df0f5327170f427.png

    17a3213d04c75ca369fb4f44b61df537.png

     损失平面等高线 

    779b3e75ad884ec9844c3819b72be36d.png

    6c6a090e484fabbaf0a12d94b6d3cfae.png

    在鞍点处的比较

    引用:

    [1]Adagrad(http://www.jmlr.org/papers/volume12/duchi11a/duchi11a.pdf)

    [2]RMSprop[Lecture 6e]

    (http://www.cs.toronto.edu/~tijmen/csc321/lecture_notes.shtml)

    [3]Adadelta(http://arxiv.org/abs/1212.5701)

    [4]Adam(http://arxiv.org/abs/1412.6980v8)

    [5]Nadam(http://cs229.stanford.edu/proj2015/054_report.pdf)

    [6]On the importance of initialization and momentum in deep learning

    (http://www.cs.toronto.edu/~fritz/absps/momentum.pdf)

    [7]Keras中文文档(http://keras-cn.readthedocs.io/en/latest/)

    [8]Alec Radford(https://twitter.com/alecrad)

    [9]An overview of gradient descent optimization algorithms

    (http://sebastianruder.com/optimizing-gradient-descent/)

    [10]Gradient Descent Only Converges to Minimizers

    (http://www.jmlr.org/proceedings/papers/v49/lee16.pdf)

    [11]Deep Learning:Nature

    (http://www.nature.com/nature/journal/v521/n7553/abs/nature14539.html)

    本文仅做学术分享,如有侵权,请联系删文。

    重磅!计算机视觉工坊-学习交流群已成立

    扫码添加小助手微信,可申请加入3D视觉工坊-学术论文写作与投稿 微信交流群,旨在交流顶会、顶刊、SCI、EI等写作与投稿事宜。

    同时也可申请加入我们的细分方向交流群,目前主要有ORB-SLAM系列源码学习、3D视觉CV&深度学习SLAM三维重建点云后处理自动驾驶、CV入门、三维测量、VR/AR、3D人脸识别、医疗影像、缺陷检测、行人重识别、目标跟踪、视觉产品落地、视觉竞赛、车牌识别、硬件选型、深度估计、学术交流、求职交流等微信群,请扫描下面微信号加群,备注:”研究方向+学校/公司+昵称“,例如:”3D视觉 + 上海交大 + 静静“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进去相关微信群。原创投稿也请联系。

    a74ad9658e8287d1511a0c8c2ecf4cfc.png

    ▲长按加微信群或投稿

    0f977d4d71b0b4731d11f09fff09ab94.png

    ▲长按关注公众号

    3D视觉从入门到精通知识星球:针对3D视觉领域的视频课程(三维重建系列三维点云系列结构光系列手眼标定相机标定、激光/视觉SLAM、自动驾驶等)、知识点汇总、入门进阶学习路线、最新paper分享、疑问解答五个方面进行深耕,更有各类大厂的算法工程人员进行技术指导。与此同时,星球将联合知名企业发布3D视觉相关算法开发岗位以及项目对接信息,打造成集技术与就业为一体的铁杆粉丝聚集区,近4000星球成员为创造更好的AI世界共同进步,知识星球入口:

    学习3D视觉核心技术,扫描查看介绍,3天内无条件退款

    417fce5545eb97e7e00516d3377ea62c.png

     圈里有高质量教程资料、可答疑解惑、助你高效解决问题

    觉得有用,麻烦给个赞和在看~

    展开全文
  • 【翻译自 : Gradient Descent Optimization With Nadam From Scratch】 【说明:Jason BrownleePhD大神的文章个人很喜欢,所以闲暇时间里会做一点翻译和学习实践的工作,这里是相应工作的实践记录,希望能帮到有...

            【翻译自 : Gradient Descent Optimization With Nadam From Scratch

            【说明:Jason Brownlee PhD大神的文章个人很喜欢,所以闲暇时间里会做一点翻译和学习实践的工作,这里是相应工作的实践记录,希望能帮到有需要的人!】

              梯度下降是一种优化算法,遵循目标函数的负梯度以定位函数的最小值。

              梯度下降的局限性在于,如果梯度变为平坦或大曲率,搜索的进度可能会减慢。可以将动量添加到梯度下降中,该下降合并了一些惯性以进行更新。可以通过合并预计的新位置而非当前位置的梯度(称为Nesterov的加速梯度(NAG)或Nesterov动量)来进一步改善此效果。

              梯度下降的另一个限制是,所有输入变量都使用单个步长(学习率)。对梯度下降的扩展,如自适应运动估计(Adam)算法,该算法对每个输入变量使用单独的步长,但可能会导致步长迅速减小到非常小的值。Nesterov加速的自适应矩估计或Nadam是Adam算法的扩展,该算法结合了Nesterov动量,可以使优化算法具有更好的性能。

            在本教程中,您将发现如何从头开始使用Nadam进行梯度下降优化。完成本教程后,您将知道:

    梯度下降是一种优化算法,它使用目标函数的梯度来导航搜索空间。
    纳丹(Nadam)是亚当(Adam)版本的梯度下降的扩展,其中包括了内斯特罗夫的动量。
    如何从头开始实现Nadam优化算法并将其应用于目标函数并评估结果。

    教程概述

           本教程分为三个部分: 他们是:

    梯度下降
    Nadam优化算法
    娜达姆(Nadam)的梯度下降
        二维测试问题
        Nadam的梯度下降优化
        可视化的Nadam优化

    梯度下降

             梯度下降是一种优化算法。它在技术上称为一阶优化算法,因为它明确利用了目标目标函数的一阶导数。

            一阶导数,或简称为“导数”,是目标函数在特定点(例如,点)上的变化率或斜率。用于特定输入。

             如果目标函数采用多个输入变量,则将其称为多元函数,并且可以将输入变量视为向量。反过来,多元目标函数的导数也可以视为向量,通常称为梯度。

            梯度:多元目标函数的一阶导数。
            对于特定输入,导数或梯度指向目标函数最陡峭的上升方向。梯度下降是指一种最小化优化算法,该算法遵循目标函数的下坡梯度负值来定位函数的最小值。

           梯度下降算法需要一个正在优化的目标函数和该目标函数的导数函数。目标函数f()返回给定输入集合的分数,导数函数f'()给出给定输入集合的目标函数的导数。梯度下降算法需要问题中的起点(x),例如输入空间中的随机选择点。

          假设我们正在最小化目标函数,然后计算导数并在输入空间中采取一步,这将导致目标函数下坡运动。首先通过计算输入空间中要移动多远的距离来进行下坡运动,计算方法是将步长(称为alpha或学习率)乘以梯度。然后从当前点减去该值,以确保我们逆梯度移动或向下移动目标函数。

    x(t)= x(t-1)–step* f'(x(t))

           在给定点的目标函数越陡峭,梯度的大小越大,反过来,在搜索空间中采取的步伐也越大。使用步长超参数来缩放步长的大小。

           步长:超参数,用于控制算法每次迭代相对于梯度在搜索空间中移动多远。
          如果步长太小,则搜索空间中的移动将很小,并且搜索将花费很长时间。如果步长太大,则搜索可能会在搜索空间附近反弹并跳过最优值。

          现在我们已经熟悉了梯度下降优化算法,接下来让我们看一下Nadam算法。

    Nadam优化算法

          Nesterov加速的自适应动量估计或Nadam算法是对自适应运动估计(Adam)优化算法的扩展,添加了Nesterov的加速梯度(NAG)或Nesterov动量,这是一种改进的动量。更广泛地讲,Nadam算法是对梯度下降优化算法的扩展。Timothy Dozat在2016年的论文“将Nesterov动量整合到Adam中”中描述了该算法。尽管论文的一个版本是在2015年以同名斯坦福项目报告的形式编写的。动量将梯度的指数衰减移动平均值(第一矩)添加到梯度下降算法中。这具有消除嘈杂的目标函数和提高收敛性的影响。Adam是梯度下降的扩展,它增加了梯度的第一和第二矩,并针对正在优化的每个参数自动调整学习率。 NAG是动量的扩展,其中动量的更新是使用对参数的预计更新量而不是实际当前变量值的梯度来执行的。在某些情况下,这样做的效果是在找到最佳位置时减慢了搜索速度,而不是过冲。

           纳丹(Nadam)是对亚当(Adam)的扩展,它使用NAG动量代替经典动量。让我们逐步介绍该算法的每个元素。Nadam使用衰减步长(alpha)和一阶矩(mu)超参数来改善性能。为了简单起见,我们暂时将忽略此方面,并采用恒定值。首先,对于搜索中要优化的每个参数,我们必须保持梯度的第一矩和第二矩,分别称为m和n。在搜索开始时将它们初始化为0.0。

    m = 0
    n = 0
            该算法在从t = 1开始的时间t内迭代执行,并且每次迭代都涉及计算一组新的参数值x,例如。从x(t-1)到x(t)。如果我们专注于更新一个参数,这可能很容易理解该算法,该算法概括为通过矢量运算来更新所有参数。首先,计算当前时间步长的梯度(偏导数)。

    g(t)= f'(x(t-1))

          接下来,使用梯度和超参数“ mu”更新第一时刻。

    m(t)=mu* m(t-1)+(1 –mu)* g(t)

          然后使用“ nu”超参数更新第二时刻。

    n(t)= nu * n(t-1)+(1 – nu)* ​​g(t)^ 2

           接下来,使用Nesterov动量对第一时刻进行偏差校正。

    mhat =(mu * m(t)/(1 – mu))+((1 – mu)* g(t)/(1 – mu))

         然后对第二个时刻进行偏差校正。注意:偏差校正是Adam的一个方面,它与在搜索开始时将第一时刻和第二时刻初始化为零这一事实相反。

    nhat = nu * n(t)/(1 – nu)

               最后,我们可以为该迭代计算参数的值。

    x(t)= x(t-1)– alpha /(sqrt(nhat)+ eps)* mhat

           其中alpha是步长(学习率)超参数,sqrt()是平方根函数,eps(epsilon)是一个较小的值,如1e-8,以避免除以零误差。

          回顾一下,该算法有三个超参数。他们是:

    alpha:初始步长(学习率),典型值为0.002。
    mu:第一时刻的衰减因子(Adam中的beta1),典型值为0.975。
    nu:第二时刻的衰减因子(Adam中的beta2),典型值为0.999。

            就是这样。接下来,让我们看看如何在Python中从头开始实现该算法。

    娜达姆(Nadam)的梯度下降

          在本节中,我们将探索如何使用Nadam动量实现梯度下降优化算法。

    二维测试问题

            首先,让我们定义一个优化函数。我们将使用一个简单的二维函数,该函数将每个维的输入平方,并定义有效输入的范围(从-1.0到1.0)。下面的Objective()函数实现了此功能

    # objective function
    def objective(x, y):
    	return x**2.0 + y**2.0

            我们可以创建数据集的三维图,以了解响应面的曲率。下面列出了绘制目标函数的完整示例。

    # 3d plot of the test function
    from numpy import arange
    from numpy import meshgrid
    from matplotlib import pyplot
    
    # objective function
    def objective(x, y):
    	return x**2.0 + y**2.0
    
    # define range for input
    r_min, r_max = -1.0, 1.0
    # sample input range uniformly at 0.1 increments
    xaxis = arange(r_min, r_max, 0.1)
    yaxis = arange(r_min, r_max, 0.1)
    # create a mesh from the axis
    x, y = meshgrid(xaxis, yaxis)
    # compute targets
    results = objective(x, y)
    # create a surface plot with the jet color scheme
    figure = pyplot.figure()
    axis = figure.gca(projection='3d')
    axis.plot_surface(x, y, results, cmap='jet')
    # show the plot
    pyplot.show()

           运行示例将创建目标函数的三维表面图。我们可以看到全局最小值为f(0,0)= 0的熟悉的碗形状。

           我们还可以创建函数的二维图。 这在以后要绘制搜索进度时会很有帮助。下面的示例创建目标函数的轮廓图。

    # contour plot of the test function
    from numpy import asarray
    from numpy import arange
    from numpy import meshgrid
    from matplotlib import pyplot
    
    # objective function
    def objective(x, y):
    	return x**2.0 + y**2.0
    
    # define range for input
    bounds = asarray([[-1.0, 1.0], [-1.0, 1.0]])
    # sample input range uniformly at 0.1 increments
    xaxis = arange(bounds[0,0], bounds[0,1], 0.1)
    yaxis = arange(bounds[1,0], bounds[1,1], 0.1)
    # create a mesh from the axis
    x, y = meshgrid(xaxis, yaxis)
    # compute targets
    results = objective(x, y)
    # create a filled contour plot with 50 levels and jet color scheme
    pyplot.contourf(x, y, results, levels=50, cmap='jet')
    # show the plot
    pyplot.show()

            运行示例将创建目标函数的二维轮廓图。我们可以看到碗的形状被压缩为以颜色渐变显示的轮廓。 我们将使用该图来绘制在搜索过程中探索的特定点。

            现在我们有了一个测试目标函数,让我们看一下如何实现Nadam优化算法。

    Nadam的梯度下降优化

          我们可以将Nadam的梯度下降应用于测试问题。首先,我们需要一个函数来计算此函数的导数。

          x ^ 2的导数在每个维度上均为x * 2。

    f(x)= x ^ 2
    f'(x)= x * 2

          derived()函数在下面实现了这一点。

    # derivative of objective function
    def derivative(x, y):
    	return asarray([x * 2.0, y * 2.0])

            接下来,我们可以使用Nadam实现梯度下降优化。首先,我们可以选择问题范围内的随机点作为搜索的起点。假定我们有一个数组,该数组定义搜索范围,每个维度一行,并且第一列定义最小值,第二列定义维度的最大值。

    # generate an initial point
    x = bounds[:, 0] + rand(len(bounds)) * (bounds[:, 1] - bounds[:, 0])
    score = objective(x[0], x[1])

           接下来,我们需要初始化力矩矢量。

    # initialize decaying moving averages
    m = [0.0 for _ in range(bounds.shape[0])]
    n = [0.0 for _ in range(bounds.shape[0])]

           然后,我们运行由“ n_iter”超参数定义的算法的固定迭代次数。

    ...
    # run iterations of gradient descent
    for t in range(n_iter):
    	...

           第一步是计算当前参数集的导数。

    ...
    # calculate gradient g(t)
    g = derivative(x[0], x[1])

         接下来,我们需要执行Nadam更新计算。 为了提高可读性,我们将使用命令式编程样式来一次执行一个变量的这些计算。在实践中,我建议使用NumPy向量运算以提高效率。

    ...
    # build a solution one variable at a time
    for i in range(x.shape[0]):
    	...

          首先,我们需要计算力矩矢量。

    # m(t) = mu * m(t-1) + (1 - mu) * g(t)
    m[i] = mu * m[i] + (1.0 - mu) * g[i]

           然后是第二个矩向量。

    # nhat = nu * n(t) / (1 - nu)
    nhat = nu * n[i] / (1.0 - nu)
    # n(t) = nu * n(t-1) + (1 - nu) * g(t)^2
    n[i] = nu * n[i] + (1.0 - nu) * g[i]**2

           然后是经过偏差校正的内斯特罗夫动量。

    # mhat = (mu * m(t) / (1 - mu)) + ((1 - mu) * g(t) / (1 - mu))
    mhat = (mu * m[i] / (1.0 - mu)) + ((1 - mu) * g[i] / (1.0 - mu))

           偏差校正的第二时刻。

    # nhat = nu * n(t) / (1 - nu)
    nhat = nu * n[i] / (1.0 - nu)

          最后更新参数。

    # x(t) = x(t-1) - alpha / (sqrt(nhat) + eps) * mhat
    x[i] = x[i] - alpha / (sqrt(nhat) + eps) * mhat

          然后,针对要优化的每个参数重复此操作。在迭代结束时,我们可以评估新的参数值并报告搜索的性能。

    # evaluate candidate point
    score = objective(x[0], x[1])
    # report progress
    print('>%d f(%s) = %.5f' % (t, x, score))

              我们可以将所有这些结合到一个名为nadam()的函数中,该函数采用目标函数和派生函数的名称以及算法超参数,并返回在搜索及其评估结束时找到的最佳解决方案。

    # gradient descent algorithm with nadam
    def nadam(objective, derivative, bounds, n_iter, alpha, mu, nu, eps=1e-8):
    	# generate an initial point
    	x = bounds[:, 0] + rand(len(bounds)) * (bounds[:, 1] - bounds[:, 0])
    	score = objective(x[0], x[1])
    	# initialize decaying moving averages
    	m = [0.0 for _ in range(bounds.shape[0])]
    	n = [0.0 for _ in range(bounds.shape[0])]
    	# run the gradient descent
    	for t in range(n_iter):
    		# calculate gradient g(t)
    		g = derivative(x[0], x[1])
    		# build a solution one variable at a time
    		for i in range(bounds.shape[0]):
    			# m(t) = mu * m(t-1) + (1 - mu) * g(t)
    			m[i] = mu * m[i] + (1.0 - mu) * g[i]
    			# n(t) = nu * n(t-1) + (1 - nu) * g(t)^2
    			n[i] = nu * n[i] + (1.0 - nu) * g[i]**2
    			# mhat = (mu * m(t) / (1 - mu)) + ((1 - mu) * g(t) / (1 - mu))
    			mhat = (mu * m[i] / (1.0 - mu)) + ((1 - mu) * g[i] / (1.0 - mu))
    			# nhat = nu * n(t) / (1 - nu)
    			nhat = nu * n[i] / (1.0 - nu)
    			# x(t) = x(t-1) - alpha / (sqrt(nhat) + eps) * mhat
    			x[i] = x[i] - alpha / (sqrt(nhat) + eps) * mhat
    		# evaluate candidate point
    		score = objective(x[0], x[1])
    		# report progress
    		print('>%d f(%s) = %.5f' % (t, x, score))
    	return [x, score]

             然后,我们可以定义函数和超参数的界限,并调用函数执行优化。在这种情况下,我们将运行该算法进行50次迭代,初始alpha为0.02,μ为0.8,nu为0.999,这是经过一点点反复试验后发现的。

    # seed the pseudo random number generator
    seed(1)
    # define range for input
    bounds = asarray([[-1.0, 1.0], [-1.0, 1.0]])
    # define the total iterations
    n_iter = 50
    # steps size
    alpha = 0.02
    # factor for average gradient
    mu = 0.8
    # factor for average squared gradient
    nu = 0.999
    # perform the gradient descent search with nadam
    best, score = nadam(objective, derivative, bounds, n_iter, alpha, mu, nu)

             运行结束时,我们将报告找到的最佳解决方案。

    # summarize the result
    print('Done!')
    print('f(%s) = %f' % (best, score))

             综合所有这些,下面列出了适用于我们的测试问题的Nadam梯度下降的完整示例。

    # gradient descent optimization with nadam for a two-dimensional test function
    from math import sqrt
    from numpy import asarray
    from numpy.random import rand
    from numpy.random import seed
    
    # objective function
    def objective(x, y):
    	return x**2.0 + y**2.0
    
    # derivative of objective function
    def derivative(x, y):
    	return asarray([x * 2.0, y * 2.0])
    
    # gradient descent algorithm with nadam
    def nadam(objective, derivative, bounds, n_iter, alpha, mu, nu, eps=1e-8):
    	# generate an initial point
    	x = bounds[:, 0] + rand(len(bounds)) * (bounds[:, 1] - bounds[:, 0])
    	score = objective(x[0], x[1])
    	# initialize decaying moving averages
    	m = [0.0 for _ in range(bounds.shape[0])]
    	n = [0.0 for _ in range(bounds.shape[0])]
    	# run the gradient descent
    	for t in range(n_iter):
    		# calculate gradient g(t)
    		g = derivative(x[0], x[1])
    		# build a solution one variable at a time
    		for i in range(bounds.shape[0]):
    			# m(t) = mu * m(t-1) + (1 - mu) * g(t)
    			m[i] = mu * m[i] + (1.0 - mu) * g[i]
    			# n(t) = nu * n(t-1) + (1 - nu) * g(t)^2
    			n[i] = nu * n[i] + (1.0 - nu) * g[i]**2
    			# mhat = (mu * m(t) / (1 - mu)) + ((1 - mu) * g(t) / (1 - mu))
    			mhat = (mu * m[i] / (1.0 - mu)) + ((1 - mu) * g[i] / (1.0 - mu))
    			# nhat = nu * n(t) / (1 - nu)
    			nhat = nu * n[i] / (1.0 - nu)
    			# x(t) = x(t-1) - alpha / (sqrt(nhat) + eps) * mhat
    			x[i] = x[i] - alpha / (sqrt(nhat) + eps) * mhat
    		# evaluate candidate point
    		score = objective(x[0], x[1])
    		# report progress
    		print('>%d f(%s) = %.5f' % (t, x, score))
    	return [x, score]
    
    # seed the pseudo random number generator
    seed(1)
    # define range for input
    bounds = asarray([[-1.0, 1.0], [-1.0, 1.0]])
    # define the total iterations
    n_iter = 50
    # steps size
    alpha = 0.02
    # factor for average gradient
    mu = 0.8
    # factor for average squared gradient
    nu = 0.999
    # perform the gradient descent search with nadam
    best, score = nadam(objective, derivative, bounds, n_iter, alpha, mu, nu)
    print('Done!')
    print('f(%s) = %f' % (best, score))

             运行示例将优化算法和Nadam应用于我们的测试问题,并报告算法每次迭代的搜索性能。

            注意:由于算法或评估程序的随机性,或者数值精度的差异,您的结果可能会有所不同。 考虑运行该示例几次并比较平均结果。

            在这种情况下,我们可以看到在大约44次搜索迭代后找到了接近最佳的解决方案,输入值接近0.0和0.0,评估为0.0。

    >40 f([ 5.07445337e-05 -3.32910019e-03]) = 0.00001
    >41 f([-1.84325171e-05 -3.00939427e-03]) = 0.00001
    >42 f([-6.78814472e-05 -2.69839367e-03]) = 0.00001
    >43 f([-9.88339249e-05 -2.40042096e-03]) = 0.00001
    >44 f([-0.00011368 -0.00211861]) = 0.00000
    >45 f([-0.00011547 -0.00185511]) = 0.00000
    >46 f([-0.0001075 -0.00161122]) = 0.00000
    >47 f([-9.29922627e-05 -1.38760991e-03]) = 0.00000
    >48 f([-7.48258406e-05 -1.18436586e-03]) = 0.00000
    >49 f([-5.54299505e-05 -1.00116899e-03]) = 0.00000
    Done!
    f([-5.54299505e-05 -1.00116899e-03]) = 0.000001

    可视化的Nadam优化

           我们可以在域的等高线上绘制Nadam搜索的进度。这可以为算法迭代过程中的搜索进度提供直观的认识。我们必须更新nadam()函数以维护在搜索过程中找到的所有解决方案的列表,然后在搜索结束时返回此列表。下面列出了具有这些更改的功能的更新版本。

    # gradient descent algorithm with nadam
    def nadam(objective, derivative, bounds, n_iter, alpha, mu, nu, eps=1e-8):
    	solutions = list()
    	# generate an initial point
    	x = bounds[:, 0] + rand(len(bounds)) * (bounds[:, 1] - bounds[:, 0])
    	score = objective(x[0], x[1])
    	# initialize decaying moving averages
    	m = [0.0 for _ in range(bounds.shape[0])]
    	n = [0.0 for _ in range(bounds.shape[0])]
    	# run the gradient descent
    	for t in range(n_iter):
    		# calculate gradient g(t)
    		g = derivative(x[0], x[1])
    		# build a solution one variable at a time
    		for i in range(bounds.shape[0]):
    			# m(t) = mu * m(t-1) + (1 - mu) * g(t)
    			m[i] = mu * m[i] + (1.0 - mu) * g[i]
    			# n(t) = nu * n(t-1) + (1 - nu) * g(t)^2
    			n[i] = nu * n[i] + (1.0 - nu) * g[i]**2
    			# mhat = (mu * m(t) / (1 - mu)) + ((1 - mu) * g(t) / (1 - mu))
    			mhat = (mu * m[i] / (1.0 - mu)) + ((1 - mu) * g[i] / (1.0 - mu))
    			# nhat = nu * n(t) / (1 - nu)
    			nhat = nu * n[i] / (1.0 - nu)
    			# x(t) = x(t-1) - alpha / (sqrt(nhat) + eps) * mhat
    			x[i] = x[i] - alpha / (sqrt(nhat) + eps) * mhat
    		# evaluate candidate point
    		score = objective(x[0], x[1])
    		# store solution
    		solutions.append(x.copy())
    		# report progress
    		print('>%d f(%s) = %.5f' % (t, x, score))
    	return solutions

             然后,我们可以像以前一样执行搜索,这一次将检索解决方案列表,而不是最佳的最终解决方案。

    # seed the pseudo random number generator
    seed(1)
    # define range for input
    bounds = asarray([[-1.0, 1.0], [-1.0, 1.0]])
    # define the total iterations
    n_iter = 50
    # steps size
    alpha = 0.02
    # factor for average gradient
    mu = 0.8
    # factor for average squared gradient
    nu = 0.999
    # perform the gradient descent search with nadam
    solutions = nadam(objective, derivative, bounds, n_iter, alpha, mu, nu)

           然后,我们可以像以前一样创建目标函数的轮廓图。

    # sample input range uniformly at 0.1 increments
    xaxis = arange(bounds[0,0], bounds[0,1], 0.1)
    yaxis = arange(bounds[1,0], bounds[1,1], 0.1)
    # create a mesh from the axis
    x, y = meshgrid(xaxis, yaxis)
    # compute targets
    results = objective(x, y)
    # create a filled contour plot with 50 levels and jet color scheme
    pyplot.contourf(x, y, results, levels=50, cmap='jet')

           最后,我们可以将在搜索过程中找到的每个解决方案绘制成一条由一条线连接的白点。

    # plot the sample as black circles
    solutions = asarray(solutions)
    pyplot.plot(solutions[:, 0], solutions[:, 1], '.-', color='w')

            综上所述,下面列出了对测试问题执行Nadam优化并将结果绘制在轮廓图上的完整示例。

    # example of plotting the nadam search on a contour plot of the test function
    from math import sqrt
    from numpy import asarray
    from numpy import arange
    from numpy import product
    from numpy.random import rand
    from numpy.random import seed
    from numpy import meshgrid
    from matplotlib import pyplot
    from mpl_toolkits.mplot3d import Axes3D
    
    # objective function
    def objective(x, y):
    	return x**2.0 + y**2.0
    
    # derivative of objective function
    def derivative(x, y):
    	return asarray([x * 2.0, y * 2.0])
    
    # gradient descent algorithm with nadam
    def nadam(objective, derivative, bounds, n_iter, alpha, mu, nu, eps=1e-8):
    	solutions = list()
    	# generate an initial point
    	x = bounds[:, 0] + rand(len(bounds)) * (bounds[:, 1] - bounds[:, 0])
    	score = objective(x[0], x[1])
    	# initialize decaying moving averages
    	m = [0.0 for _ in range(bounds.shape[0])]
    	n = [0.0 for _ in range(bounds.shape[0])]
    	# run the gradient descent
    	for t in range(n_iter):
    		# calculate gradient g(t)
    		g = derivative(x[0], x[1])
    		# build a solution one variable at a time
    		for i in range(bounds.shape[0]):
    			# m(t) = mu * m(t-1) + (1 - mu) * g(t)
    			m[i] = mu * m[i] + (1.0 - mu) * g[i]
    			# n(t) = nu * n(t-1) + (1 - nu) * g(t)^2
    			n[i] = nu * n[i] + (1.0 - nu) * g[i]**2
    			# mhat = (mu * m(t) / (1 - mu)) + ((1 - mu) * g(t) / (1 - mu))
    			mhat = (mu * m[i] / (1.0 - mu)) + ((1 - mu) * g[i] / (1.0 - mu))
    			# nhat = nu * n(t) / (1 - nu)
    			nhat = nu * n[i] / (1.0 - nu)
    			# x(t) = x(t-1) - alpha / (sqrt(nhat) + eps) * mhat
    			x[i] = x[i] - alpha / (sqrt(nhat) + eps) * mhat
    		# evaluate candidate point
    		score = objective(x[0], x[1])
    		# store solution
    		solutions.append(x.copy())
    		# report progress
    		print('>%d f(%s) = %.5f' % (t, x, score))
    	return solutions
    
    # seed the pseudo random number generator
    seed(1)
    # define range for input
    bounds = asarray([[-1.0, 1.0], [-1.0, 1.0]])
    # define the total iterations
    n_iter = 50
    # steps size
    alpha = 0.02
    # factor for average gradient
    mu = 0.8
    # factor for average squared gradient
    nu = 0.999
    # perform the gradient descent search with nadam
    solutions = nadam(objective, derivative, bounds, n_iter, alpha, mu, nu)
    # sample input range uniformly at 0.1 increments
    xaxis = arange(bounds[0,0], bounds[0,1], 0.1)
    yaxis = arange(bounds[1,0], bounds[1,1], 0.1)
    # create a mesh from the axis
    x, y = meshgrid(xaxis, yaxis)
    # compute targets
    results = objective(x, y)
    # create a filled contour plot with 50 levels and jet color scheme
    pyplot.contourf(x, y, results, levels=50, cmap='jet')
    # plot the sample as black circles
    solutions = asarray(solutions)
    pyplot.plot(solutions[:, 0], solutions[:, 1], '.-', color='w')
    # show the plot
    pyplot.show()

          运行示例将像以前一样执行搜索,但是在这种情况下,将创建目标函数的轮廓图。

          在这种情况下,我们可以看到在搜索过程中找到的每个解决方案都显示一个白点,从最优点开始,逐渐靠近图中心的最优点。

     

    展开全文
  • 首先,Adam优化器的权重更新公式也可以写成: Nadam使用Nesterov通过将上式中的 m t − 1 ^ \hat{m_{t-1}} mt−1​^​ 替换为当前的 m t ^ \hat{m_t} mt​^​ 来提前更新梯度: 其中, m m m 和 v v v 初始化为 0 0...
  • 教程概述 本教程分为三个部分:他们是: 梯度下降 Nadam优化算法 娜达姆(Nadam)的梯度下降 二维测试问题 Nadam的梯度下降优化 可视化的Nadam优化 梯度下降 梯度下降是一种优化算法。它在技术上称为一阶优化算法,...
  • 一般而言,在想使用带动量的RMSprop,或者Adam的地方,大多可以使用Nadam取得更好的效果。    经验之谈    对于稀疏数据,尽量使用学习率可自适应的优化方法,不用手动调节,而且最好采用默认值 SGD...
  • Nadam 最后是Nadam。我们说Adam是集大成者,但它居然遗漏了Nesterov,这还能忍?必须给它加上,按照NAG的步骤1: 就是Nesterov + Adam = Nadam了。 说到这里,大概可以理解为什么j经常有人说 Adam / Nadam 目前最...
  • 以下来自: ...1.5.1.1.AdaGrad(自适应学习率算法) 1.5.1.2.AdaDelta 1.5.1.3.RmsProp 1.5.1.4.Adam 1.5.1.5.AdaMax 1.5.1.6.Nadam 1.5.1.7.AMSGrad 1.5.1.8.Nesterovs(动量的随机梯度下降法) 1.5.1.9
  • 深度学习中的优化方法(SGD,Adagrad,Adadelta,Adam,Adamax,Nadam, Radam) SGD,Adagrad,Adadelta,Adam,Adamax,Nadam: https://zhuanlan.zhihu.com/p/22252270 提供了不需要可调参数的动态warmup的Radam: ...
  • 一、准备知识 指数加权平均 指数加权平均值又称指数加权移动平均值,局部平均值,移动平均值。加权平均这个概念都很熟悉,即根据各个元素所占权重计算平均值。指数加权平均中的指数表示各个元素所占权重呈指数分布。...
  • Nadam 这样的发展历程。优化器其实就是采用何种方式对损失函数进行迭代优化,也就是有一个卷积参数我们初始化了,之后loss还很大,我们让这个参数根据loss的梯度如何变,每次变多少可以让loss函数在凸曲面上不断变...
  • 目录 优化算法通用框架 SGD 系列:固定学习率的优化算法 SGD SGD (with Momentum) = SGD-M SGD(with Nesterov Acceleration)= NAG ...Adam / Nadam Adam Nadam Adam 两宗罪 1. 可能不收敛 2.可能...
  • 深度学习最全优化方法总结比较(SGD,Adagrad,Adadelta,Adam,Adamax,Nadam) ycszen Semantic Segmentation / changqianyu.me 1,652 人赞同了该文章 前言 (标题不...
  • 深度学习优化算法经历了 SGD -> SGDM -> NAG ->AdaGrad -> AdaDelta -> Adam -> Nadam 这样的发展历程。Google一下就可以看到很多的教程文章,详细告诉你这些算法是如何一步一步演变而来的。在这里,我们换一个思路...
  • Nadam(Nesterov-accelerated Adaptive Moment Estimation),Nesterov加速的自适应矩估计,将adam和NAG结合起来,为了将NAG添加到Adam,我们需要对动量部分进行一些改变。作者将NAG梯度更新公式变为:   也就是...
  • 一般而言,在想使用带动量的RMSprop,或者Adam的地方,大多可以使用Nadam取得更好的效果。 经验之谈 对于稀疏数据,尽量使用学习率可自适应的优化方法,不用手动调节,而且最好采用默认值 SGD通常训练时间更长,...
  • nadam优化器

    千次阅读 2020-08-26 19:38:19
    https://blog.csdn.net/qq_42109740/article/details/105401197
  • 本文仅对一些常见的优化方法进行直观介绍和简单的比较,主要是一阶的梯度法,包括SGD, Momentum, Nesterov Momentum, AdaGrad, RMSProp, Adam。 其中SGD,Momentum,Nesterov Momentum是手动指定学习速率的,而后面的...
  • 参考博客: ... ... ...标记成原创是因为加入了很多整理,内容并非原创,写在前面,希望后人不要误解,一切解释归参考博客中的博文所有 ...当然,实际情况下的loss损失函数可能更为复杂,比如鞍面,这样我们使用...10-NAdam
  • 一般而言,在想使用带动量的RMSprop,或者Adam的地方,大多可以使用Nadam取得更好的效果。 经验之谈 对于稀疏数据,尽量使用学习率可自适应的优化方法,不用手动调节,而且最好采用默认值 SGD通常训练时间更长,容易...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,398
精华内容 559
关键字:

nadam

友情链接: 随机森林1.rar