数组的总大小不得更改

2 投票
1 回答
3324 浏览
提问于 2025-04-18 14:29

我正在使用一个叫做emcee的Python模块来采样一个分布。我需要把一个名为events的数组(大小为37行100列,分别叫做Ntrig和Nsamp)传递给下面的函数。

def mp(SNR2, *events):
    events = np.asarray(events).reshape((Ntrig,Nsamp))
    bessel = special.iv(0,np.sqrt(x*SNR2(event)))
    exp = np.exp(-0.5*(x+SNR2(event)))
    I = integrate.quad(lambda x: exp*bessel,0,SNRth**2)[0]
    return np.asarray([np.array[I for event in events[i]] for i in range(len(events))]).reshape(events.shape)

但是我一直收到错误信息:

ValueError: total size of new array must be unchanged

我理解的是,*events会把events数组拆分成37*100个单独的参数。那我接下来把数组重新调整形状的那一行,难道不应该把它再放回一个37行100列的数组吗?

顺便说一下,在你问我为什么要把events拆分成单独的参数之前,模块需要这样做才能正常工作,它不能直接接受一个数组。

完整的错误追踪信息:

ValueError                                Traceback (most recent call last)
<ipython-input-17-c8e815326a69> in <module>()
----> 1 mp(SNR2,events)

<ipython-input-16-9f73f234c628> in mp(SNR2, *events)
      5 def mp(SNR2, *events):
      6     events = np.asarray(events).reshape((Ntrig,Nsamp))
----> 7     return np.asarray([np.array([integrate.quad(lambda x: np.exp(-0.5*(x+SNR2(event)))*special.iv(0,np.sqrt(x*SNR2(event))),0,SNRth**2)[0] for event in events[i]]) for i in range(len(events))]).reshape(events.shape)
      8 #    return integrate.quad(lambda x: 0.5*np.exp(-0.5*(x+SNR2(event)))*special.iv(0,np.sqrt(x*SNR2(event))),0,SNRth**2)[0]
      9 def pp(SNR2, *events):

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in quad(func, a, b, args, full_output, epsabs, epsrel, limit, points, weight, wvar, wopts, maxp1, limlst)
    279         args = (args,)
    280     if (weight is None):
--> 281         retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points)
    282     else:
    283         retval = _quad_weight(func,a,b,args,full_output,epsabs,epsrel,limlst,limit,maxp1,weight,wvar,wopts)

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in _quad(func, a, b, args, full_output, epsabs, epsrel, limit, points)
    343     if points is None:
    344         if infbounds == 0:
--> 345             return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
    346         else:
    347             return _quadpack._qagie(func,bound,infbounds,args,full_output,epsabs,epsrel,limit)

<ipython-input-16-9f73f234c628> in <lambda>(x)
      5 def mp(SNR2, *events):
      6     events = np.asarray(events).reshape((Ntrig,Nsamp))
----> 7     return np.asarray([np.array([integrate.quad(lambda x: np.exp(-0.5*(x+SNR2(event)))*special.iv(0,np.sqrt(x*SNR2(event))),0,SNRth**2)[0] for event in events[i]]) for i in range(len(events))]).reshape(events.shape)
      8 #    return integrate.quad(lambda x: 0.5*np.exp(-0.5*(x+SNR2(event)))*special.iv(0,np.sqrt(x*SNR2(event))),0,SNRth**2)[0]
      9 def pp(SNR2, *events):

<ipython-input-16-9f73f234c628> in SNR2(*events)
      1 def SNR2(*events):
----> 2     events = np.asarray(events).reshape((Ntrig,Nsamp))
      3     C = 5*np.pi**(-1.33333)*events**(1.66667)/(96*d**2)
      4     return C*integrate.quad(lambda f: f**(-2.3333)/S(f), 20, 1500, limit=1000)[0]
      5 def mp(SNR2, *events):

ValueError: total size of new array must be unchanged

1 个回答

3

根据我的理解,events 会把事件数组拆分成 37*100 个单独的参数。

其实这并不对。如果你用下面的方式调用 mp

mp(SNR2, events)

那么在 mp 里面,events 会是一个包含一个元素的元组,形式是 (arr,),其中 arr 是一个形状为 (37, 100) 的数组。

如果你用下面的方式调用 mp

mp(SNR2, *events)

那么在 mp 里面,events 会是一个包含 37 个元素的元组,这 37 个元素就是这个 (37, 100) 形状数组的 37 行。

如果你用下面的方式调用 mp

mp(SNR2, *events.flat)

那么在 mp 里面,events 会是一个包含 37*100 个元素的元组。


注意,错误信息的最后一行说:

<ipython-input-16-9f73f234c628> in SNR2(*events)
      1 def SNR2(*events):
----> 2     events = np.asarray(events).reshape((Ntrig,Nsamp))
      3     C = 5*np.pi**(-1.33333)*events**(1.66667)/(96*d**2)
      4     return C*integrate.quad(lambda f: f**(-2.3333)/S(f), 20, 1500, limit=1000)[0]
      5 def mp(SNR2, *events):

ValueError: total size of new array must be unchanged

所以错误是在 Python 的 SNR2 函数中产生的。

因为 SNR2 是通过 SNR2(event)mp 中被调用的,而 event 是一个形状为 (37,100) 的数组,所以在 SNR2 中,event 变量实际上是一个包含原始数组的单元素元组。这并不是你想要的结果。

修复代码的最简单方法是定义:

def SNR2(events):  
    # no longer needed
    # events = np.asarray(events).reshape((Ntrig,Nsamp))

然后像预期那样传递 events

不过,如果你不能改变 SNR2 的参数定义,那么你必须用下面的方式调用它:

SNR2(*event.flat)

mp 函数内部。


参考资料:这里有一篇 很好的解释,讲解了 * 拆包操作符,以及在定义和调用函数时如何使用这种语法。

撰写回答