Python LBFGS在pytorch中永远不会在大维度上收敛

Python LBFGS在pytorch中永远不会在大维度上收敛,python,tensorflow,pytorch,nonlinear-optimization,Python,Tensorflow,Pytorch,Nonlinear Optimization,我在玩Wolfram细胞自动机的110规则。给定一行0和1,您可以使用以下规则计算下一行: 从00000000…1开始,最后得到以下序列: 出于好奇,我决定用多项式近似这些规则,这样单元格不仅可以是0和1,还可以是介于0和1之间的灰色: def triangle(x,y,z,v0): v=(y + y * y + y * y * y - 3. * (1. + x) * y * z + z * (1. + z + z * z)) / 3. return (v-v0)*(v-v0

我在玩Wolfram细胞自动机的110规则。给定一行0和1,您可以使用以下规则计算下一行:

从00000000…1开始,最后得到以下序列:

出于好奇,我决定用多项式近似这些规则,这样单元格不仅可以是0和1,还可以是介于0和1之间的灰色:

def triangle(x,y,z,v0):
    v=(y + y * y + y * y * y - 3. * (1. + x) * y * z + z * (1. + z + z * z)) / 3.
    return (v-v0)*(v-v0)
因此,如果x、y、z和v0与表中的任何规则匹配,它将返回0,否则返回正的非零值

接下来,我将所有可能的4个邻居组添加到单和中,对于整数解,这将是零:

def eval():
    s = 0.
    for i in range(W - 1):
        for j in range(1, W + 1):
            xx = x[i, (j - 1) % W]
            yy = x[i, j % W]
            zz = x[i, (j + 1) % W]
            r = x[i + 1, j % W]
            s += triangle(xx, yy, zz, r)
    for j in range(W - 1): s += x[0, j] * x[0, j]
    s += (1 - x[0, W - 1]) * (1 - x[0, W - 1])
    return torch.sqrt(s)
同样在这个函数的底部,我为第一行添加了普通条件,这样除了最后一个元素是1外,所有元素都是0。最后,我决定用pytorch最小化W*W矩阵上的平方和:

x = Variable(torch.DoubleTensor(W,W).zero_(), requires_grad=True)
opt = torch.optim.LBFGS([x],lr=.1)
for i in range(15500):
    def closure():
        opt.zero_grad()
        s=eval()
        s.backward()
        return s
    opt.step(closure)
这是,你可以自己试试。问题在于,对于10*10,它会在大约20个步骤中收敛到正确的解:

但如果我用15*15板,它永远不会完成收敛:

右边的图表显示了平方和在每次迭代中是如何变化的,你可以看到它永远不会达到零。我的问题是为什么会发生这种情况,以及我如何解决这种情况。尝试了不同的Pytork优化程序,但所有这些程序的性能都不如LBFGS。尝试不同的学习速度。您知道为什么会发生这种情况,以及如何在优化过程中达到最终点吗

UPD:改进的收敛图,SOS日志:

UPD2:我也尝试过用DLIB在C++中做同样的事情,而且我没有任何收敛性的问题,它在时间上要深得多:

我使用此代码在C++中进行优化:

find_min_using_approximate_derivatives(bfgs_search_strategy(),
        objective_delta_stop_strategy(1e-87),
        s, x, -1)

你们要做的是非凸优化,这是一个众所周知的难题。一旦你想一想,它是有意义的,因为几乎任何实际的数学问题都可以表述为优化问题

1。前奏曲
所以,在给你们一些提示,告诉你们在哪里可以找到解决你们特定问题的方法之前,我想解释一下为什么某些优化问题很容易解决

我将从讨论凸问题开始。即使在受约束的情况下,这些问题也很容易解决,原因是当你计算梯度时,你实际上得到了很多关于最小值不可能存在的信息(凸函数f的泰勒展开总是低估了f),此外,只有一个最小值,没有萨德尔点。如果你有兴趣学习更多关于凸优化的知识,我建议你去看斯蒂芬·博伊德的《凸优化》课程

现在,如果非凸优化如此困难,我们怎么能在深入学习中解决它呢?答案很简单,我们在深度学习中最小化的非凸函数非常好,如所示

因此,机器学习实践者必须意识到,深度学习中使用的操作程序很可能不会在其他非凸问题上产生一个好的最小值,如果它们首先收敛到最小值

2。回答您的问题
现在来回答你们的问题,你们可能不会找到快速的解决方案,因为非凸优化是NP完全的。但不用担心,SciPy有一些全局优化算法可供选择。是指向另一个堆栈溢出线程的链接,它很好地回答了您的问题

3。故事的寓意
最后,我想提醒大家,收敛保证很重要,忘记了它导致了一个错误

PS.请原谅我的打字错误,我正在用我的手机处理这个问题


更新:至于BFGS为什么与dlib一起工作,可能有两个原因,第一,BFGS比L-BFGS更善于使用曲率信息,第二,它使用直线搜索来找到最佳步长。我建议检查PyTorch是否允许行搜索,如果不允许,则设置一个减小的步长(或者只设置一个非常小的步长)。

这不是一个凸问题,因此对于L-BFGS没有任何收敛保证。好吧,但我能做些什么呢?PyTorch中的BFGS不实现线性搜索,而SciPy中实现了线性搜索,如果使用Numpy:)重写代码,应该可以让它正常工作