我正在使用Keras进行线性回归。我的数据集由50个1D输入点和50个1D输出点组成。为了执行线性回归,我正在训练具有单层和单个神经元的神经网络,没有激活功能。神经网络定义为
model = Sequential()
model.add(Dense(1, input_dim=1, kernel_initializer='zeros',
bias_initializer='zeros'))
我要求Keras找到w和b的最佳值,使用SGD作为优化器,将均方误差作为损失函数。
model.compile(loss='mean_squared_error', optimizer=SGD(lr=0.01))
model.fit(x,y,epochs=100, callbacks=[history], verbose=0, batch_size=50);
其中history
是我创建的回调,用于在优化的每一步保存当前的权重和偏差。
然后我继续绘制损失函数的水平曲线,以及w
x b
空间中的优化轨迹。输出如下。
优化轨迹以红色圆圈显示,全局最优值显示为蓝色“x”。这似乎是合理的,因为我们从[0,0]
开始,并且在每次迭代之后我们接近全局最优。最终,渐变开始变得如此之小,以至于我们停止改进。
然而,我知道通过使用梯度下降,人们总是会在当前点(即垂直于水平曲线)的渐变方向上移动。这种优化轨迹似乎并不像那样。 Keras SGD
优化器是否正在做其他事情?或者我错过了什么?
编辑: 尽管该图似乎说明了水平曲线是平行线,但它们实际上是椭圆体,但非常细长。选择不同的范围来绘制它们会显示出来。
编辑2: 为了避免与我如何绘制此问题中显示的图像有任何混淆,我现在创建了一个gist with the code。
答案 0 :(得分:2)
您必须记住,您使用的SGD
是Stochastic Gradient Descent
。在下图中可以看到使用SGD
与香草GD
进行比较后得到的轨迹差异的可视化:
(source)
您可以看到SGD
轨迹与水平线不垂直,但移动方式不同。也许这已经在解释你的轨迹形式了。
答案 1 :(得分:1)
首先,您应该意识到,由于您没有使用激活函数,您的神经网络只能表示线性系统(相当于矩阵乘法)。非线性激活函数带来了神经网络的代表性能力。
您实际上没有执行线性回归。如果要这样做,例如使用2次多项式,则应将平方参数作为输入添加。由于http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.PolynomialFeatures.html
,Scikit-learn提供了这种转换假设您具有两个输入x和y的函数,执行线性回归,就像您使用具有x, x^2, xy, y, y^2
和一个输出神经元的输入层一样。
编辑: 但是,在(w,b)空间中,您实际上应该能够达到全局最小值。但是,没有关于收敛速度的结果。如果你看一下你的损失函数,你可以注意到它在一个方向上被拉伸很多:它相当于说Hessian矩阵有两个具有非常不同大小的特征值。这意味着你将能够在一个方向(最大的eingenvalues之一)快速学习,但在另一个方向慢慢学习。
在神经网络优化中,计算Hessian矩阵是不可能的,因为它需要在每个步骤进行许多计算。然而,一些学习算法能够逃脱鞍点和严重条件(如你的)优化问题。 SGD表现不佳,几乎不再使用。看看http://ruder.io/optimizing-gradient-descent/,知道所有这些优化器都包含在Keras中。对你来说,我会首先尝试增加动力以提高收敛速度,正如你所说,如果等待足够长时间,它实际上可以收敛。
答案 2 :(得分:1)
打扰一下,如果你已经考虑到这一点,我就看不出你是如何创建图表的。
渐变取决于输入数据。
神经元具有公式w.x + b
,其中x是输入。
w和b函数的梯度为:(x,1)。
因此,它取决于输入。
但也不要忘记渐变也会受到损失函数的影响,在你的情况下,这些差异会影响差异。
要查看关卡曲线,您必须应用连锁规则。
Loss = [(wx + b) - y]^2
所以你的渐变是:
W: 2.[(wx + b) - y].x
B: 2.[(wx + b) - y].1
答案 3 :(得分:1)
是正交(0.2 vs -5斜率),但图表的x / y单位不相同。在给定方向上缩放不会保持正交性。