深度学习如何优化神经网络结构

优化是非常困难的一类问题,而这正是深度学习的核心。优化问题是如此困难,以至于在神经网络引入几十年后,深度神经网络的优化问题仍阻碍着它们的推广,并导致了其 20 世纪 90 年代到 21 世纪初的衰落。自那以后,我们解决了这个问题。在这篇文章中,我会探讨优化神经网络的「困难度(hardness)」,并发掘其背后的理论。简而言之:网络越深,优化问题就越难。


 

最简单的神经网络是单节点感知器,其优化问题是凸优化的。凸优化问题的好处是其所有的局部最小值也是全局最小值。现在有各种各样的优化算法来处理凸优化问题,且每隔几年就有更好用于凸优化理论的多项式时间算法(polynomial-time algorithms)出现。运用凸优化很容易得到单个神经元的优化权重(见下图)。从单个神经元开始,让我们看看会发生什么。

图 1。左:凸函数。右:非凸函数。沿着函数表面,凸函数比非凸函数更容易找到表面的最小值。(来源: Reza Zadeh)


 

下一步是保持单层网络下添加多个神经元。对于单层、n 节点的感知机神经网络,如果存在一组边权重使得网络可以正确地分类给定的训练集,则这样的权重可以通过线性规划用 n 的多项式时间找到,这也是凸优化的特殊例子。所以下个问题是:对于更深的多层神经网络,我们是否可以类似地使用这种多项式时间方法?不幸的是,我们无法保证


 

能够有效解决两层或多层的广义神经网络的优化问题并不容易,这些算法将会涉及计算机科学中的一些最棘手的开放性问题。因此,要想机器学习研究人员找到可靠的深度网络最佳优化算法可能性十分渺茫。因为该问题是 NP-hard(非确定性多项式困难 non-deterministic polynomial hard)的,也就意味着如果可以在多项式时间的计算复杂度中解决它,也将解决数十年来悬而未决的几千个开放性问题。事实上,1988 年 J.Stephen Judd 阐述的以下问题就是 NP-hard:


 

给定一个广义神经网络和一组训练集样本,是否存在一组网络边权重(edge weight),使网络能够为所有的训练样本产生正确的输出结果?


 

Judd 还表明,即使只需要神经网络正确输出三分之二的训练样本,但还是 NP-hard 的,这意味着即使在最坏的情况下,训练一个不精确的神经网络在本质上也是困难的。1993 年,Blum 和 Rivest 证明了更坏的消息:即使训练一个只有两层和三个节点的简单神经网络也是 NP-hard!


 

理论上,对比深度学习与机器学习中的许多更简单的模型(例如支持向量机和逻辑回归),这些模型可以在数学上保证优化能在多项式时间中执行。对于这些更简单的模型,我们能够保证优化算法在多项式时间内就会找到最佳模型。但是,对于深度神经网络的优化算法,并没有这样的保证。根据你的设置来看,你不知道你训练的深度神经网络是否是你可以找到的最好的模型。所以你也并不知道如果继续训练是否能得到更好的模型。


 

幸运的是,实践中我们可以非常有效地解决这些「困难」结果:运用典型梯度下降(gradient descent)优化方法可以给出足够好的局部最小值,让我们在许多问题上取得了巨大进步,例如图像识别、语音识别和机器翻译。我们只是忽略困难的部分,在时间允许下尽可能多地运用梯度下降迭代。


 

似乎最优化问题的传统理论结果是很笨拙的,我们很大程度上可以通过工程和数学技巧、启发式方法、增加更多的机器或使用新的硬件(如 GPU)来解决它们。有意思的是,仍有很多人研究为什么典型的优化算法如此有用,当然除了那些困难的部分。


 

深度学习流行的原因远远不止是解决了优化问题。深度学习在许多机器学习任务中获得领先,它的网络的架构、训练的数据量、损失函数和正则化都起着关键作用。

优化方法(SGD,Adagrad,Adadelta,Adam,Adamax,Nadam)

https://zhuanlan.zhihu.com/p/22252270


 

SGD

此处的SGD指mini-batch gradient descent,关于batch gradient descent, stochastic gradient descent, 以及 mini-batch gradient descent的具体区别就不细说了。现在的SGD一般都指mini-batch gradient descent。


 

SGD就是每一次迭代计算mini-batch的梯度,然后对参数进行更新,是最常见的优化方法了。即:


 


 


 


 

其中,


 

是学习率,


 

是梯度SGD完全依赖于当前batch的梯度,所以


 

可理解为允许当前batch的梯度多大程度影响参数更新


 

缺点:(正因为有这些缺点才让这么多大神发展出了后续的各种算法)


 

Momentum

momentum是模拟物理里动量的概念,积累之前的动量来替代真正的梯度。公式如下:


 


 


 

其中,


 

是动量因子


 

特点:


 

能够进行很好的加速

使得更新幅度增大,跳出陷阱

