无法直接应用meshgrid来创建Surfaceplot

问题描述 投票:1回答:1

请考虑以下示例:

from numpy import array, exp, linspace, meshgrid
import matplotlib.pyplot as plt

x = array([1, 2, 3, 4, 5, 6])
y = array([10, 5.49, 0.89, -0.14, -1.07, 0.84])
a1, a2 = 1, 4

def model(x, a1, a2):
    return a1 * exp(-a2 * x)

def residuen(x, y, a1, a2):
    return modell(x, a1, a2) - y

def S(x, y, a1, a2): 
    return 0.5 * sum(residuen(x, y, a1, a2) ** 2)

输入值xy是固定的。我想为Sa1的不同值计算函数a2的值,并将结果显示为3D表面图。在matplotlib tutorial中,我找到了一个使用meshgrid功能的示例。我尝试针对此问题应用此功能:

a1 = linspace(-100, 100, 1000)
a2 = linspace(-100, 100, 1000)
A1, A2 = meshgrid(a1, a2)
Z = S(x, y, A1, A2) 

当我运行此代码时,出现错误

ValueError: operands could not be broadcast together with shapes (1000,1000) (6,)

很明显,上面的代码为什么不起作用,但是我不知道如何修复/重新定义函数S,因此我可以应用meshgrid函数来获得表面图的所需值Z。有人知道如何解决此问题吗?

python numpy matplotlib numpy-broadcasting
1个回答
0
投票

正如您的错误所指示,您的问题确实与matplotlib无关。您正在尝试计算模型与每个1e6位置的6个数据点之间的残差。由于残差是一个和,因此可以想象在某个点处有一个1000x1000x6的数组,并将其与最后一个维度相加。您也可以制作一个6x1000x1000数组,并在第一个维度上求和,但我将显示前一种情况。

您要使用的技术称为broadcasting。这意味着将形状从最后的尺寸开始对齐,并填写单位尺寸以进行匹配。进行广播的最简单的更改是在model中:

a1[..., None] * exp(-a2[..., None] * x)

...中的省略号([..., None])表示“采用所有现有尺寸”。在这种情况下,它是执行[:, :]的简写,但是对于特定数组而言,则需要多次。 None等效于np.newaxis,表示“添加单位尺寸”。总的来说,索引表达式是将尺寸附加到形状的惯用方式。另一种方法是执行类似np.newaxis的操作。

现在您可以执行以下操作:

  1. 将形状a1.reshape(a1.shape + (1,))乘以形状(1000, 1000, 1)a2)->将形状乘以(6,)->结果形状:x(1000, 1000, 6)的最后一个维度是broadcasted。给a2两个隐含的尺寸为x的前导尺寸,这些尺寸也broadcasted

    这是您发生错误的地方。您不能以有意义的方式逐个元素地将形状为1(1000, 1000)的数组相乘,但是可以使用新的单位维度。

  2. 形状(6,)的指数保留形状。
  3. 将结果乘以形状(1000, 1000, 6)(展开的(1000, 1000, 1))。最后一个维度是broadcasted

现在a1中的残差非常好:residuen查找modell(x, a1, a2) - y数组和(1000, 1000, 6)数组之间的差。最终尺寸完美对齐,其余部分由广播负责。

唯一的区别是,由于数组不再平坦,您必须告诉(6,)要在哪个轴上进行操作:

sum

尽管这不是正确的RMS计算。我本来希望看到

sum

查找数组均方根的更简单方法是使用0.5 * sum(residuen(x, y, a1, a2)**2, axis=1)

sum(residuen(x, y, a1, a2)**2, axis=-1)**0.5

TL; DR

您的节目需要使用广播:

np.linalg.norm
© www.soinside.com 2019 - 2024. All rights reserved.