我希望能够看到表面顶部(第二张图像)上的3D表面上的线条(和点),而不是后面(第一张图像)。 这是我的3D功能:
def f(x, y):
return np.sin(2*x) * np.cos(2*y)
3D表面的X,Y,Z:
x = np.linspace(-2, 2, 100)
y = np.linspace(-2, 2, 100)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
我生成了x点(xx)和y点(yy)的向量,其中zz = f(xx,yy)
fig = plt.figure(figsize=(8,6))
ax = plt.axes(projection='3d')
ax.scatter(xx, yy, zz, c='r', marker='o')
#ax.plot(xx,yy,zz, c= 'r')
ax.plot_surface(X, Y, Z, rstride=1, cstride=1,
cmap='viridis', edgecolor='none')
正如你所看到的,这些点是在情节的后面,这个数字涵盖了各点。我想看看情节上的分数。我该怎么办?
我希望能够看到像这样的点和线:
编辑: 这就是我生成积分的方式:
for i in range(1,2000):
[a, b] = np.random.rand(2,1)*np.sign(np.random.randn(2,1))*2
xx = np.append(xx, a)
yy = np.append(yy, b)
我注意到如果我写zz = f(xx,yy) + epsilon
,我可以看到这些点。如果是epsilon = 0
,那么这些点在数学上就在表面上,我无法清楚地看到它们,就像在第一张图像中一样。如果epsilon > 0.05
,我可以看到这些点,但这意味着将点数移到上方。我真的不喜欢这个解决方案。如果一个点在表面上,表面具有优先权,则表面看起来超过该点。我希望我的图形能够反过来。
答案 0 :(得分:1)
首先让我说你想要的东西有些不明确。您希望以一种始终在图中显示的方式在底层曲面上绘制完全的点,即正好在曲面上方,而不是明确地将它们向上移动。这已经成为一个问题,因为
然而,最大的问题是,当涉及绘制图中的多个或复杂对象时,matplotlib中的3d绘图是known to be unreliable。特别是,渲染器本质上是2d,并且在试图找出对象的相对明显位置时经常遇到问题。要克服此问题,可以尝试使用hacking around the problem,或使用合适的3D渲染器切换到mayavi
之类的内容。
不幸的是,zorder
可选关键字参数通常被3d轴对象忽略。所以我在pyplot中唯一可以提出的就是你几乎拥有的东西,注释掉:使用ax.plot
而不是ax.scatter
。虽然后者产生了第一个图中显示的图(由于某种原因隐藏了每个散点,无论视角如何),前者会导致第二个图中显示的图(点可见的位置)。通过从绘图样式中删除线条,我们几乎得到你想要的东西:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def f(x, y):
return np.sin(2*x) * np.cos(2*y)
# data for the surface
x = np.linspace(-2, 2, 100)
X, Y = np.meshgrid(x, x)
Z = f(X, Y)
# data for the scatter
xx = 4*np.random.rand(1000) - 2
yy = 4*np.random.rand(1000) - 2
zz = f(xx,yy)
fig = plt.figure(figsize=(8,6))
ax = plt.axes(projection='3d')
#ax.scatter(xx, yy, zz, c='r', marker='o')
ax.plot(xx, yy, zz, 'ro', alpha=0.5) # note the 'ro' (no '-') and the alpha
ax.plot_surface(X, Y, Z, rstride=1, cstride=1,
cmap='viridis', edgecolor='none')
但并不完全:很明显,在这种情况下,点总是可见,即使它们应隐藏在表面的一部分后面:
# note the change in points: generate only in the "back" quadrant
xx = 2*np.random.rand(1000) - 2
yy = 2*np.random.rand(1000)
zz = f(xx,yy)
fig = plt.figure(figsize=(8,6))
ax = plt.axes(projection='3d')
ax.plot(xx,yy,zz, 'ro', alpha=0.5)
ax.plot_surface(X, Y, Z, rstride=1, cstride=1,
cmap='viridis', edgecolor='none')
很容易看出前面的凹凸应该隐藏背景中的大块点,但这些点是可见的。这正是pyplot在复杂的三维可视化中遇到的问题。因此,我的底线是你无法使用matplotlib可靠地做你想做的事。对于它的价值,我不确定无论如何这样的情节是多么容易理解。
最后以更积极的方式结束,这里是如何使用mayavi
(您需要安装vtk
来实现此目的的,最好通过您的包管理器完成):
import numpy as np
from mayavi import mlab
from matplotlib.cm import get_cmap # for viridis
def f(x, y):
return np.sin(2*x) * np.cos(2*y)
# data for the surface
x = np.linspace(-2, 2, 100)
X, Y = np.meshgrid(x, x)
Z = f(X, Y)
# data for the scatter
xx = 4*np.random.rand(1000) - 2
yy = 4*np.random.rand(1000) - 2
zz = f(xx,yy)
fig = mlab.figure(bgcolor=(1,1,1))
# note the transpose in surf due to different conventions compared to meshgrid
su = mlab.surf(X.T, Y.T, Z.T)
sc = mlab.points3d(xx, yy, zz, scale_factor=0.1, scale_mode='none',
opacity=1.0, resolution=20, color=(1,0,0))
# manually set viridis for the surface
cmap_name = 'viridis'
cdat = np.array(get_cmap(cmap_name,256).colors)
cdat = (cdat*255).astype(int)
su.module_manager.scalar_lut_manager.lut.table = cdat
mlab.show()
如您所见,结果是交互式三维图,其中表面上的数据点是适当的球体。可以使用不透明度和球体比例设置来获得令人满意的可视化效果。由于正确的3D渲染,无论视角如何,您都可以看到适当数量的每个点。
答案 1 :(得分:0)
从图中看来,您似乎愿意展示非线性优化器局部解决方案的路径,因此我认为您应该考虑在等高线图上绘制线框:
...
ax.scatter(xx,yy,zz,c ='r',marker ='o')###这将仅绘制点,而不绘制线
ax.plot_surface(X,Y,Z,rstride = 1,cstride = 1,cmap ='viridis',edgecolor ='none')
ax.plot_wireframe(xx,yy,zz)###这将绘制线以及可能的点。
...
(xx,yy,zz)包含到局部最大值的路径,这是我想从非线性后悔方法获得的。