【问题标题】:Vectorizing A Function With Array Parameter使用数组参数向量化函数
【发布时间】:2018-05-12 09:26:24
【问题描述】:

我目前正在尝试将卡方分析应用于某些数据。 我想根据模型的两个系数绘制不同值的颜色图

def f(x, coeff):
    return coeff[0] + numpy.exp(coeff[1] * x)

def chi_squared(coeff, x, y, y_err):
    return numpy.sum(((y - f(x, coeff) / y_err)**2)

us = numpy.linspace(u0, u1, n)
vs = numpy.linspace(v0, v1, n)
rs = numpy.meshgrid(us, vs)

chi = numpy.vectorize(chi_squared)
chi(rs, x, y, y_error)

我尝试对函数进行矢量化,以便能够传递不同系数的网格来生成颜色图。

x、y、y_err 的值都是长度为 n 的一维数组。 u, v 是各种变化系数。

但是这不起作用,导致 IndexError: invalid index to scalar variable.

这是因为 coeff 作为标量而不是向量传递,但我不知道如何纠正。

更新

我的目标是获取坐标数组

rs = [[[u0, v0], [u1, v0],..,[un, v0]],...,[[u0, vm],..,[un,vm]]

其中每个坐标是要传递给卡方方法的系数参数。 这应该返回一个二维数组,其中填充了适当坐标的卡方值

chi = [[c00, c10, ..., cn0], ..., [c0m, c1m, ..., cnm]]

然后我可以使用这些数据通过 imshow 绘制颜色图

【问题讨论】:

  • 较新的vectorize 采用signature 参数。如果您提供一个示例 f 函数,我们也许能够计算出正确的签名。看起来我需要样品xy。我也想知道你是否需要vectorizechi_squared 中的表达式可能会正确广播数组。总之,我们需要更多的工作示例。
  • 取 f 为添加了指数项的二阶多项式。将更新一个工作示例
  • xyy_error 是标量,还是需要包含在广播中?需要注意的另一件事是 rs 来自 meshgrid 是 2 个数组的列表。 vectorize 将把它包装在 np.asarray 中,生成一个 3d 数组。 np.sum 没有轴,返回一个值(即,它对扁平数组求和)。
  • 这个“工作示例”包括:未定义的 u0、未定义的 u1、未定义的 n、未定义的 v0、未定义的 v1、未定义的 x、未定义的 y、未定义的 y_error 和 chi_squared 函数中不匹配的括号。不是我对工作示例的想法。无论如何,hpaulj 已经告诉了你答案:meshgrid 并没有按照你的想法去做,请再次阅读它的描述。
  • 道歉。我不熟悉工作示例的概念,特别是因为我没有这样的工作代码。我研究了 meshgrid,我正在更新我的代码

标签: python numpy vectorization chi-squared


【解决方案1】:

这是我第一次尝试运行您的代码:

In [44]: def f(x, coeff):
    ...:     return coeff[0] + numpy.exp(coeff[1] * x)
    ...: 
    ...: def chi_squared(coeff, x, y, y_err):
    ...:     return numpy.sum((y - f(x, coeff) / y_err)**2)

(我必须删除最后一行中的 (

首先猜测可能的数组值:

In [45]: x = np.arange(3)
In [46]: y = x
In [47]: y_err = x
In [48]: us = np.linspace(0,1,3)
In [49]: rs = np.meshgrid(us,us)
In [50]: rs
Out[50]: 
[array([[ 0. ,  0.5,  1. ],
        [ 0. ,  0.5,  1. ],
        [ 0. ,  0.5,  1. ]]), 
 array([[ 0. ,  0. ,  0. ],
        [ 0.5,  0.5,  0.5],
        [ 1. ,  1. ,  1. ]])]

In [51]: chi_squared(rs, x, y, y_err)
/usr/local/bin/ipython3:5: RuntimeWarning: divide by zero encountered in true_divide
  import sys
Out[51]: inf

哎呀,y_err 不应该是 0。再试一次:

In [52]: y_err = np.array([1,1,1])
In [53]: chi_squared(rs, x, y, y_err)
Out[53]: 53.262865105526018

如果我将rs 列表转换为数组,它也可以工作:

In [55]: np.array(rs).shape
Out[55]: (2, 3, 3)
In [56]: chi_squared(np.array(rs), x, y, y_err)
Out[56]: 53.262865105526018

现在,vectorize 的目的是什么?

f 函数返回一个 (n,n) 数组:

In [57]: f(x, rs)
Out[57]: 
array([[ 1.        ,  1.5       ,  2.        ],
       [ 1.        ,  2.14872127,  3.71828183],
       [ 1.        ,  3.21828183,  8.3890561 ]])

让我们修改chi_squaredsum 一个轴

In [61]: def chi_squared(coeff, x, y, y_err, axis=None):
    ...:     return numpy.sum((y - f(x, coeff) / y_err)**2, axis=axis)

In [62]: chi_squared(np.array(rs), x, y, y_err)
Out[62]: 53.262865105526018

In [63]: chi_squared(np.array(rs), x, y, y_err, axis=0)
Out[63]: array([  3.        ,   6.49033483,  43.77253028])

In [64]: chi_squared(np.array(rs), x, y, y_err, axis=1)
Out[64]: array([  1.25      ,   5.272053  ,  46.74081211])

我很想将coeff 更改为coeff0, coeff1,以便从一开始就更好地控制此参数的传递方式,但它可能没有什么不同。

更新

现在您已经更具体地了解了coeff 值与xy 等的关系,我发现这可以通过简单的广播来解决。无需使用np.vectorize

首先,定义一个不同大小的网格;这样我们和代码就不会认为coeff 网格的每个维度都与x,y 值有关。

In [134]: rs = np.meshgrid(np.linspace(0,1,4), np.linspace(0,1,5), indexing='ij')
In [135]: coeff=np.array(rs)
In [136]: coeff.shape
Out[136]: (2, 4, 5)

现在看看f 在给定coeffx 后的样子。

In [137]: f(x, coeff[...,None]).shape
Out[137]: (4, 5, 3)

coeff 实际上是 (4,5,1),而 x 是 (1,1,3),导致 (4,5,3)(通过广播规则)

同样的事情发生在chi_squared 内部,最后一步是sum 在最后一个轴上(大小为 3):

In [138]: chi_squared(coeff[...,None], x, y, y_err, axis=-1)
Out[138]: 
array([[  2.        ,   1.20406718,   1.93676807,   8.40646968,
         32.99441808],
       [  2.33333333,   2.15923164,   3.84810347,  11.80559574,
         38.73264336],
       [  3.33333333,   3.78106277,   6.42610554,  15.87138846,
         45.13753532],
       [  5.        ,   6.06956056,   9.67077427,  20.60384785,
         52.20909393]])
In [139]: _.shape
Out[139]: (4, 5)

每个coeff 值对都有一个值,即 (4,5) 网格。

【讨论】:

  • 这很接近,我想生成一个卡方值的二维数组
  • 完美!谢谢,看来我需要更多地阅读广播,我只知道基础知识。一个问题,将系数作为 coeff[..., None] 传递的需要是什么
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-10
  • 1970-01-01
  • 2019-08-10
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
相关资源
最近更新 更多