CS231n Lectue7

本文深入探讨了深度学习优化策略,包括SGD、Momentum、Nesterov Momentum、RMSprop、Adam等优化算法,以及Learning Rate调整策略。此外,还讨论了Second-Order Optimization、Dropout、Data Augmentation和Regularization等技术,旨在帮助读者理解如何提升模型性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


首先在复习前边知识的部分,提出Data Preprocessing之后的数据对于weights的改变更有鲁棒性,也更容易进行优化。在超参数调试时,通常可以先选择两三个超参数进行调试(也可以选择优先级高的超参数进行调试),若一起调试,在指数级的超参数空间上很难遍历。

Optimization

while True:
    weights_grad = evaluate_gradient(loss_fun, data, weights)
    weights += -step_size * weights_grad

使用SGD时出现的问题

提出了一个概念condition number:Hession矩阵中最大值与最小值的比值,如果condition number很大,那么在优化过程中会出现一个方向上优化很快,另一个方向优化很慢,更新的方向会出现Zigzag的路径。

优化过程中出现局部最优点和鞍点,这两种情况均会使gradient变为0,参数更新停止,在高维空间中,鞍点的出现更为频繁。

SGD的梯度来自于mini batches,所以更新路线会很曲折(由于存在噪声)。

解决方案

SGD+ Momentum

initialize    v t = 0 \text{initialize}\;v_t = 0 initializevt=0
v t + 1 = ρ v t + ▽ f ( x t ) v_{t+1} = \rho v_t + \triangledown f(x_t) vt+1=ρvt+f(xt)
x t + 1 = x t − α v t + 1 x_{t+1} = x_t - \alpha v_{t+1} xt+1=xtαvt+1
该方法的直观理解是在更新过程引入速度(velocity)的概念, ρ \rho ρ 理解为在速度更新的基础上引入了摩擦力(friction)。
在更新时引入了之前的速度,那么变化快的方向的值会相互抵消,减少了向敏感处前进的数量,相反在不那么敏感的方向上更新速度会加快;在更新过程中其实对noisy做了一个平均,更新过程中可以向更smooth的方向移动。

Nesterov Momentum

v t + 1 = ρ v t − α ▽ f ( x ~ t ) v_{t+1} = \rho v_t - \alpha \triangledown f(\tilde{x}_t) vt+1=ρvtαf(x~t)
x ~ t + 1 = x ~ t + v t + 1 + ρ ( v t + 1 − v t ) \tilde{x}_{t+1} = \tilde{x}_t +v_{t+1} + \rho(v_{t+1} - v_t) x~t+1=x~t+vt+1+ρ(vt+1vt)

dx = compute_gradient(x)
old_v = v
v = rho * v - learning_rate * dx
x += -rho * old_v + (1 + rho) * v

RMSprop

AdaGrad

grad_squared = 0
while True:
    dx = compute_gradient(x)
    grad_squared += dx * dx
    x -= learning_rate * dx / (np.sqrt(grad_sqared) + 1e-7)

该方法主要是为了处理condition number很大的情况,这样处理之后,对于 slow direction,值会在一定程度上变大;对于quick direction,值会在一定程度上变小。这种方法缺点也很明显,当迭代次数增大时,grad_suqred的值会变的很大,更新权重会越来越小,而且该方法对于局部最优点和鞍点依然无法解决。
对该方法进行改进就提出了RMSProp

grad_squared = 0
while True:
    dx = compute_gradient(x)
    grad_squared = decay_rate * grad_squared + (1 - decay_rate) * dx * dx # 削弱了平方项的权重
    x -= learning_rate * dx / (np.sqrt(grad_sqared) + 1e-7)

Adam

first_moment = 0
second_moment = 0
for t in range(1, num_iterations):
    dx = compute_gradient(x)
    first_moment = beta1 * first_moment + (1-beta1) * dx# Momentum
    second_moment = beta2 * second_moment + (1 - beta2) * dx * dx# RMSProp
    first_unbias = first_moment / (1 - beta1 ** t)# Bias correction
    second_unbias = second_moment / (1 - beta2 ** t)# Bias correction
    x -= learning_rate * first_unbias / (np.sqrt(second_unbias ) + 1e-7) #RMSProp

通常Adam的超参设置为beta1 = 0.9 beta2 = 0.999 learning_rate = 1e-3或5e-4
在这里插入图片描述

Learning rate的更新策略

exponential decay:
α = α 0 e − k t \alpha = \alpha_0 e^{-kt} α=α0ekt
1/t decay:
α = α 0 / ( 1 + k t ) \alpha = \alpha_0/(1+kt) α=α0/(1+kt)
learning rate的更新策略:使用不同的learning rate绘制loss的下降曲线,再根据曲线,判断使用 learning rate decay的位置。
在这里插入图片描述

