scipy 0.11.0 到 0.12.0 更改了线性 scipy.interpolate.interp1d,破坏了我不断更新的插值器
Posted
技术标签:
【中文标题】scipy 0.11.0 到 0.12.0 更改了线性 scipy.interpolate.interp1d,破坏了我不断更新的插值器【英文标题】:scipy 0.11.0 to 0.12.0 changes a linear scipy.interpolate.interp1d, breaks my constantly updated interpolator 【发布时间】:2013-07-04 00:30:28 【问题描述】:我一直在玩一个包,它使用线性 scipy.interpolate.interp1d 为 scipy 中的 ode 求解器创建历史函数,描述为 here.
相关的代码类似于
def update(self, ti, Y):
""" Add one new (ti, yi) to the interpolator """
self.itpr.x = np.hstack([self.itpr.x, [ti]])
yi = np.array([Y]).T
self.itpr.y = np.hstack([self.itpr.y, yi])
#self.itpr._y = np.hstack([self.itpr.y, yi])
self.itpr.fill_value = Y
“self.itpr”在 __init__ 中被初始化:
def __init__(self, g, tc=0):
""" g(t) = expression of Y(t) for t<tc """
self.g = g
self.tc = tc
# We must fill the interpolator with 2 points minimum
self.itpr = scipy.interpolate.interp1d(
np.array([tc-1, tc]), # X
np.array([self.g(tc), self.g(tc)]).T, # Y
kind='linear', bounds_error=False,
fill_value = self.g(tc))
其中g
是某个函数,它返回一组值,这些值是一组微分方程的解,tc
是当前时间。
这对我来说似乎很好,因为每次我想更新值的范围时都不必重新创建一个新的插值器对象(这发生在模拟期间的每个显式时间步)。这种更新插值器的方法在 scipy v 0.11.0 下运行良好。但是,在更新到 v 0.12.0 后,我遇到了问题。我看到新的插值器现在包含一个数组_y
,它似乎只是原始的另一个副本。如上所述仅更新_y
是否安全和/或理智? 是否有一种更简单、更 Pythonic 的方法来解决这个问题,希望对 scipy 中的未来更新更加稳健? 同样,在 v 0.11 中一切正常并产生预期结果,在 v 0.12 中我得到IndexError
when _y
is referenced 因为它没有在我的函数中更新,而 y 本身是。
任何帮助/指针将不胜感激!
【问题讨论】:
【参考方案1】:看起来_y
只是y
的一个副本,已被interp1d._reshape_yi()
重塑。因此,使用以下命令更新它应该是安全的:
self.itpr._y = self.itpr._reshape_yi(self.itpr.y)
事实上,据我所知,只有 _y
会被插值器在内部使用,所以我认为您完全可以不用更新 y
。
一个更优雅的解决方案是使_y
成为插值器的一个属性,该属性返回y
的适当重构的副本。可以通过在创建 interp1d
的特定实例后对其进行猴子修补来实现这一点(有关更多解释,请参阅 Alex Martelli 的回答 here):
x = np.arange(100)
y = np.random.randn(100)
itpr = interp1d(x,y)
# method to get self._y from self.y
def get_y(self):
return self._reshape_yi(self.y)
meth = property(get_y,doc='reshaped version of self.y')
# make this a method of this interp1d instance only
basecls = type(itpr)
cls = type(basecls.__name__, (basecls,), )
setattr(cls, '_y', meth)
itpr.__class__ = cls
# itpr._y is just a reshaped version of itpr.y
print itpr.y.shape,itpr._y.shape
>>> (100,) (100, 1)
现在itpr._y
会在您更新itpr.y
时更新
itpr.x = np.arange(110)
itpr.y = np.random.randn(110)
print itpr._y.shape
>>> (110,) (110, 1)
这一切都非常繁琐,而且不是很 Pythonic - 修复 scipy 源代码 (scipy/interpolate/interpolate.py) 要容易得多。您需要做的就是从它设置的interp1d.__init__()
中删除最后一行:
self._y = y
并添加这些行:
@property
def _y(self):
return self._reshape_yi(self.y)
【讨论】:
以上是关于scipy 0.11.0 到 0.12.0 更改了线性 scipy.interpolate.interp1d,破坏了我不断更新的插值器的主要内容,如果未能解决你的问题,请参考以下文章
使用 apt-get 在 Ubuntu 中安装 SciPy 0.11 版 [重复]
sql 2012日志文件频繁出现:svchost (4892) 数据库引擎已分离数据库(1C:Windowssystem32LogFilesSumCurrent.mdb)