模型集成可以实现比单个模型更低的泛化误差,但是考虑到训练nn的时候单个模型的计算成本,使用深度学习神经网络来开发它具有挑战性。一种替代方法是在一次训练的过程中训练多个模型快照,然后将它们的预测合并以进行整体预测。此方法的局限性在于,保存的模型将相似,从而导致相似的预测和预测误差,以及结合他们的预测并不能提供太多好处。
有效的集成尊崇好而不同的原则,需要各种具有不同预测误差分布的高精度的模型(这里说的是bagging stacking这类的不搞过gradient boosting machine)。促进在一次训练中保存的模型多样性的一种方法是 使用灵活的的学习率,即训练的过程中对学习率进行动态调整,以迫使模型权重发生较大的变化,进而迫使每个快照保存的模型的性质发生变化。
用深度学习方法进行整体学习的一个问题是训练多个模型的大量计算成本。这是因为使用了非常深的模型和非常大的数据集,这可能导致模型训练时间延长到几天,几周甚至几个月。
深度学习神经网络的集成学习的一种方法是从一次训练中收集多个模型。这解决了训练多个深度学习模型的计算成本,因为可以在训练期间选择并保存模型,然后将其用于整体预测。与单个模型的预测相比,集成学习的主要优势在于性能的提高。这可以通过选择泛化性能相对较好的子模型来实现,但是可以通过不同的方式来组合的多种预测。在一次训练中收集多个模型的局限性在于,模型可能会很好,但是太相似了。这可以通过更改用于深度神经网络的学习算法来解决,以在一次训练中强制探索不同的网络权重,进而导致具有不同性能的模型。可以达到这一目的的一种方法是,积极改变训练期间使用的学习率。一种在训练过程中系统地,积极地更改学习率以产生完全不同的网络的方法。
这种方法就是循环学习率(余弦退货学习率),公式如下:
![f45004e19230fd5e497c4edb0180005c.png](https://i-blog.csdnimg.cn/blog_migrate/c8a7c8dbc4865ddcbad7facd9f715e79.png)
其中a(t)是第t个epoch处的学习率,a0是最大学习率,t是总,m是循环次数,mod是模运算,方括号表示floor操作。
![1a02d864e8dbe97ab4bbfc70507e578f.png](https://i-blog.csdnimg.cn/blog_migrate/d7824ccae35cd52ec416da78db5d9979.jpeg)
![bed36419005b26368dd5ab0da42c9be1.png](https://i-blog.csdnimg.cn/blog_migrate/ae2c7827eda9b24090a980bd60e0752d.png)
学习率的变动情况如上图这样,最高点是初始的大学习率,如上图,当到达100 iterations的时候,第一个模型生成,进行保存;
余弦退火学习率是一种在训练过程中,调整学习率的方法。第一幅图,余弦退火学习率不同于传统的学习率,随着epoch的增加,learning rate 先急速下降,再陡然提升,然后不断重复这个过程。这样剧烈波动的目的在于:试图逃离当前的最优点;
但是有个问题就是,比如第二幅图,当到达第100个iteration的时候不一定到达局部最优了,毕竟这些都是人工来定义的。。。,这是我是用snapshot的时候面临的一个比较现实的问题,举个例子,比如每个周期都很短,例如只有5个epochs,然后进行了保存,这会导致最终我们得到多个效果很差的网络权重,比如说得到了10个auc为0.7的网络结构,怎么折腾都不如训练一个auc为0.8的网络结构。。因此,snapshot也是需要做参数调整的。。。
如上图,传统的训练过程中学习率逐渐减小,所以模型逐渐找到局部最优点。这个过程中,因为一开始的学习率较大,模型不会踏入陡峭的局部最优点,而是快速往平坦的局部最优点移动。随着学习率逐渐减小,模型最终收敛到一个比较好的最优点。
如上图,由于余弦退火的学习率急速下降,所以模型会迅速踏入局部最优点(不管是否陡峭),并保存局部最优点的模型。⌈快照集成⌋中⌈快照⌋的指的就是这个意思。保存模型后,学习率重新恢复到一个较大值,逃离当前的局部最优点,并寻找新的最优点。因为不同局部最优点的模型则存到较大的多样性,所以集合之后效果会更好。
两种方式比较起来,可以理解为模型训练的“起点”和“终点”是差不多的。不同的是,余弦退火学习率使得模型的训练过程比较“曲折”。
直接来看代码实现吧:
# cosine annealing learning rate schedule
def cosine_annealing(epoch, n_epochs, n_cycles, lrate_max):
epochs_per_cycle = floor(n_epochs/n_cycles)
cos_inner = (pi * (epoch % epochs_per_cycle)) / (epochs_per_cycle)
return lrate_max/2 * (cos(cos_inner) + 1)
首先要定义n_cycles,也就是我们多少个epochs,学习率进行一次调整,假设我们总的n_epochs=1000,n_cycle=50,则 epochs_per_cycle=1000/50=20,也就是20个epochs一次循环完成,对学习率,这里直接在初始的大学习率alpha0上进行调整,
![f45004e19230fd5e497c4edb0180005c.png](https://i-blog.csdnimg.cn/blog_migrate/c8a7c8dbc4865ddcbad7facd9f715e79.png)
然后按照上面的公式,对学习率进行调整。
下面来做一些测试看看:
# scatter plot of blobs dataset
from sklearn.datasets.samples_gene