调试什么:
学习率α是最重要的、最需要调节的超参数;其次是Momentum的β、隐藏单元和batch size;应用Adam算法时,一般不调节他的几个参数。
如何调试:
早期使用网格图枚举超参数组合,但不同超参数的重要性不同,并不应该如此枚举。我们可以随机选择点来测试。
策略:从粗糙到精细,即依据好结果出现的位置不断缩小搜索范围
层数、每层单元数:
数轴上你需要的范围均匀取值
学习率α:
记为10^r,让r在数轴上你需要的范围均匀取值
β:
如果需要在类似0.9-0.999的范围搜索,让r在数轴上你需要的范围均匀取值,结果取1-10^r
两种搜索合适超参数的方式:
第一,计算资源不够,无法同时试验大量模型的情况。人们观察模型一段时间的表现,根据表现调整超参数,继续观察-调整。
第二,计算资源足够。人们同时试验大量模型,观察他们的学习曲线,直接选择最好的那一个。
第一种就叫Pandas(熊猫),第二种叫Caviar(鱼子酱)
Batch归一化(Batch Norm):
归一化a来获取更好的效果,实际上归一化的是z。
具体过程如下(这里省略了层数的上标[l]):
这时,每一个分量都有了均值0和方差1,但也许隐藏单元有不同分布会有意义,因此我们再处理:
γ和β是可以调整的参数,在梯度下降类的算法中,也会在每次迭代中更新。
通过这两个参数,显然我们可以随意调整每一层中z的均值、方差。
应用上一节的算法即可。
注意这里的β们和之前Adam等算法的β没有关系。
应用时我们会发现,无论z=wx+b中b是多少,事实上归一化中都会被消去,因此如果使用Batch Norm,我们可以取消b这个参数
另外β^[l]和γ^[l]的维数都是(n^[l],1),对应每一层的每个单元其实都有不同的值
第一,类似对x的归一化,它可以加速学习
第二,在你训练网络的过程中,数据的分布可能改变了,这使得你需要重新训练网络,称为“Covariate shift”。体现在神经网络中,就是说前层的参数w和b会影响后层的a。
而Batch Norm归一化了方差和均值,一定程度上减弱这些影响,使各层显得更稳定,而且更加独立,这利于加速整体学习。
第三,Batch Norm有轻微的正则化效果。类似dropout,其调整过程给数据增加了噪声。迫使后层的单元对前层单元的依赖减小。你可以将它和dropout一起使用来获得更强的正则化效果。这里提到一个性质,更大的mini-batch会减弱dropout的效果。
最后,注意Batch Norm一次只能处理一个mini-batch。
你可能无法同时处理整个mini-batch的所有样本,因此需要用其他方法来获得μ和σ^2:指数加权平均数
你逐一处理每个mini-batch内的所有样本,每处理一个mini-batch,你将得到一个μ和σ^2,利用指数加权平均数来平均已经处理过的mini-batch的μ和σ^2,最后得到对于已经处理的所有mini-batch的μ和σ^2,利用它来进行最后的归一化。
这是logistic回归的一般形式,用来处理多分类问题。
对应的神经网络中,其输出层有C个,表示需要把数据分成C类,输出值代表数据属于某一类的概率,其和应当为1,最大的那个就是你需要的类别对应的概率。
最后一层之前的处理与之前的神经网络没有很大不同,但最后一层要使用softmax激活函数:
注意这里t的维数是C*1
a的维数也是C*1,代表数据属于每一类的概率
hardmax:
区别于softmax,会把z的最大分量变为1,其他的变为0,再处理
损失函数:
在多分类问题的标记y中,只有表示正确的分类的那个分量是1,其他都是0,整个Y矩阵是C*m的
那么要最小化损失函数,实际上就是最大化正确分类的那个log项,即最大化那个yhat。
对大多数人而言,从零开始实现所有算法不现实,因此我们需要框架。
选择标准:便于编程、运行速度、是否真的开放
导入需要的包:
import numpy as np
import tensorflow as tf
定义参数w:
w = tf.Variable(0,dtype = tf.float32)
定义损失函数:
cost=tf.add(tf.add(w**2,tf.multiply(-10.,w)),25)
梯度下降法(学习率0.01):
train = tf.train.GradientDescentOptimizer(0.01).minimize(cost)
惯用表达式:
init = tf.global_variables_initializer()
# get a TensorFlow session
session = tf.Session()
# initialize global variables
session.run(init)
让TensorFlow评估一个变量:
session.run(w)
上面的这一行将 w 初始化为 0,并定义损失函数,如果用print输出,会得到0
运行梯度下降:
for i in range(1000):
session.run(train)
事实上,tensorflow重载了运算符,下面两种写法等价:
cost=tf.add(tf.add(w**2,tf.multiply(-10.,w)),25)
cost=w**2-10*w+25
把训练数据加入程序,即告诉程序先把place给hold一下,稍后提供数值:
x = tf.placeholder(tf.float32,[3,1])
我们这里把之前函数的系数变成数据:
cost = x[0][0]*w**2 +x[1][0]*w + x[2][0]
定义一个数组存x:
coefficient = np.array([[1.],[-10.],[25.]])
提供给x:
feed_dict = {x:coefficients}
做一个整理:
session=tf.Session():
session.run(init)
print(session.run(w))
#changed to
with tf.Session() as session:
session.run(init)
print(session.run(w))
Adam优化器等也可以简单实现