gpt4 book ai didi

python - 通过 3D 表面绘制 2D 平面

转载 作者:太空狗 更新时间:2023-10-29 21:36:07 25 4
gpt4 key购买 nike

我正在尝试使用 Numpy 和 Matplotlib 可视化 2D 平面切割 3D 图形,以解释偏导数的直觉。

具体来说,我使用的函数是 J(θ1,θ2) = θ1^2 + θ2^2,我想在 θ2=0 处绘制一个 θ1-J(θ1,θ2) 平面。

我已经设法用下面的代码绘制了一个 2D 平面,但是 2D 平面和 3D 图形的叠加不太正确,2D 平面稍微偏离了,因为我希望平面看起来像是在切割θ2=0 时的 3D。

如果我能借用您在这方面的专业知识,那就太好了,谢谢。

    def f(theta1, theta2):
return theta1**2 + theta2**2

fig, ax = plt.subplots(figsize=(6, 6),
subplot_kw={'projection': '3d'})

x,z = np.meshgrid(np.linspace(-1,1,100), np.linspace(0,2,100))
X = x.T
Z = z.T
Y = 0 * np.ones((100, 100))
ax.plot_surface(X, Y, Z)

r = np.linspace(-1,1,100)
theta1_grid, theta2_grid = np.meshgrid(r,r)
J_grid = f(theta1_grid, theta2_grid)
ax.contour3D(theta1_grid,theta2_grid,J_grid,500,cmap='binary')

ax.set_xlabel(r'$\theta_1$',fontsize='large')
ax.set_ylabel(r'$\theta_2$',fontsize='large')
ax.set_zlabel(r'$J(\theta_1,\theta_2)$',fontsize='large')
ax.set_title(r'Fig.2 $J(\theta_1,\theta_2)=(\theta_1^2+\theta_2^2)$',fontsize='x-large')

plt.tight_layout()
plt.show()

这是代码输出的图片:

plot showing a parabolic surface with a vertical plane weirdly superimposed on it

最佳答案

作为@ImportanceOfBeingErnest noted in a comment ,你的代码很好,但 matplotlib 有一个 2d 引擎,所以 3d 图很容易显示奇怪的工件。特别是,一次渲染一个对象,因此两个 3d 对象通常要么完全在另一个前面,要么完全在另一个后面,这使得使用 matplotlib 几乎不可能可视化互锁的 3d 对象。

我个人的替代建议是 mayavi (令人难以置信的灵 active 和可视化,非常陡峭的学习曲线),但是我想展示一个通常可以完全消除问题的技巧。这个想法是使用表面之间的无形桥梁将两个独立的对象变成一个单独的对象。该方法的可能缺点是

  1. 您需要将两个表面绘制为表面而不是 contour3D,并且
  2. 输出在很大程度上依赖于透明度,因此您需要一个可以处理该问题的后端。

免责声明:我从 now-defunct Stack Overflow Documentation project 的 matplotlib 主题的贡献者那里学到了这个技巧。 ,但不幸的是,我不记得那个用户是谁。

为了将此技巧用于您的用例,我们基本上必须将 contour3D 调用转换为另一个 plot_surface 调用。我不认为这总体上有那么糟糕;如果您发现生成的图形有太多交互使用的面,您可能需要重新考虑切割平面的密度。我们还必须明确定义逐点颜色图,其 Alpha channel 有助于在两个表面之间建立透明的桥梁。由于我们需要将两个表面缝合在一起,因此表面的至少一个“平面内”维度必须匹配;在这种情况下,我确保沿“y”的点在这两种情况下是相同的。

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

def f(theta1, theta2):
return theta1**2 + theta2**2

fig, ax = plt.subplots(figsize=(6, 6),
subplot_kw={'projection': '3d'})

# plane data: X, Y, Z, C (first three shaped (nx,ny), last one shaped (nx,ny,4))
x,z = np.meshgrid(np.linspace(-1,1,100), np.linspace(0,2,100)) # <-- you can probably reduce these sizes
X = x.T
Z = z.T
Y = 0 * np.ones((100, 100))
# colormap for the plane: need shape (nx,ny,4) for RGBA values
C = np.full(X.shape + (4,), [0,0,0.5,1]) # dark blue plane, fully opaque

# surface data: theta1_grid, theta2_grid, J_grid, CJ (shaped (nx',ny) or (nx',ny,4))
r = np.linspace(-1,1,X.shape[1]) # <-- we are going to stitch the surface along the y dimension, sizes have to match
theta1_grid, theta2_grid = np.meshgrid(r,r)
J_grid = f(theta1_grid, theta2_grid)
# colormap for the surface; scale data to between 0 and 1 for scaling
CJ = plt.get_cmap('binary')((J_grid - J_grid.min())/J_grid.ptp())

# construct a common dataset with an invisible bridge, shape (2,ny) or (2,ny,4)
X_bridge = np.vstack([X[-1,:],theta1_grid[0,:]])
Y_bridge = np.vstack([Y[-1,:],theta2_grid[0,:]])
Z_bridge = np.vstack([Z[-1,:],J_grid[0,:]])
C_bridge = np.full(Z_bridge.shape + (4,), [1,1,1,0]) # 0 opacity == transparent; probably needs a backend that supports transparency!

# join the datasets
X_surf = np.vstack([X,X_bridge,theta1_grid])
Y_surf = np.vstack([Y,Y_bridge,theta2_grid])
Z_surf = np.vstack([Z,Z_bridge,J_grid])
C_surf = np.vstack([C,C_bridge,CJ])

# plot the joint datasets as a single surface, pass colors explicitly, set strides to 1
ax.plot_surface(X_surf, Y_surf, Z_surf, facecolors=C_surf, rstride=1, cstride=1)

ax.set_xlabel(r'$\theta_1$',fontsize='large')
ax.set_ylabel(r'$\theta_2$',fontsize='large')
ax.set_zlabel(r'$J(\theta_1,\theta_2)$',fontsize='large')
ax.set_title(r'Fig.2 $J(\theta_1,\theta_2)=(\theta_1^2+\theta_2^2)$',fontsize='x-large')

plt.tight_layout()
plt.show()

两个角度的结果:

result 1, default view; all's fine and well result 2; still all's fine and well

如您所见,结果相当不错。您可以开始尝试使用表面的各个透明度,看看是否可以使该横截面更加可见。您还可以将桥的不透明度切换为 1,以查看您的表面实际上是如何缝合在一起的。总而言之,我们要做的就是获取您现有的数据,确保它们的大小匹配,并定义明确的颜色图和表面之间的辅助桥接。

关于python - 通过 3D 表面绘制 2D 平面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47835726/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com