能够减少更新总而言之,momentum项能够在相关方向加速SGD,抑制振荡,从而加快收敛

Nesterov

nesterov项在梯度更新时做一个校正,避免前进太快,同时提高灵敏度。 将上一节中的公式展开可得:


 

可以看出,


 

并没有直接改变当前梯度


 

,所以Nesterov的改进就是让之前的动量直接影响当前的动量。即:


 


 


 


 


 

所以,加上nesterov项后,梯度在大的跳跃后,进行计算对当前梯度进行校正。如下图:


 

momentum首先计算一个梯度(短的蓝色向量),然后在加速更新梯度的方向进行一个大的跳跃(长的蓝色向量),nesterov项首先在之前加速的梯度方向进行一个大的跳跃(棕色向量),计算梯度然后进行校正(绿色梯向量)


 

其实,momentum项和nesterov项都是为了使梯度更新更加灵活,对不同情况有针对性。但是,人工设置一些学习率总还是有些生硬,接下来介绍几种自适应学习率的方法


 

Adagrad

Adagrad其实是对学习率进行了一个约束。即:


 


 


 

此处,对


 

从1到


 

进行一个递推形成一个约束项regularizer,


 


 

用来保证分母非0


 

特点:


 

较小的时候, regularizer较大,能够放大梯度

较大的时候,regularizer较小,能够约束梯度

缺点:


 

,使得训练提前结束

Adadelta

Adadelta是对Adagrad的扩展,最初方案依然是对学习率进行自适应约束,但是进行了计算上的简化。Adagrad会累加之前所有的梯度平方,而Adadelta只累加固定大小的项,并且也不直接存储这些项,仅仅是近似计算对应的平均值。即:


 


 


 

在此处Adadelta其实还是依赖于全局学习率的,但是作者做了一定处理,经过近似牛顿迭代法之后:


 


 


 

其中,


 

代表求期望。


 

此时,可以看出Adadelta已经不用依赖于全局学习率了。


 

特点:


 

RMSprop

RMSprop可以算作Adadelta的一个特例:


 


 

时,


 

就变为了求梯度平方和的平均数。


 

如果再求根的话,就变成了RMS(均方根):


 

此时,这个RMS就可以作为学习率


 

的一个约束:


 

特点:


 

Adam

Adam(Adaptive Moment Estimation)本质上是带有动量项的RMSprop,它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。Adam的优点主要在于经过偏置校正后,每一次迭代学习率都有个确定范围,使得参数比较平稳。公式如下:


 


 


 


 


 


 


 


 


 

其中,


 


 

分别是对梯度的一阶矩估计和二阶矩估计,可以看作对期望


 


 

的估计;


 


 

是对


 


 

的校正,这样可以近似为对期望的无偏估计。可以看出,直接对梯度的矩估计对内存没有额外的要求,而且可以根据梯度进行动态调整,而


 

对学习率形成一个动态约束,而且有明确的范围。


 

特点:


 

Adamax

Adamax是Adam的一种变体,此方法对学习率的上限提供了一个更简单的范围。公式上的变化如下:


 


 


 

可以看出,Adamax学习率的边界范围更简单


 

Nadam

Nadam类似于带有Nesterov动量项的Adam。公式如下:


 


 


 


 


 


 


 


 


 


 


 

可以看出,Nadam对学习率有了更强的约束,同时对梯度的更新也有更直接的影响。一般而言,在想使用带动量的RMSprop,或者Adam的地方,大多可以使用Nadam取得更好的效果。


 

经验之谈

最后展示两张可厉害的图,一切尽在图中啊,上面的都没啥用了… …


 

损失平面等高线


 

在鞍点处的比较


 

转载须全文转载且注明作者和原文链接,否则保留维权权利


 

引用

[1]Adagrad


 

[2]RMSprop[Lecture 6e]


 

[3]Adadelta


 

[4]Adam


 

[5]Nadam


 

[6]On the importance of initialization and momentum in deep learning


 

[7]Keras中文文档


 

[8]Alec Radford(图)


 

[9]An overview of gradient descent optimization algorithms


 

[10]Gradient Descent Only Converges to Minimizers


 

[11]Deep Learning:Nature

Torch-rnn

视频:https://youtu.be/NG-LATBZNBs?list=PLlF2F_XFTTKKR_vHU0UDrjU6PLxI_41Yk

安装:http://www.jeffreythompson.org/blog/2016/03/25/torch-rnn-mac-install/

https://github.com/jcjohnson/torch-rnn

注意:

要在python2.7环境下安装:

conda create -n python2 python=2.7 <anaconda 加这条表示安装所有库>


 

关于以上的错误,参考如下:

https://github.com/deepmind/torch-hdf5/issues/83#issuecomment-254427843

change


 

local process = io.popen(“gcc -E ” .. headerPath) — TODO pass -I

to

local process = io.popen(“gcc -D ‘_Nullable=’ -E ” .. headerPath) — TODO pass -I


 


 