Second-Order Optimization

根据泰勒展开式:
J ( θ ) ≈ J ( θ 0 ) + ( θ − θ 0 ) T ▽ θ J ( θ 0 ) + 1 2 ( θ − θ 0 ) T H ( θ − θ 0 ) J(\theta) \approx J(\theta_0) + (\theta - \theta_0)^T\triangledown_{\theta}J(\theta_0) + \frac{1}{2} (\theta -\theta_0)^TH(\theta -\theta_0) J(θ)J(θ0)+(θθ0)TθJ(θ0)+21(θθ0)TH(θθ0)
求解之后可得
θ ∗ = θ 0 − H − 1 ▽ θ J ( θ 0 ) \theta ^* = \theta_0 - H^{-1}\triangledown_{\theta} J(\theta_0) θ=θ0H1θJ(θ0)
好处:
不需要learning rate或者其他的超参数
缺点:
Hession矩阵的存储需要 O ( N 2 ) O(N^2) O(N2),转换需要 O ( N 3 ) O(N^3) O(N3)
改善方法:

  1. BFGS:不是直接对Hession矩阵取逆,而是对Hession矩阵的你矩阵进行估计,复杂度为 O ( N 2 ) O(N^2) O(N2)
  2. L-BFGS: 不需要对Hession矩阵进行存储,该方法对于将输入全部输入(full-batch)的情况很有效,但是没有很好的办法应用到mini-batch情况下。

在实际情况中,我们通常使用Adam,如果可以将数据集全部输入也可以使用L-BFGS
对于训练集的误差与测试集的误差差距很大的情况,我们可以采取几种方法来提高学习的准确率:
3. 我们可以训练多个网络,通过对网络的结果取平均来提高准确率,通常可以提高2%的准确率。
4. 在一次训练过程中截取某一时刻的训练结果,在测试阶段使用这些不同时刻训练结果进行输出,最后将输出整合。在训练时我们可以使用小的学习速率和大的学习速率交叉使用的方法,会使snapshot的结果表现性能更好。
5. 在更新参数时对结果进行平滑衰减,即

while True:
    data_batch = dataset.sample_data_batch()
    loss = network.forward(data_batch)
    dx = network.backward()
    x += -learning_rate  *  dx
    x_test = 0.995 * x_test + 0.005 * x

Drop out

通常使用在全连接层后边,如果用在卷积层后边,那么随机选择一些channel上的卷积核参数归0。

在这里插入图片描述
Dropout有作用的原因:

  1. 强迫网络减小对某些特定参数的依赖,避免特征之间的相互适应
  2. dropout可以理解为是多个网络模型的整合(每次训练一种状态的链接可以认为是一个模型)

在测试阶段,我们将神经元激活之后的值乘以dropout的概率作为当前神经元的输出,这样做是为了使测试时的输出为训练时输出的期望。

H1 = np.maximum(0, np.dot(W1, X) + b1) * p
H2 = np.maximum(0, np.dot(W2, H1) + b2) * p
out = np.doy(W3, H2) + b3

更一般的情况在训练时我们将选择出的神经元的激活值增大

def train_step(X):
     H1 = np.maximum(0, np.dot(W1, X) + b1)
     U1 = (np.random.rand(*H1.shape) < p) /p
     H1 *= U1
     H2 = np.maximum(0, np.dot(W2, H1) + b2)
     U2 = (np.random.rand(*H2.shape) < p) /p
     H2 *= U2
     out = np.doy(W3, H2) + b3

def predict(X):
    H1 = np.maximum(0, np.dot(W1, X) + b1) * p
    H2 = np.maximum(0, np.dot(W2, H1) + b2) * p
    out = np.doy(W3, H2) + b3

Regularization的一般形式:在训练时加入一种随机值,在测试时取随机值的平均。一种例子为Batch normalization,训练时选择随机的batch,测试时则选择固定的参数取normalization。

Data Augmentation

在这里插入图片描述

Regularization 的一些方法

  1. L2 Regularization: R ( W ) = ∑ k ∑ l W k , l 2 R(W) = \sum_k\sum_lW^2_{k,l} R(W)=klWk,l2
  2. L1 Regularization: R ( W ) = ∑ k ∑ l ∣ W k , l ∣ R(W) = \sum_k\sum_l|W_{k,l}| R(W)=klWk,l
  3. Elastic net(L1 + L2): R ( W ) = ∑ k ∑ l β W k , l 2 + ∣ W k , l ∣ R(W) = \sum_k\sum_l \beta W^2_{k,l} + |W_{k,l}| R(W)=klβWk,l2+Wk,l
  4. Drop out
  5. Batch Normalization
  6. Data Augmentation
  7. Drop connection
    在这里插入图片描述
  8. Fractional Max Pooling
    在这里插入图片描述
    随机取 2 \sqrt{2} 2 附近的值,在测试时取一些固定pooling的结果平均或者测试很多样本取平均
  9. 随机深度,跳过其中的某一些层

