第七部分 让 学习率学习潜能 随时间的变化

光训练就花了一个小时的时间。等结果并非一个令人心情愉快的事情。这一部分。我们将讨论将两个技巧结合让网络训练的更快!

直觉上的解决的方法是,開始训练时取一个较高的学习率,随着迭代次数的增多不停的减小这个值。这是有道理的,由于開始的时候我们距离全局最长处很远。我们想要朝着最长处的方向大步前进;然而里最长处越近,我们就前进的越慎重,以免一步跨过去。举个样例说就是你乘火车回家,但你进家门的时候肯定是走进去。不能让火车开进去。

从讨论深度学习中初始化和学习势的重要性的资料,我们得到了一种新的技巧来加速网络的训练:添加最优化方法的“动量參数”。假设你还不知道什么是学习势,请阅读【參考】。

在我们上一个模型中,我们将学习率和学习势初始化为0.01和0.9。让我们来改变这两个參数,使得学习率随着迭代次数线性减小。同一时候让学习势增大。

NeuralNet同意我们在训练时通过on_epoch_finished钩子函数来更新參数。于是我们传一个函数给on_epoch_finished,使得这个函数在每次迭代之后被调用。

然而。在我们改变学习率和学习势这两个參数之前,我们必须将这两个參数改变为Theano shared variables。

好在这很easy。

import theano

def float32(k):
return np.cast['float32'](k) net4 = NeuralNet(
# ...
update_learning_rate=theano.shared(float32(0.03)),
update_momentum=theano.shared(float32(0.9)),
# ...
)

我们传递的回调函数在调用时,须要两个參数:nn 是NeuralNet的实例,train_history,和nn.history是同一个值。

我们使用一个可參数化的类,在当中定义一个call函数来作为我们的回调函数。让我们把这个类叫做AdjustVariable,看一下这个类的实现:

class AdjustVariable(object):
def __init__(self, name, start=0.03, stop=0.001):
self.name = name
self.start, self.stop = start, stop
self.ls = None def __call__(self, nn, train_history):
if self.ls is None:
self.ls = np.linspace(self.start, self.stop, nn.max_epochs) epoch = train_history[-1]['epoch']
new_value = float32(self.ls[epoch - 1])
getattr(nn, self.name).set_value(new_value)

如今让我们把这些变化放到一起:

net4 = NeuralNet(
# ...
update_learning_rate=theano.shared(float32(0.03)),
update_momentum=theano.shared(float32(0.9)),
# ...
regression=True,
# batch_iterator_train=FlipBatchIterator(batch_size=128),
on_epoch_finished=[
AdjustVariable('update_learning_rate', start=0.03, stop=0.0001),
AdjustVariable('update_momentum', start=0.9, stop=0.999),
],
max_epochs=3000,
verbose=1,
) X, y = load2d()
net4.fit(X, y) with open('net4.pickle', 'wb') as f:
pickle.dump(net4, f, -1)

我们将训练两个网络:net4不适用之前的FlipBatchIterator。net5採用了。

除了这一点之外,两个网络全然相同。

Net4的学习步骤例如以下:

Epoch Train loss Valid loss Train / Val
50 0.004216 0.003996 1.055011
100 0.003533 0.003382 1.044791
250 0.001557 0.001781 0.874249
500 0.000915 0.001433 0.638702
750 0.000653 0.001355 0.481806
1000 0.000496 0.001387 0.357917

能够看到,训练速度快多了。

第500次、1000次迭代的训练错误。net4都比net2低了一半。可是泛华程度到750次就不再变好了,所以看起来没有必要训练这么多次。

看看打开了数据扩充之后的net5表现怎样:

Epoch Train loss Valid loss Train / Val
50 0.004317 0.004081 1.057609
100 0.003756 0.003535 1.062619
250 0.001765 0.001845 0.956560
500 0.001135 0.001437 0.790225
750 0.000878 0.001313 0.668903
1000 0.000705 0.001260 0.559591
1500 0.000492 0.001199 0.410526
2000 0.000373 0.001184 0.315353