在torch-rnn目录下执行:

th sample.lua -checkpoint cv/checkpoint_17000.t7 -length 2000 -gpu -1 <-temperature 0.2 取值在0-1之间,越小越像正常英语> > <shakespeare.txt 可选存到此文件中>

TensorFlow与OpenCV,读取图片,进行简单操作并显示

TensorFlow与OpenCV,读取图片,进行简单操作并显示 难度1

http://blog.csdn.net/helei001/article/details/52400497


 

import tensorflow as tf

import cv2

 

#file_path = ‘/Users/cloveai/Desktop/’

#ilename = ‘1.jpg’

 

image = cv2.imread(‘/Users/cloveai/Desktop/1.jpg’, 1)

cv2.namedWindow(‘image’, 0)

cv2.imshow(‘image’, image)

 

# Create a TensorFlow Variable

x = tf.Variable(image, name=’x’)

 

#model = tf.initialize_all_variables()

model = tf.global_variables_initializer()

with tf.Session() as session:

    x = tf.transpose(x, perm=[1, 0, 2])

    session.run(model)

    result = session.run(x)

 

cv2.namedWindow(‘result’, 0)

cv2.imshow(‘result’, result)

cv2.waitKey(0)

树莓派超级计算机

  1. 安装mpi4py https://www.youtube.com/watch?v=bBpKq3Y-E2g&list=PLlF2F_XFTTKI2lGpp-tDRthxVCqRG6gNz

http://www.tinkernut.com/2014/04/make-cluster-computer/

http://www.tinkernut.com/2014/05/make-cluster-computer-part-2/


 

cd ./mpi4py-2.0.0

mpiexec -n <numofprocessor> python demo/helloworld.py


 


 


 

  1. 安装opencv3 http://www.pyimagesearch.com/2016/04/18/install-guide-raspberry-pi-3-raspbian-jessie-opencv-3/

source ~./profile

workon cv

python

import cv2


 


 


 

  1. 安装tensorflow

https://github.com/samjabrahams/tensorflow-on-raspberry-pi#installing-from-pip

https://github.com/samjabrahams/tensorflow-on-raspberry-pi/blo

另一种方式:https://github.com/samjabrahams/tensorflow-on-raspberry-pi

python3

import tensorflow


 


 

  1. 安装Google Assistant https://developers.google.com/assistant/sdk/prototype/getting-started-pi-python/run-sample


https://pypi.python.org/pypi/google-assistant-sdk

进入虚拟Python命令:source gooassistant/bin/activate

退出:deactivate

音频设备查看:arecord -l aplay -l 查看card和device

音频录制:arecord -d 10 -D plughw:<cardid>,<deviceid> test.wav ///默认保存在/home/pi

执行命令:google-assistant-demo


 


 


 


 


 


 


 

  1. 备份


 

scp -r filename.py <ip address>:/home/pi

mpiexec -r machinefile -n 1 python filename.py

MarI/O缺附件


 

  1. 安装bizhawk_prereqs_v1.4
  2. 网上下载Super Mario World (USA).sfc 或类似游戏,将文件名改为此
  3. 打开EmuHawk.exe,载入ROM。模拟器选择SNES。
  4. 在开局进行手动命名存档,存档名为DP1.State,将此存档放在模拟器根目录下和Lua目录下
  5. 载入lua脚本
  6. 观察
  7. 备份文件是Lua文件夹里的backup.xx.DP1.state.pool。每次断开重新开始时可以载入最后一个文件修改名字为DP1.state.pool


 

原地址:https://www.youtube.com/watch?v=qv6UVOQ0F44

AI test by Facebook

地址:https://github.com/facebook/bAbI-tasks


 

安装torch 和 luajit:

git clone https://github.com/torch/distro.git ~/torch –recursive

cd ~/torch

bash install-deps

./install.sh

source /Users/chenhongyu/torch/install/bin/torch-activate

luarocks make babitasks-scm-1.rockspec


 

每次执行前运行:

source /Users/chenhongyu/torch/install/bin/torch-activate


 


 


 

执行代码:

例如:

babi-tasks 3

fast-style-transfer 图像滤镜

网址:https://github.com/floydhub/fast-style-transfer


 


 

对于错误:

Traceback (most recent call last):

File “evaluate.py”, line 267, in <module>

main()

File “evaluate.py”, line 264, in main

batch_size=opts.batch_size)

File “evaluate.py”, line 147, in ffwd

preds = transform.net(img_placeholder)

File “src/transform.py”, line 14, in net

conv_t1 = _conv_tranpose_layer(resid5, 64, 3, 2)

File “src/transform.py”, line 38, in _conv_tranpose_layer

tf_shape = tf.pack(new_shape)

AttributeError: ‘module’ object has no attribute ‘pack’


 

修改src/transform.py”, line 14, 将tf.pack 替换成 tf.stack