【问题标题】:Keras fails to find solution to linear convex problemKeras 无法找到线性凸问题的解决方案
【发布时间】:2021-01-29 19:33:40
【问题描述】:

我编写了这个可重现代码来演示这个问题:

import numpy as np
import keras
import tensorflow as tf

n, d = 2, 3
A = np.random.random((n, d))
b = np.random.random((n, 1))
x = np.linalg.lstsq(A, b, rcond=None)[0]
print("Numpy MSE is {}".format((np.linalg.norm(A @ x - b) ** 2) / n))

model = keras.models.Sequential()
model.add(keras.layers.Dense(1, use_bias=False, activation='linear'))
opt = tf.keras.optimizers.SGD(learning_rate=0.01, momentum=0, nesterov=False)
model.compile(loss="mse", optimizer=opt)
model.fit(A, b, batch_size=A.shape[0], epochs=10000, verbose=0)
x = model.layers[0].get_weights()[0]
print("Keras MSE is {}".format((np.linalg.norm(A @ x - b) ** 2) / n))

基本上,我以两种方式求解欠定线性方程组Ax=b,一次使用 numpy,一次使用 keras 标准梯度下降。

当我运行它时,我得到这个输出:

Numpy MSE is 6.162975822039155e-33
Keras MSE is 1.3108133821545518e-10

numpy 产生了更好的结果,但我仍然愿意接受 keras 作为解决方案,10^(-10) 相当小。

现在将 n 增加到 200,将 d 增加到 300。 现在的输出是:

Numpy MSE is 1.4348640308871558e-30
Keras MSE is 0.0001953624326696054

现在不仅numpy好很多,而且就我而言,keras没有找到解决方案。我们得到的结果还不够接近于零,我被卡住了。改变学习率或增加迭代不会显着改变结果。为什么会这样?

我知道有一个解决方案。对于大尺寸数据,例如 n = 200 d = 300 的情况,我希望误差最多为 10^(-10),使用 keras

TLDR:我拼命想过度拟合。我知道有一个解决方案可以让我零损失。我的问题是线性和凸的,经典的欠定系统,keras 找不到那个解决方案,给我 0 训练损失。

【问题讨论】:

  • 致以基于意见(也可能被否决)和审阅者投票结束此问题的人:这是一个完全合法的编码问题,具有完全可重现示例(如今很少见),并且其中没有任何基于意见的内容。
  • 与您的问题无关,但将独立的kerastf.keras 混合使用不是一个好主意;我建议您删除 import keras 并将代码中的 keras 替换为 tf.keras
  • 我没有投票给任何东西,但我想知道这个问题是不是比较苹果和橘子?我不知道np.linalg.lstsq 如何计算其解决方案,但我在文档中找不到对梯度下降的参考。因此,将其与带有 SGD 的 Keras 进行比较是不公平的。至少,应该使用衰减的学习率计划来(理论上)保证收敛。此外,问题应包括生成数据的特定随机种子——事实上,desertnauts 更好的结果可能仅仅是由于机会。
  • @xdurch0 随机种子的公平点,但是即使没有它,也可以多次复制提供的代码,我得到的结果与报告的结果非常相似。我建议的解决方案始终如一地改变了这一点,即使是多次运行。 np.linalg.lstsq 很可能不使用 SGD,但我原则上理解 Keras 不应该在这里表​​现那么糟糕的期望。

标签: python numpy keras linear-regression


【解决方案1】:

您在层定义中缺少input_shape 参数。不太清楚为什么没有定义 input_shape 就不能工作(权重的形状似乎还可以);但是,根据documentation

一般来说,如果您知道顺序模型的输入形状是什么,建议您始终提前指定输入形状。

另一件事是,通过设置batch_size=A.shape[0],你实际上是在使用batch梯度下降,而不是stochastic;为了使用 SGD,您需要设置一个小于数据样本大小的batch_size

因此,在高维情况下对代码进行以下更改(加上将所有 keras 使用替换为 tf.keras,因为将两者混合不是一个好习惯):

# n, d = 200, 300

model.add(tf.keras.layers.Dense(1, input_shape=(A.shape[1],), use_bias=False, activation='linear'))

model.fit(A, b, batch_size=32, epochs=10000, verbose=0)

10,000 epochs 后,结果是:

Keras MSE is 1.9258555439788135e-10

在迭代 10,000 多个 epoch(即总共 20,000 个)时,我们得到:

Keras MSE is 1.2521153241468356e-13

重复运行,我们得到质量相似(但当然不相同)的结果。

【讨论】:

  • 你确定你没有做任何其他事情吗?我仍然得到不好的结果。
  • @OriaGruber 你是对的-我很抱歉:(。我也使用了batch_size=32(加上提到的更改keras->tf.keras)。我正在更新答案...跨度>
  • 但这改变了算法。这现在不再是“香草”梯度下降。这很好,但对我不是很有帮助,因为我正在研究处理常规 GD 的定理,而不是任何随机的。
  • @OriaGruber 不确定您所说的“香草”是什么意思,因为实际使用的是 SGD;但无论如何,如果它没有真正解决您的问题,请随时不接受答案,从而保持开放并邀请其他想法(我承认这种 Keras 行为非常奇怪,并且您最好将此作为可能的问题发布到 Keras/Tensorflow 存储库)。
  • 香草我的意思是 x = x - learning_rate * df/dx。最陡的下降。我知道它在实践中并不经常使用。我将保留此答案为已接受。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-31
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-13
相关资源
最近更新 更多