为何np.gradient计算的二维梯度与解析梯度结果不符?
问题:np.gradient计算二维梯度方向不符合预期
我尝试用np.gradient在二维平面上计算梯度,但结果不符合预期。选用解析函数测试:
z = f(x,y) = -(x - 2)**2 - (y - 2)**2
该函数的梯度向量本应指向中心(2,2),但np.gradient给出的结果方向不对。以下是运行代码:
import numpy as np import matplotlib.pyplot as plt # Define the grids for x and y x = np.linspace(0, 4, 100) # 100 points between 0 and 4 y = np.linspace(0, 4, 100) # 100 points between 0 and 4 X, Y = np.meshgrid(x, y) # Create a 2D grid # Define the function f(x, y) Z = -(X - 2)**2 - (Y - 2)**2 # Compute gradients numerically dz_dx, dz_dy = np.gradient(Z, x, y) # Downsampling to reduce the density of arrows step = 10 plt.figure(figsize=(10, 8)) contour = plt.contourf(X, Y, Z, cmap='viridis', levels=50, alpha=0.8) plt.colorbar(contour, label='f(x, y)') plt.quiver(X[::step, ::step], Y[::step, ::step], dz_dx[::step, ::step], dz_dy[::step, ::step], color='r', headlength=3, headwidth=4) plt.title('Function $f(x, y) = -(x - 2)^2 - (y - 2)^2$ and its gradients (numerical)') plt.xlabel('x') plt.ylabel('y') plt.grid(True) plt.show()
分析与解决
问题出在梯度计算的轴顺序与网格维度不匹配:
- 网格维度对应关系
np.meshgrid(x, y)默认使用indexing='xy',生成的X和Y满足:
X[i,j] = x[j]:轴1(列方向)对应x的变化Y[i,j] = y[i]:轴0(行方向)对应y的变化
- np.gradient的返回顺序
对于二维数组Z,np.gradient(Z, spacing0, spacing1)返回的两个数组分别是:
- 第一个数组:沿轴0(y方向)的梯度,即
dz/dy - 第二个数组:沿轴1(x方向)的梯度,即
dz/dx
你当前代码中错误地将返回值顺序赋值为dz_dx, dz_dy,同时spacing参数的顺序也搞反了(应该先传y的spacing,再传x的spacing)。
修正后的代码
import numpy as np import matplotlib.pyplot as plt x = np.linspace(0, 4, 100) y = np.linspace(0, 4, 100) X, Y = np.meshgrid(x, y) Z = -(X - 2)**2 - (Y - 2)**2 # 修正梯度计算的顺序:先轴0(y)的spacing,再轴1(x)的spacing,返回dz_dy, dz_dx dz_dy, dz_dx = np.gradient(Z, y, x) step = 10 plt.figure(figsize=(10, 8)) contour = plt.contourf(X, Y, Z, cmap='viridis', levels=50, alpha=0.8) plt.colorbar(contour, label='f(x, y)') # quiver中使用正确的dz_dx(x方向梯度)和dz_dy(y方向梯度) plt.quiver(X[::step, ::step], Y[::step, ::step], dz_dx[::step, ::step], dz_dy[::step, ::step], color='r', headlength=3, headwidth=4) plt.title('Function $f(x, y) = -(x - 2)^2 - (y - 2)^2$ and its gradients (corrected)') plt.xlabel('x') plt.ylabel('y') plt.grid(True) plt.show()
验证解析解
该函数的解析梯度为:
- $\frac{\partial f}{\partial x} = -2(x-2)$
- $\frac{\partial f}{\partial y} = -2(y-2)$
修正后的数值梯度会与解析解一致,箭头将正确指向中心(2,2)。
内容的提问来源于stack exchange,提问作者rthgtr Gaehgq
相关产品推荐
相关产品推荐

