深度学习技巧与窍门

2019-08-16 17:24:58 浏览数 (1)

本文是根据自身构建深度学习模型总结而来,可能读起来比较干巴,但干货确实不少。闲话少叙,直接进入相关内容。

...

首先,为什么只是微调模型?

类似于卷积神经网络(CNN)的深度学习模型一般而言都有大量的参数,我们训练构建的模型实际上就是为了得到比较好的网络参数值,整个调参过程需要花费大量的硬件和时间资源。因此,很多研究者在改进模型时采用的方法是在专家设计和构建的模型基础上进行深入研究,一般情况下,专家会开源构建的模型结构和原理,有些会给出相应训练好的模型参数,可供其它研究人员直接使用,比如迁移学习等。

深度学习技巧

可以通过以下几种方法来改善训练模型的拟合时间和准确性:

  • 1.研究理想的预训练结构:了解迁移学习的好处,或浏览一些高效CNN模型结构。此外,可以考虑其它看起来不太明显的领域,共享潜在的相似特征。
  • 2.使用一个小的学习率:由于预先训练的权重通常比随机初始化的权重要好,所以修改参数时应该更细致些!参数的选择取决于学习环境和预训练的效果,但需要检查各个Epoch的错误以清楚收敛过程。
  • 3.使用dropout:与用于回归模型的Ridge和LASSO正则化一样,所有模型都没有优化的alpha或dropout。dropout是一个超参数,表明每次训练时丢弃的神经元概率,其设置取决于具体问题,并且必须经过实验测试。一般开始时设置得比较大,随后跨数量级的形式搜索其最优设置值。
  • 4.限制权重大小:可以限制某些层权重的最大范数(绝对值)以使得模型更加泛化。
  • 5.不要修改第一层:神经网络的第一个隐藏层倾向于捕捉通用和可解释的特征,例如形状、曲线等。因此,在应用迁移学习时,一般不会对经典模型的第一层进行修改,并且专注于优化其它层或添加隐藏层。
  • 6.修改输出层:将模型默认值替换为适合的新激活函数和输出大小。但是,不要将自己局限于最明显的解决方案,即只改变激活函数和最后输出层的节点数。虽然MNIST数据集可能看起来像是需要10个输出类别,但一些数字有共同的变化,相关结果表明输出层设置为输出12-16个类别可以更好地解决这些变体并提高模型性能!

Keras中的技巧

以下是如何修改dropout和限制MNIST数据集的权重大小:

代码语言:javascript复制
# dropout in input and hidden layers# weight constraint imposed on hidden layers# ensures the max norm of the weights does not exceed 5model = Sequential()
model.add(Dropout(0.2, input_shape=(784,))) # dropout on the inputs# this helps mimic noise or missing datamodel.add(Dense(128, input_dim=784, kernel_initializer='normal', activation='relu', kernel_constraint=maxnorm(5)))
model.add(Dropout(0.5))
model.add(Dense(128, kernel_initializer='normal', activation='tanh', kernel_constraint=maxnorm(5)))
model.add(Dropout(0.5))
model.add(Dense(1, kernel_initializer='normal', activation='sigmoid'))

Dropout最佳实践:

  • 使用小的dropout概率,一般为20%~50%,对于输入建议使用20%。概率太低会导致收获甚微,太高导致训练不好;
  • 在输入层和隐藏层上都使用dropout,这已被证明可以提高深度学习模型的性能;
  • 使用衰减大的学习速率和大的动量;
  • 限制权重,大的学习速率可能导致梯度爆炸,相关论文表明,对网络权重施加约束可以改善结果。
  • 使用大型网络。在较大的网络中使用dropout可能会获得更好的性能,从而使模型更有机会学习独立表示。

...

下面是Keras中修改最后一层的例子,将MNIST的10类修改为14类:

代码语言:javascript复制
from keras.layers.core import Activation, Dense
model.layers.pop() # defaults to lastmodel.outputs = [model.layers[-1].output]
model.layers[-1].outbound_nodes = []
model.add(Dense(14, activation='softmax')) 

以及如何冻结前五层权重的示例:

代码语言:javascript复制
for layer in model.layers[:5]:
   layer.trainable = False

或者,可以将该层的学习率设置为零,然后使用像Adadelta或Adam这样的参数自适应学习算法。

...

预训练网络库资源

Keras

  • Kaggle List
  • Kears Application
  • OpenCV Example

TensorFlow

  • VGG16
  • Inception V3
  • ResNet

Torch

  • LoadCaffe

Caffe

  • Model Zoo

在Jupyter中查看TensorBoard图

了解模型的外观通常是很重要的。如果使用的是Keras工具,搭建出来的模型会很抽象,并且不允许深入分析模型的各个部分。幸运的是,下面的代码可以直接用Python直观地看到构建的模型(代码太长,见原文):

代码语言:javascript复制
from IPython.display import clear_output, Image, display, HTMLdef strip_consts(graph_def, max_const_size=32):
   """Strip large constant values from graph_def."""
   strip_def = tf.GraphDef()    for n0 in graph_def.node:
       n = strip_def.node.add()
       n.MergeFrom(n0)        if n.op == 'Const':
           tensor = n.attr['value'].tensor
           size = len(tensor.tensor_content)            if size > max_const_size:
               tensor.tensor_content = bytes("<stripped %d bytes>"%size, 'utf-8')    return strip_def ..

用Keras可视化模型

以下代码将绘制模型的图形并将其保存为png文件:

代码语言:javascript复制
from keras.utils.visualize_util import plot
plot(model, to_file='model.png')

plot有两个参数可供选择:

  • show_shapes(默认为False)控制输出形状是否显示在图形中;
  • show_layer_names(默认为True)控制图层中是否显示图层名称; 也可以直接获取pydot.Graph对象并自己渲染它,例如在ipython notebook中显示它:
代码语言:javascript复制
from IPython.display import SVGfrom keras.utils.visualize_util import model_to_dot
SVG(model_to_dot(model).create(prog='dot', format='svg'))

以上即为个人的全部建模经验,读者如果有不同意见或有其它优方法的话可以留言探讨。

0 人点赞