IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 深度学习中的优化算法之带Momentum的SGD -> 正文阅读

[人工智能]深度学习中的优化算法之带Momentum的SGD

? ? ? 之前在https://blog.csdn.net/fengbingchun/article/details/123955067介绍过SGD(Mini-Batch Gradient Descent(MBGD),有时提到SGD的时候,其实指的是MBGD)。这里介绍下带动量(Momentum)的SGD。

? ? ? SGD(Stochastic Gradient Descent)难以导航沟壑(SGD has trouble navigating ravines),即SGD在遇到沟壑时容易陷入震荡。

? ? ? Momentum是一种有助于在相关方向上加速SGD收敛(加速学习)并抑制振荡的方法。Momentum具有抑制梯度变化的效果,进而抑制搜索空间中每个新点的步长。如下图所示,截图来自:https://arxiv.org/pdf/1609.04747.pdf

? ? ?

?? ? ? Momentum是梯度下降优化算法的扩展,通常称为带动量的梯度下降。它旨在加速优化过程,例如减少达到最优值所需的函数评估次数,或提高优化算法的能力,例如从而获得更好的最终结果(It is designed to accelerate the optimization process, e.g. decrease the number of function evaluations required to reach the optima, or to improve the capability of the optimization algorithm, e.g. result in a better final result)。

? ? ? Momentum涉及添加一个额外的超参数mu,该参数控制梯度下降更新方程中的历史量(动量)。超参数mu的值定义在0.0到1.0的范围内,并且通常具有接近1.0的值,例如0.8、0.9或0.99。0.0的动量与没有动量的梯度下降相同。较大的mu(如0.9)将意味着更新受到先前更新的影响较大,而较小的mu(如0.2)将意味着影响较小。

? ? ? Momentum在目标函数具有大曲率(例如变化很大)的优化问题中最有用,这意味着梯度可能在搜索空间的相对较小区域内发生很大变化(Momentum is most useful in optimization problems where the objective function has a large amount of curvature (e.g. changes a lot), meaning that the gradient may change a lot over relatively small regions of the search space)。当搜索空间平坦或接近平坦时,动量很有帮助,例如零梯度。动量允许搜索与平坦点之前相同的方法进行,并有助于穿过平坦区域。

? ? ? 加入动量的SGD,其参数更新方向不仅由当前的梯度决定,也与此前累积的梯度下降方向有关。若当前的梯度方向与累积的历史梯度方向一致,则当前的梯度会被加强,从而这一步下降的幅度更大。若当前的梯度方向与累积的梯度方向不一致,则会减弱当前下降的梯度幅度。由此产生了加速收敛和减少震荡的效果。

? ? ? 以上内容主要参考:

? ? ? 1. https://machinelearningmastery.com/gradient-descent-with-momentum-from-scratch/

? ? ? 2. 7.4. 动量法 — 《动手学深度学习》 文档

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

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

enum class Optimization {
	BGD, // Batch Gradient Descent
	SGD, // Stochastic Gradient Descent
	MBGD, // Mini-batch Gradient Descent
	SGD_Momentum // SGD with momentum
};

? ? ? 2. 在原有LogisticRegression2类的基础上新增set_mu,用于设置动量项超参数mu:

void set_mu(float mu) { mu_ = mu; }

? ? ? 3. 为了每次运行与SGD产生的随机初始化权值相同,这里使用std::default_random_engine:

template<typename T>
void generator_real_random_number(T* data, int length, T a, T b, bool default_random)
{
	// 每次产生固定的不同的值
    std::default_random_engine generator;

    std::uniform_real_distribution<T> distribution(a, b);
    for (int i = 0; i < length; ++i)
        data[i] = distribution(generator);
}

? ? ? 4. 为了对数据集每次执行shuffle时,结果一致,这里有std::random_shuffle调整为std::shuffle:

//std::srand(unsigned(std::time(0)));
//std::random_shuffle(random_shuffle_.begin(), random_shuffle_.end(), generate_random); // 每次执行后random_shuffle_结果不同
std::default_random_engine generator;
std::shuffle(random_shuffle_.begin(), random_shuffle_.end(), generator); // 每次执行后random_shuffle_结果相同

? ? ? 5.?calculate_gradient_descent函数:

void LogisticRegression2::calculate_gradient_descent(int start, int end)
{
	switch (optim_) {
		case Optimization::SGD_Momentum: {
			int len = end - start;
			std::vector<float> change(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 new_change = mu_ * change[j] - alpha_ * (data_->samples[random_shuffle_[i]][j] * dz[x]);
					w_[j] += new_change;
					change[j] = new_change;
				}

				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) {
					w_[j] = w_[j] - alpha_ * (data_->samples[random_shuffle_[i]][j] * dz[x]);
				}

				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,多次执行每种配置,最终结果都相同。SGD耗时7秒,识别率为99.94%;mu值不同,带动量的SGD的耗时和识别率也不同,当mu为0.7时,耗时最少为3秒,识别率为99.89%,识别率比SGD略低;当mu为0.5时,耗时4秒,识别率与SGD相同。

? ? ? ?GitHubhttps://github.com/fengbingchun/NN_Test

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-05-09 12:39:40  更:2022-05-09 12:42:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:28:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码