我需要根据一组给定方程从向量场f(x,y) -> z
重构一个高场g(x,y) -> (a,b,c)
,但是我在计算梯度时遇到了一个问题(我使用L_BFGS_B是因为我认为唯一允许我不爆炸内存的优化程序。
我遇到以下冲突:
因此,在计算梯度之后,scipy抱怨该函数无法将梯度为(img_x * img_y,2)的数组作为梯度返回。只有一维形状与高度字段数组的计数完全相同。
我在这里缺少明显的东西吗?
我定义了三个变量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