Приблизительная двумерная поверхность с использованием scipy.minimize L_BFGS_B - PullRequest
0 голосов
/ 06 сентября 2018

Мне нужно восстановить высшее поле f(x,y) -> z из векторного поля g(x,y) -> (a,b,c), в соответствии с набором заданных уравнений, но у меня есть проблема для вычисления градиента (я использую L_BFGS_B, потому что я думаю, что это единственный оптимизатор, который позволит мне не взрывать память).

У меня следующий конфликт:

  • Изображения представляют собой двумерные массивы, градиент вычисляется вдоль каждой оси и требует двух значений на пиксель
  • Поле высоты имеет только 1 переменную на пиксель (высоту)

Поэтому, после вычисления градиента, Сципи жалуется, что функция не может возвращать в качестве градиента массив с (img_x * img_y, 2) формой. Только 1D фигура с точно таким же количеством, что и массив полей высоты.

Я что-то упускаю здесь очевидное?

Подробная задача

Я определяю три переменные nx, ny, nz:

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
  • В противном случае, что я должен вернуть для моего градиента? или я вычисляю это правильно?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...