使用scipy近似2d表面。最小化L_BFGS_B

时间:2018-09-06 10:28:02

标签: python scipy

我需要根据一组给定方程从向量场f(x,y) -> z重构一个高场g(x,y) -> (a,b,c),但是我在计算梯度时遇到了一个问题(我使用L_BFGS_B是因为我认为唯一允许我不爆炸内存的优化程序。

我遇到以下冲突:

  • 图像是二维数组,沿每个轴计算梯度,每个像素需要两个值
  • 高度场每个像素(高度)只有1个变量

因此,在计算梯度之后,scipy抱怨该函数无法将梯度为(img_x * img_y,2)的数组作为梯度返回。只有一维形状与高度字段数组的计数完全相同。

我在这里缺少明显的东西吗?

详细问题

我定义了三个变量nxnynz

nx = g(x,y).x
ny = g(x,y).y
nz = g(x,y).z

现在,对于网格的每个点(x,y),我需要根据以下公式计算点(f(x,y))的高度:

nz * [f(x+1, y) - f(x,y)] == nx
nz * [f(x, y+1) - f(x,y)] == ny

我尝试用损失函数表达这一点:

class Eval():
    def __init__(self, g):
        '''
        g: (x, y, 3)
        '''
        self.g = g

    def loss(self, x):
        depth = x.reshape(self.g.shape[:2])

        x_roll = np.roll(depth, -1, axis=0)
        y_roll = np.roll(depth, -1, axis=1)

        dx = depth - x_roll
        dy = depth - y_roll

        nx = self.g[:,:,0]
        ny = self.g[:,:,1]
        nz = self.g[:,:,2]

        loss_x = nz * dx - nx
        loss_y = nz * dy - ny

        self.error_loss = np.stack([loss_x, loss_y], axis=-1)

        total_loss = norm(self.error_loss, axis=-1)

        return np.sum(total_loss)

def grads(self, x):
    x_roll = np.roll(self.error_loss[:,:,0], -1, axis=0)
    y_roll = np.roll(self.error_loss[:,:,1], -1, axis=1)

    dx = self.error_loss[:,:,0] - x_roll
    dy = self.error_loss[:,:,1] - y_roll

    g_xy = np.stack([dx, dy], axis=-1)

    # g_xy has shape (x, y, 2)
    # BUT THIS MUST RETURN (x * y), not (x * y, 2) nor (x * y * 2)
    # WHAT SHOULD I RETURN HERE ? ||g_xy|| ?

并这样称呼

vector_field = ... # shape: 1024, 1024, 3
x0 = np.random.uniform(size=vector_field.shape[:2])
ev = Eval(vector_field)
result = optim.fmin_l_bfgs_b(ev.loss, x0, fprime=ev.grads)

问题

  • 是否有一种表达这些方程的方法,可以用另一种方法求解?从理论上讲,它们是过度约束的线性系统,可以用最小二乘法求解,但是我找不到如何重新构建Ax = b
  • 形式的方程式的方法。
  • 否则,我应该为梯度返回什么?还是我计算正确?

0 个答案:

没有答案