使用CNN(convolutional neural nets)关键的一点是检测到的面部教程(四):学习率,学习潜能,dropout
第七部分 让 学习率 和 学习潜能 随时间的变化
光训练就花了一个小时的时间。等结果并非一个令人心情愉快的事情。这一部分。我们将讨论将两个技巧结合让网络训练的更快!
直觉上的解决的方法是,開始训练时取一个较高的学习率,随着迭代次数的增多不停的减小这个值。这是有道理的,由于開始的时候我们距离全局最长处很远。我们想要朝着最长处的方向大步前进;然而里最长处越近,我们就前进的越慎重,以免一步跨过去。举个样例说就是你乘火车回家,但你进家门的时候肯定是走进去。不能让火车开进去。
从讨论深度学习中初始化和学习势的重要性的资料,我们得到了一种新的技巧来加速网络的训练:添加最优化方法的“动量參数”。假设你还不知道什么是学习势,请阅读【參考】。
在我们上一个模型中,我们将学习率和学习势初始化为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的更多相关文章
- (zhuan) Using convolutional neural nets to detect facial keypoints tutorial
Using convolutional neural nets to detect facial keypoints tutorial this blog from: http://danieln ...
- CNN(Convolutional Neural Network)
CNN(Convolutional Neural Network) 卷积神经网络(简称CNN)最早可以追溯到20世纪60年代,Hubel等人通过对猫视觉皮层细胞的研究表明,大脑对外界获取的信息由多层的 ...
- 卷积神经网络CNN(Convolutional Neural Networks)没有原理只有实现
零.说明: 本文的所有代码均可在 DML 找到,欢迎点星星. 注.CNN的这份代码非常慢,基本上没有实际使用的可能,所以我只是发出来,代表我还是实践过而已 一.引入: CNN这个模型实在是有些年份了, ...
- 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的范围是否为(油棕树植被群,其他植被/ ...
- 一目了然卷积神经网络 - An Intuitive Explanation of Convolutional Neural Networks
An Intuitive Explanation of Convolutional Neural Networks 原文地址:https://ujjwalkarn.me/2016/08/11/intu ...
- [转]An Intuitive Explanation of Convolutional Neural Networks
An Intuitive Explanation of Convolutional Neural Networks https://ujjwalkarn.me/2016/08/11/intuitive ...
- An Intuitive Explanation of Convolutional Neural Networks
https://ujjwalkarn.me/2016/08/11/intuitive-explanation-convnets/ An Intuitive Explanation of Convolu ...
- 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 翻 ...
- 卷积神经网络(Convolutional Neural Network, CNN)简析
目录 1 神经网络 2 卷积神经网络 2.1 局部感知 2.2 参数共享 2.3 多卷积核 2.4 Down-pooling 2.5 多层卷积 3 ImageNet-2010网络结构 4 DeepID ...
随机推荐
- udacity android 学习笔记: lesson 4 part b
udacity android 学习笔记: lesson 4 part b 作者:干货店打杂的 /titer1 /Archimedes 出处:https://code.csdn.net/titer1 ...
- 制作service服务,shell脚本小例子(来自网络)
事先准备工作:源码安装apache .安装目录为/usr/local/httpd 任务需求:1.可通过 service httpd start|stop|status|restart 命令对服务进行控 ...
- HDU4866 Shooting (要持久段树)
意甲冠军: 给你一些并行x行轴.总是询问坐标x的顶部之前,k一个段高度,.标题是必须在线. 思路: 首先要会可持久化线段树(又称主席树和函数式线段树).不会的能够去做下POJ 2104. 把全部线段高 ...
- Lua基础(转)
局部定义与代码块: 使用local声明一个局部变量或局部函数,局部对象只在被声明的那个代码块中有效. 代码块:一个控制结构.一个函数体.一个chunk(一个文件或文本串)(Lua把chunk当做函数处 ...
- 有人实践过 Phabricator 以及 Arcanist 作为 code review 的工具么?(转)
作者:覃超链接:http://www.zhihu.com/question/19977889/answer/13539702来源:知乎 平时就经常实践. 整个公司的code review就是使用这个. ...
- thinkphp达到UploadFile.class.php图片上传功能
片上传在站点里是非经常常使用的功能.ThinkPHP里也有自带的图片上传类(UploadFile.class.php) 和图片模型类(Image.class.php).方便于我们去实现图片上传功能,以 ...
- 用AsyncTask实现多线程
前言 在Android应用开发中,有时我们需要实现任务的同步.Android里的AsyncTask类可以帮我们更好地管理线程同步(异步方式),就像Thread类能做的,不过用法比Thread更简单. ...
- 为应用程序池 'DefaultAppPool' 提供服务的进程关闭时间超过了限制
服务器经常产生“应用程序池 'DefaultAppPool' 提供服务的进程关闭时间超过了限制.进程 ID 是 '2068'.”的错误,导致iis处于假死状态,经了解是IIS应用程序池的设置问题.解决 ...
- XXTEA 加密算法 C++ C#兼容版本号
1.一个不错的可逆加密算法XXTEA 之前无意中看到了TexturePacker 使用了XXTEA来加密图片资源.所以花了点时间来看了下XXTEA. 一般有两种加密算法:1.像md5,SHA1,等ha ...
- cocos2d-x lua 学习笔记(1) -- 环境结构
Cocos2d-x 3.0超过环境的版本号来建立和前Cocos2d-x 2.0 差异较大的版本,从同时Cocos2d-x 3.0项目打包成apkAndroid的应用程序文件,步骤,构建环境有些乏味安德 ...