Transfer Learning

很有效的方法
将非常大训练集的训练的网络参数 转换到自己的网络中
TensorFlow:https://github.com/tensorflow/models
Pytorch:https://github.com/pytorch/vision
最近有一篇论证预训练有效性的论文:https://mp.weixin.qq.com/s/qBK_-xO2BH7U8abl8I7dOQ

基于数据挖掘的音乐推荐系统设计与实现 需要一个代码说明,不需要论文 采用python语言,django框架,mysql数据库开发 编程环境:pycharm,mysql8.0 系统分为前台+后台模式开发 网站前台: 用户注册, 登录 搜索音乐,音乐欣赏(可以在线进行播放) 用户登陆时选择相关感兴趣的音乐风格 音乐收藏 音乐推荐算法:(重点) 本课题需要大量用户行为(如播放记录、收藏列表)、音乐特征(如音频特征、歌曲元数据)等数据 (1)根据用户之间相似性或关联性,给一个用户推荐与其相似或有关联的其他用户所感兴趣的音乐; (2)根据音乐之间的相似性或关联性,给一个用户推荐与其感兴趣的音乐相似或有关联的其他音乐。 基于用户的推荐和基于物品的推荐 其中基于用户的推荐是基于用户的相似度找出相似相似用户,然后向目标用户推荐其相似用户喜欢的东西(和你类似的人也喜欢**东西); 而基于物品的推荐是基于物品的相似度找出相似的物品做推荐(喜欢该音乐的人还喜欢了**音乐); 管理员 管理员信息管理 注册用户管理,审核 音乐爬虫(爬虫方式爬取网站音乐数据) 音乐信息管理(上传歌曲MP3,以便前台播放) 音乐收藏管理 用户 用户资料修改 我的音乐收藏 完整前后端源码,部署后可正常运行! 环境说明 开发语言:python后端 python版本:3.7 数据库:mysql 5.7+ 数据库工具:Navicat11+ 开发软件:pycharm
MPU6050是一款广泛应用在无人机、机器人和运动设备中的六轴姿态传感器,它集成了三轴陀螺仪和三轴加速度计。这款传感器能够实时监测并提供设备的角速度和线性加速度数据,对于理解物体的动态运动状态至关重要。在Arduino平台上,通过特定的库文件可以方便地与MPU6050进行通信,获取并解析传感器数据。 `MPU6050.cpp`和`MPU6050.h`是Arduino库的关键组成部分。`MPU6050.h`是头文件,包含了定义传感器接口和函数声明。它定义了类`MPU6050`,该类包含了初始化传感器、读取数据等方法。例如,`begin()`函数用于设置传感器的工作模式和I2C地址,`getAcceleration()`和`getGyroscope()`则分别用于获取加速度和角速度数据。 在Arduino项目中,首先需要包含`MPU6050.h`头文件,然后创建`MPU6050`对象,并调用`begin()`函数初始化传感器。之后,可以通过循环调用`getAcceleration()`和`getGyroscope()`来不断更新传感器读数。为了处理这些原始数据,通常还需要进行校准和滤波,以消除噪声和漂移。 I2C通信协议是MPU6050与Arduino交互的基础,它是一种低引脚数的串行通信协议,允许多个设备共享一对数据线。Arduino板上的Wire库提供了I2C通信的底层支持,使得用户无需深入了解通信细节,就能方便地与MPU6050交互。 MPU6050传感器的数据包括加速度(X、Y、Z轴)和角速度(同样为X、Y、Z轴)。加速度数据可以用来计算物体的静态位置和动态运动,而角速度数据则能反映物体转动的速度。结合这两个数据,可以进一步计算出物体的姿态(如角度和角速度变化)。 在嵌入式开发领域,特别是使用STM32微控制器时,也可以找到类似的库来驱动MPU6050。STM32通常具有更强大的处理能力和更多的GPIO口,可以实现更复杂的控制算法。然而,基本的传感器操作流程和数据处理原理与Arduino平台相似。 在实际应用中,除了基本的传感器读取,还可能涉及到温度补偿、低功耗模式设置、DMP(数字运动处理器)功能的利用等高级特性。DMP可以帮助处理传感器数据,实现更高级的运动估计,减轻主控制器的计算负担。 MPU6050是一个强大的六轴传感器,广泛应用于各种需要实时运动追踪的项目中。通过 Arduino 或 STM32 的库文件,开发者可以轻松地与传感器交互,获取并处理数据,实现各种创新应用。博客和其他开源资源是学习和解决问题的重要途径,通过这些资源,开发者可以获得关于MPU6050的详细信息和实践指南
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值