相同的,和net3相比net5训练的快多了。并且获得了更好的结果。

在1000次迭代后,结果比net3迭代了3000次的效果还要好。此外,使用了数据扩充的网络的验证错误也比不使用数据扩充好了10%。

第八部分 丢弃技巧(Dropout)

2012年。这篇paper中引入了一种叫做“Dropout”的技巧,作为正则化方法,dropout工作的出奇的好。这里不会讲dropout之所以好用的细节,只是你能够阅读这些參考

和其它的正则化技巧一样。dropout仅仅有当网络过拟合的时候才有意义。上个部分我们训练的net5是明显过拟合的。注意一定要使你的网络过拟合,再使用正则化。

在Lasagne中使用正则化技巧。我们仅仅要在网络中加入DropoutLayer并指定每层dropout的概率。

这里是我们最新网络的完整定义,我在新加入的行后面加入了#。来标识与net5的不同。

net6 = NeuralNet(
layers=[
('input', layers.InputLayer),
('conv1', layers.Conv2DLayer),
('pool1', layers.MaxPool2DLayer),
('dropout1', layers.DropoutLayer), # !
('conv2', layers.Conv2DLayer),
('pool2', layers.MaxPool2DLayer),
('dropout2', layers.DropoutLayer), # !
('conv3', layers.Conv2DLayer),
('pool3', layers.MaxPool2DLayer),
('dropout3', layers.DropoutLayer), # !
('hidden4', layers.DenseLayer),
('dropout4', layers.DropoutLayer), # !
('hidden5', layers.DenseLayer),
('output', layers.DenseLayer),
],
input_shape=(None, 1, 96, 96),
conv1_num_filters=32, conv1_filter_size=(3, 3), pool1_pool_size=(2, 2),
dropout1_p=0.1, # !
conv2_num_filters=64, conv2_filter_size=(2, 2), pool2_pool_size=(2, 2),
dropout2_p=0.2, # !
conv3_num_filters=128, conv3_filter_size=(2, 2), pool3_pool_size=(2, 2),
dropout3_p=0.3, # !
hidden4_num_units=500,
dropout4_p=0.5, # !
hidden5_num_units=500,
output_num_units=30, output_nonlinearity=None, update_learning_rate=theano.shared(float32(0.03)),
update_momentum=theano.shared(float32(0.9)), regression=True,
batch_iterator_train=FlipBatchIterator(batch_size=128),
on_epoch_finished=[
AdjustVariable('update_learning_rate', start=0.03, stop=0.0001),
AdjustVariable('update_momentum', start=0.9, stop=0.999),
],
max_epochs=3000,
verbose=1,
)

我们的网路如今已经大到能够让python报一个“超过最大递归限制”错误了。所以为了避免这一点。我们最好添加python的递归限制。

import sys
sys.setrecursionlimit(10000) X, y = load2d()
net6.fit(X, y) import cPickle as pickle
with open('net6.pickle', 'wb') as f:
pickle.dump(net6, f, -1)

看一下我们如今的训练,我们注意到训练速度又变慢了,以为加入了dropout。这是不出意料的效果。然而。整个网络的表现其实超过了net5:

Epoch Train loss Valid loss Train / Val
50 0.004619 0.005198 0.888566
100 0.004369 0.004182 1.044874
250 0.003821 0.003577 1.068229
500 0.002598 0.002236 1.161854
1000 0.001902 0.001607 1.183391
1500 0.001660 0.001383 1.200238
2000 0.001496 0.001262 1.185684
2500 0.001383 0.001181 1.171006
3000 0.001306 0.001121 1.164100

仍然过拟合不一定是坏事,虽然我们必须小心这些数字:训练错误和验证错误的比率如今的意义稍有不同,由于训练错误是受过dropout调制的,而验证错误没有。更有比較意义的数值是:

from sklearn.metrics import mean_squared_error
print mean_squared_error(net6.predict(X), y) # prints something like 0.0010073791

在我们上一个没有dropout的模型里,训练集上的错误是0.00373。所以如今我们的dropout net不但表现稍好,并且过拟合水平更低。

