神经网络的结构(例如2输入3隐节点1输出)建好后,一般就要求神经网络里的权值和阈值。现在一般求解权值和阈值,都是采用梯度下降之类的搜索算法(梯度下降法、牛顿法、列文伯格-马跨特法、狗腿法等等),这些算法会先初始化一个解,在这个解的基础上,确定一个搜索方向和一个移动步长(各种法算确定方向和步长的方法不同,也就使各种算法适用于解决不同的问题),使初始解根据这个方向和步长移动后,能使目标函数的输出(在神经网络中就是预测误差)下降。 然后将它更新为新的解,再继续寻找下一步的移动方向的步长,这样不断的迭代下去,目标函数(神经网络中的预测误差)也不断下降,最终就能找到一个解,使得目标函数(预测误差)比较小。
而在寻解过程中,步长太大,就会搜索得不仔细,可能跨过了优秀的解,而步长太小,又会使寻解过程进行得太慢。因此,步长设置适当非常重要。
学习率对原步长(在梯度下降法中就是梯度的长度)作调整,如果学习率lr = 0.1,那么梯度下降法中每次调整的步长就是0.1*梯度,
而在matlab神经网络工具箱里的lr,代表的是初始学习率。因为matlab工具箱为了在寻解不同阶段更智能的选择合适的步长,使用的是可变学习率,它会根据上一次解的调整对目标函数带来的效果来对学习率作调整,再根据学习率决定步长。
机制如下:
if newE2/E2 >maxE_inc %若果误差上升大于阈值
lr = lr * lr_dec %则降低学习率
else
if newE2 <E2%若果误差减少
lr = lr * lr_inc%则增加学习率
end
详细的可以看《神经网络之家》nnetinfo里的《[重要]写自己的BP神经网络(traingd)》一文,里面是matlab神经网络工具箱梯度下降法的简化代码
若果对你有帮助,请点赞。
祝学习愉快
我们到目前为止在神经网络中使用了好几个参数, hyper-parameters包括:
学习率(learning rate):η
Regularization parameter:λ
之前只是设置了一些合适的值, 如何来选择合适的hyper-parameters呢?
例如:
我们设置如下参数:
隐藏层: 30个神经元, mini-batch size: 10, 训练30个epochs
η=10.0, λ=1000.0
>>>importmnist_loader>>>
training_data,validation_data,test_data=\...mnist_loader.load_data_wrapper()
>>>importnetwork2>>>net=network2.Network([784,30,10]) >>>net.SGD(training_data,30,10,10.0,lmbda=1000.0,...evaluation_data=validation_data,monitor_evaluation_accuracy=True)
结果:
结果: Epoch 0 training complete Accuracy on evaluation data: 1030 / 10000
Epoch 1 training complete Accuracy on evaluation data: 990 / 10000
Epoch 2 training complete Accuracy on evaluation data: 1009 / 10000
差到跟随机猜测一样!
神经网络中可变化调整的因素很多:
神经网络结构::层数、每层神经元个数多少
初始化w和b的方法
Cost函数(目标定义的cost函数最小)
Regularization: L1、L2(减少overfitting的方式)
Sigmoid输出还是Softmax?
使用Droput?
训练集大小
mini-batch size()
学习率(learning rate):η
Regularization parameter:λ
总体策略:
从简单的出发:开始实验,循环的个数减小
如:MNIST数据集, 开始不知如何设置, 可以先简化使用0,1两类图, 减少80%数据量, 用两层神经网络[784, 2] (比[784, 30, 2]快),取得设置是否合理?
更快的获取反馈: 之前每个epoch来检测准确率, 可以替换为每1000个图之后,或者减少validation set的量, 比如用100代替10000
重复实验:
>>>net = network2.Network([784, 10])
>>>net.SGD(training_data[:1000], 30, 10, 10.0, lmbda = 1000.0, \ ... evaluation_data=validation_data[:100], \ ... monitor_evaluation_accuracy=True)
Epoch 0 training complete Accuracy on evaluation data: 10 / 100
Epoch 1 training complete Accuracy on evaluation data: 10 / 100
Epoch 2 training complete Accuracy on evaluation data: 10 / 100
更快得到反馈, 之前可能每轮要等10秒,现在不到1秒: λ之前设置为1000, 因为减少了训练集的数量, λ为了保证weight decay一样,对应的减少λ = 20.0
>>>net = network2.Network([784, 10])
>>>net.SGD(training_data[:1000], 30, 10, 10.0, lmbda = 20.0, \ ... evaluation_data=validation_data[:100], \ ... monitor_evaluation_accuracy=True)
结果:
Epoch0 training complete Accuracy one valuationdata:12/100
Epoch1 training complete Accuracy one valuationdata:14/100
Epoch2 training complete Accuracy one valuationdata:25/100
Epoch3 training complete Accuracy one valuationdata:18/100
也许学习率η=10.0太低? 应该更高?增大到100:
>>>net=network2.Network([784,10])
>>>net.SGD(training_data[:1000],30,10,100.0,lmbda=20.0,\...evaluation_data=validation_data[:100],\...monitor_evaluation_accuracy=True)
结果:
Epoch0 training complete Accuracy one valuationdata:10/100
Epoch1 training complete Accuracy one valuationdata:10/100
Epoch2 training complete Accuracy one valuationdata:10/100
Epoch3 training complete Accuracy one valuationdata:10/100
结果非常差, 也许结果学习率应该更低? =10
>>>net=network2.Network([784,10])
>>>net.SGD(training_data[:1000],30,10,1.0,lmbda=20.0,\...evaluation_data=validation_data[:100],\...monitor_evaluation_accuracy=True)
结果好很多:
Epoch0 training complete Accuracy one valuationdata:62/100
Epoch1 training complete Accuracy one valuationdata:42/100
Epoch2 training complete Accuracy one valuationdata:43/100
Epoch3 training complete Accuracy one valuationdata:61/100
假设保持其他参数不变: 30 epochs, mini-batch size: 10,λ=5.0
实验学习率=0.025, 0.25, 2.5
如果学习率太大,可能造成越走越高,跳过局部最低点 太小,学习可能太慢
对于学习率, 可以从0.001, 0.01, 0.1, 1, 10 开始尝试, 如果发现cost开始增大, 停止, 实验更小的微调 。
对于MNIST, 先找到0.1, 然后0.5, 然后0.25。
对于提前停止学习的条件设置, 如果accuracy在一段时间内变化很小 (不是一两次,5到10次变化很小)。
之前一直使用学习率是常数, 可以开始设置大一下, 后面逐渐减少: 比如开始设定常数, 直到在验证集上准确率开始下降, 减少学习率 (/2, /3)。
对于regularization parameterλ:
先不设定regularization, 把学习率调整好, 然后再开始实验λ, 1.0, 10, 100..., 找到合适的, 再微调。
对于mini-batch size:
太小: 没有充分利用矩阵计算的library和硬件的整合的快速计算。
太大: 更新权重和偏向不够频繁。
好在mini-batch size和其他参数变化相对独立, 所以不用重新尝试, 一旦选定。
自动搜索: 网格状搜索各种参数组合
(grid search) 2012**Random search for hyper-parameter optimization, by James Bergstra and Yoshua Bengio (2012). by James Bergstra and Yoshua Bengio 1998
paper**Efficient BackProp, by Yann LeCun, Léon Bottou, Genevieve Orr and Klaus-Robert Müller (1998) by Yann LeCun, Léon Bottou, Genevieve Orr and Klaus-Robert Müller.
参数之前会互相影响 如何选择合适的hyper-parameters仍是一个正在研究的课题,
随机梯度下降有没有其他变种: Hessian 优化, Momentum-based gradient descent
除了sigmoid,其他人工神经网络的模型?
tanh
tanh(w⋅x+b)
要靠实验比较rectified、linear和sigmoid,tanh的好坏,目前神经网络还有很多方面理论基础需要研究,为什么学习能力强,现在的一些实验表明结果比较好,但发展底层理论基础还有很长的路要走。
不一定,也可设置为[-1,1]之间。事实上,必须要有权值为负数,不然只有激活神经元,没有抑制的也不行。至于为什么在[-1,1]之间就足够了,这是因为归一化和Sigmoid函数输出区间限制这两个原因。一般在编程时,设置一个矩阵为bounds=ones(S,1)*[-1,1]%权值上下界。在MATLAB中,可以直接使用net = init(net)来初始化。我们可以通过设定网络参数net.initFcn和net.layer{i}.initFcn这一技巧来初始化一个给定的网络。net.initFcn用来决定整个网络的初始化函数。前馈网络的缺省值为initlay,它允许每一层用单独的初始化函数。设定了net.initFcn ,那么参数net.layer{i}.initFcn 也要设定用来决定每一层的初始化函数。对前馈网络来说,有两种不同的初始化方式经常被用到:initwb和initnw。initwb函数根据每一层自己的初始化参数(net.inputWeights{i,j}.initFcn)初始化权重矩阵和偏置。前馈网络的初始化权重通常设为rands,它使权重在-1到1之间随机取值。这种方式经常用在转换函数是线性函数时。initnw通常用于转换函数是曲线函数。它根据Nguyen和Widrow[NgWi90]为层产生初始权重和偏置值,使得每层神经元的活动区域能大致平坦的分布在输入空间。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)