返回介绍

Caffe 中的 SGD 的变种优化算法(2)

发布于 2025-02-25 23:04:59 字数 4408 浏览 0 评论 0 收藏 0

接上回,我们继续来看优化的算法。

Adam

关于 adam 的算法,我觉得它的复杂程度比前面的算法更高,但是它还是主要使用了和计算动量相同的方法,并把这种方法应用到梯度的一阶总量和二阶总量上:

m_{t+1} = \beta_1 * m_t+(1-\beta_1)*g
v_{t+1}=\beta_2*v_t+(1-\beta_2)*g^2

同时作者发现这两个变量存在某种偏差,于是又给这两个变量加上了一定的修正量:

\hat{m_t}=\frac{m_t}{1-\beta_1^t}
\hat{v_t}=\frac{v_t}{1 - \beta_2^t}

最后我们将这两个变量融合起来得到最终的更新公式:

x_{t+1}= x_t - lr*\frac{\hat{m_t}}{\sqrt{\hat{v_t}} + \varepsilon }*g_t

它的代码如下所示:

def adam(x_start, step, g, beta1 = 0.9, beta2 = 0.999,delta=1e-8):
    x = np.array(x_start, dtype='float64')
    sum_m = np.zeros_like(x)
    sum_v = np.zeros_like(x)
    passing_dot = [x.copy()]
    for i in range(50):
        grad = g(x)
        sum_m = beta1 * sum_m + (1 - beta1) * grad
        sum_v = beta2 * sum_v + (1 - beta2) * grad * grad
        correction = np.sqrt(1 - beta2 ** i) / (1 - beta1 ** i)
        x -= step * sum_m / (np.sqrt(sum_v + delta))
        passing_dot.append(x.copy())
        if abs(sum(grad)) < 1e-6:
            break;
    return x, passing_dot

前面也说过,实际上这些算法背后都有些原理的,但是这些原理在我们看来可能都比较抽象,所以再我们看完实验再看原理可能会更有感觉。下面我们看看它的表现:

res, x_arr = adam([5, 5], 0.1, g)
contour(X,Y,Z, x_arr)

好吧,这一回它是唯一一个走得有点过头的算法,不过最后还是走上了正道。

这样除了 Nesterov 算法之外,我们把其他所有的算法都展示出来了。前面这个实验中,我们希望检验算法的“拐弯”能力。也就是说一开始算法冲着一个局部最优点而来,什么时候它会发现这是个骗局并掉头朝向真正的最优值呢?现在每一个算法都给我们交出了答案。仔细看来每个算法的表示还是不太一样的。有的算法比较灵敏,刚发现不对就调头逃跑,有的算法则是冲过了头才转过身来。有的算法做到这一切十分容易,并不需要很大的 Learning rate,有的算法则需要强大的力量才能转过来,否则就会行动缓慢。

好了,各位童鞋,转弯赛到此结束,下面我们进入下一个比赛 - 爬坡赛。爬坡赛的比赛规则是,所有算法使用同样的参数,从鞍点附近出发,经过 50 轮迭代,看看它能走到哪里。

爬坡赛

首先是我们的老朋友梯度下降法:

res, x_arr = gd([-0.23,0.0], 0.0008, g)
contour(X,Y,Z, x_arr)

我们的老朋友在爬坡赛看来是要叫白卷了,说明它虽然很轻盈,但是动力不是很足啊。

下面是动量算法:

res, x_arr = momentum([-0.23,0], 5e-4, g)
contour(X,Y,Z, x_arr)

比梯度下降好一点,但是好的有限。

然后是 Adagrad:

res, x_arr = adagrad([-0.23, 0], 1.3, g)
contour(X,Y,Z, x_arr)

好吧,表现得比转弯赛还好,省去夸赞的词语了。

下面是 Rmsprop:

res, x_arr = rmsprop([-0.23, 0], 0.3, g)
contour(X,Y,Z, x_arr)

同样完成的不错!

下面我们再看 AdaDelta:

res, x_arr = adadelta([-0.23, 0], 0.4, g)
contour(X,Y,Z, x_arr)

好吧,直接一骑绝尘而去了。

最后是我们今天登场的 Adam:

res, x_arr = adam([-0.23, 0], 0.1, g)
contour(X,Y,Z, x_arr)

同样是跑出了我们原始规划的区域。

总结

经过两轮的比赛 - 转弯赛和爬坡赛,我们测试了几种算法在同一配置上的实力。测试的目标不是为了比较哪个算法更厉害,而是展示另外一个实力 - 哪个算法表现更稳定。

因为我们在实际使用过程中,learning rate 是相对固定的,在优化过程中我们无法预料自己将会碰上什么样的情景,那么我们肯定希望一个算法又能转弯又能爬坡。如果一个算法转弯厉害但是爬坡比较弱,那一旦遇上爬坡它就会走得很慢,反之也是如此。

所以从刚才的表现来看,我们的新算法似乎表现更为平稳,现在也确实有越来越多的人抛弃了一些经典的算法,转而投入这些新算法的怀抱,而这些新算法也足够争气,拿出了它们的实力。关于算法性能的测试一直在进行,这些算法还需要经历更多的考验!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文