这是好消息,由于我们能够通过使得网络更大获得更好的效果。这也正是我们接下来要做的。我们加倍网络最后两个隐层的单元个数。更新这两行:

net7 = NeuralNet(
# ...
hidden4_num_units=1000, # !
dropout4_p=0.5,
hidden5_num_units=1000, # !
# ...
)

相比于没有dropout的网络,改进效果更加明显:

Epoch Train loss Valid loss Train / Val
50 0.004756 0.007043 0.675330
100 0.004440 0.005321 0.834432
250 0.003974 0.003928 1.011598
500 0.002574 0.002347 1.096366
1000 0.001861 0.001613 1.153796
1500 0.001558 0.001372 1.135849
2000 0.001409 0.001230 1.144821
2500 0.001295 0.001146 1.130188
3000 0.001195 0.001087 1.099271

有一点过拟合,但效果着实不错。我的感觉是,假设继续添加训练次数,模型效果会变得更棒。

试一下:

net12 = NeuralNet(
# ...
max_epochs=10000,
# ...
)
Epoch Train loss Valid loss Train / Val
50 0.004756 0.007027 0.676810
100 0.004439 0.005321 0.834323
500 0.002576 0.002346 1.097795
1000 0.001863 0.001614 1.154038
2000 0.001406 0.001233 1.140188
3000 0.001184 0.001074 1.102168
4000 0.001068 0.000983 1.086193
5000 0.000981 0.000920 1.066288
6000 0.000904 0.000884 1.021837
7000 0.000851 0.000849 1.002314
8000 0.000810 0.000821 0.985769
9000 0.000769 0.000803 0.957842
10000 0.000760 0.000787 0.966583

如今你是dropout魔力的见证者了。:-)

让我们比較一下到眼下为止我们训练过的网络:

Name Description Epochs Train loss Valid loss
net1 single hidden 400 0.002244 0.003255
net2 convolutions 1000 0.001079 0.001566
net3 augmentation 3000 0.000678 0.001288
net4 mom + lr adj 1000 0.000496 0.001387
net5 net4 + augment 2000 0.000373 0.001184
net6 net5 + dropout 3000 0.001306 0.001121
net7 net6 + epochs 10000 0.000760 0.000787

使用CNN(convolutional neural nets)检測脸部关键点教程(一):环境搭建和数据

使用CNN(convolutional neural nets)检測脸部关键点教程(二):浅层网络训练和測试

使用CNN(convolutional neural nets)检測脸部关键点教程(三):卷积神经网络训练和数据扩充

使用CNN(convolutional neural nets)检測脸部关键点教程(五):通过前训练(pre-train)训练专项网络

使用CNN(convolutional neural nets)关键的一点是检测到的面部教程(四):学习率,学习潜能,dropout的更多相关文章

  1. (zhuan) Using convolutional neural nets to detect facial keypoints tutorial

    Using convolutional neural nets to detect facial keypoints tutorial   this blog from: http://danieln ...

  2. CNN(Convolutional Neural Network)

    CNN(Convolutional Neural Network) 卷积神经网络(简称CNN)最早可以追溯到20世纪60年代,Hubel等人通过对猫视觉皮层细胞的研究表明,大脑对外界获取的信息由多层的 ...

  3. 卷积神经网络CNN(Convolutional Neural Networks)没有原理只有实现

    零.说明: 本文的所有代码均可在 DML 找到,欢迎点星星. 注.CNN的这份代码非常慢,基本上没有实际使用的可能,所以我只是发出来,代表我还是实践过而已 一.引入: CNN这个模型实在是有些年份了, ...

  4. Large-Scale Oil Palm Tree Detection from High-Resolution Satellite Images Using Two-Stage Convolutional Neural Networks(worldview油棕树检测)

    不是目标检测也不是语义分割,两步CNN指的是,采集的数据是一堆点,以点为中心的65*65和17*17图像范围大小来判断这个点是否是油棕树.第一步就是判断65*65的范围是否为(油棕树植被群,其他植被/ ...

  5. 一目了然卷积神经网络 - An Intuitive Explanation of Convolutional Neural Networks

    An Intuitive Explanation of Convolutional Neural Networks 原文地址:https://ujjwalkarn.me/2016/08/11/intu ...

  6. [转]An Intuitive Explanation of Convolutional Neural Networks

    An Intuitive Explanation of Convolutional Neural Networks https://ujjwalkarn.me/2016/08/11/intuitive ...

  7. An Intuitive Explanation of Convolutional Neural Networks

    https://ujjwalkarn.me/2016/08/11/intuitive-explanation-convnets/ An Intuitive Explanation of Convolu ...

  8. Deep learning_CNN_Review:A Survey of the Recent Architectures of Deep Convolutional Neural Networks——2019

    CNN综述文章 的翻译 [2019 CVPR] A Survey of the Recent Architectures of Deep Convolutional Neural Networks 翻 ...

  9. 卷积神经网络(Convolutional Neural Network, CNN)简析

    目录 1 神经网络 2 卷积神经网络 2.1 局部感知 2.2 参数共享 2.3 多卷积核 2.4 Down-pooling 2.5 多层卷积 3 ImageNet-2010网络结构 4 DeepID ...

随机推荐

  1. 移动web:图片切换(焦点图)

    在web页面上图片切换(焦点图)效果实在是太常见了,PC端.移动端到处都有它的身影. 上次写了个tab选项卡的效果,在这里延续一下,改成图片切换的效果. 如果不需要自动播放,稍微修改下html标签.和 ...

  2. 两个文件中的配置项设置方法和C比较程序处理

    在实际的软件开发项目.程序经常需要翻阅了一些资料可能会改变从外部,我们需要读出的信息到一个统一的文件(一般ini档),而此文件被称为个人资料. 考虑这样一个场景,程序须要与多个数据库打交道,要从配置文 ...

  3. C# winForm里窗体嵌套

    ShowAllPage sAllPage = new ShowAllPage();            sAllPage.FormBorderStyle = FormBorderStyle.None ...

  4. Git Flow流程

    # 1. clone远程仓库到本地 git clone git@git.oschina.net:huogh/muzhifm_xxx.git ​ # 2. 使用远程分支origin/dev创建本地分支d ...

  5. cocos2dx3.1-lua移植android流程

    我很懒惰,写这篇博客只是为了能够转出后,当忘记查看,所以我写了下面非常简单的内容.假设完全没有经验的学生请找另一篇文章 一.环境配置(win7): 用户变量如下面: ANDROID_SDK_ROOT: ...

  6. 编hadoop-1.X源代码

    满足需要在不久的将来windows调试Linux下一个hadoop问题,Linux检查时需要的文件权限.和windows在没有必要,因此,有必要修改hadoop源代码,再次编译,过程例如以下: (1) ...

  7. linux权限和ntfs知识文件系统权限

    左右ntfs权限的问题 文件权限: [-dcbps][u:rwx][g:rwx][a:rwx] 当中: r=4, w=2, x=1,  u=owner, g=group, a=all user     ...

  8. 职业选择測试(A/B卷)

    不同性格的人适合从事不同的职业.职业选择对于每一个人都是很重要的事情.假设能选一个既可以发挥潜能又有兴趣的工作,会使整个团队的效率逐倍增长.想了解你更适合什么职业吗?一起来測试一下吧.本套測试分为A卷 ...

  9. 【SSH2(实用文章)】--Struts2文件上传和下载的例子

    回想一下,再上一篇文章Struts2实现机制,该步骤做一步一步来解决,这种决心不仅要理清再次Struts2用法.映射机制及其在深入分析.最后一个例子来介绍Struts2一种用法,这里将做一个有关文件上 ...

  10. NOI第一天感想&小结

    嘛...中午总算是到了深圳了--在虹桥机场和飞机上和市队大神们一起讨论各种各样奇(sang)葩(bing)的算(ren)法(lei)还是非常开心的,在此再各种膜拜一下尽管没来比赛的FFT大神@陈中瑞 ...