我需要找到一个广义状态空间的根。也就是说,我有一个维度grid=AxBx(...)xX
的离散网格,其中我不知道它有多少维度(解决方案应该适用于任何grid.size
)。
我想使用bisection method为f(z) = 0
内的每个州z
找到根(grid
)。说remainder
包含f(z)
,我知道f'(z) < 0
。然后我需要
z
&gt; remainder
0 z
&lt; remainder
0 Wlog,假设形状history
的矩阵(grid.shape, T)
包含网格中每个点的z
的早期值的历史记录,我需要增加z
(因为remainder
&gt; 0)。然后,我需要在zAlternative
内选择history[z, :]
,这是{最小的那些,大于z
“。在伪代码中,即:
zAlternative = hist[z,:][hist[z,:] > z].min()
I had asked this earlier。我给出的解决方案是
b = sort(history[..., :-1], axis=-1)
mask = b > history[..., -1:]
index = argmax(mask, axis=-1)
indices = tuple([arange(j) for j in b.shape[:-1]])
indices = meshgrid(*indices, indexing='ij', sparse=True)
indices.append(index)
indices = tuple(indices)
lowerZ = history[indices]
b = sort(history[..., :-1], axis=-1)
mask = b <= history[..., -1:]
index = argmax(mask, axis=-1)
indices = tuple([arange(j) for j in b.shape[:-1]])
indices = meshgrid(*indices, indexing='ij', sparse=True)
indices.append(index)
indices = tuple(indices)
higherZ = history[indices]
newZ = history[..., -1]
criterion = 0.05
increase = remainder > 0 + criterion
decrease = remainder < 0 - criterion
newZ[increase] = 0.5*(newZ[increase] + higherZ[increase])
newZ[decrease] = 0.5*(newZ[decrease] + lowerZ[decrease])
但是,此代码对我来说不再适用。承认这一点我感到非常糟糕,但我从未理解指数所发生的魔力,因此我很遗憾需要帮助。
代码实际上做了什么,它分别给我最低 最高。也就是说,如果我修复了两个特定的z
值:
history[z1] = array([0.3, 0.2, 0.1])
history[z2] = array([0.1, 0.2, 0.3])
我会得到higherZ[z1]
= 0.3
和lowerZ[z2] = 0.1
,即极值。两种情况的正确值都是0.2
。这里出了什么问题?
如果需要,为了生成测试数据,您可以使用
行history = tile(array([0.1, 0.3, 0.2, 0.15, 0.13])[newaxis,newaxis,:], (10, 20, 1))
remainder = -1*ones((10, 20))
测试第二种情况。
预期结果
我调整了上面的history
变量,给出了向上和向下的测试用例。预期结果将是
lowerZ = 0.1 * ones((10,20))
higherZ = 0.15 * ones((10,20))
对于历史记录中的每个点z
[z,:],下一个最高的前一个值(higherZ
)和下一个最小的前一个值(lowerZ
)。由于所有积分z
都具有完全相同的历史记录([0.1, 0.3, 0.2, 0.15, 0.13]
),因此lowerZ
和higherZ
的所有积分都具有相同的值。当然,一般来说,每个z
的历史记录会有所不同,因此两个矩阵在每个网格点上都会包含可能不同的值。
答案 0 :(得分:1)
我将您在此处发布的内容与the solution for your previous post进行了比较,并发现了一些差异。
对于较小的 z,你说
mask = b > history[..., -1:]
index = argmax(mask, axis=-1)
他们说:
mask = b >= a[..., -1:]
index = np.argmax(mask, axis=-1) - 1
对于较大的 z,你说
mask = b <= history[..., -1:]
index = argmax(mask, axis=-1)
他们说:
mask = b > a[..., -1:]
index = np.argmax(mask, axis=-1)
使用the solution for your previous post,我得到:
import numpy as np
history = np.tile(np.array([0.1, 0.3, 0.2, 0.15, 0.13])[np.newaxis,np.newaxis,:], (10, 20, 1))
remainder = -1*np.ones((10, 20))
a = history
# b is a sorted ndarray excluding the most recent observation
# it is sorted along the observation axis
b = np.sort(a[..., :-1], axis=-1)
# mask is a boolean array, comparing the (sorted)
# previous observations to the current observation - [..., -1:]
mask = b > a[..., -1:]
# The next 5 statements build an indexing array.
# True evaluates to one and False evaluates to zero.
# argmax() will return the index of the first True,
# in this case along the last (observations) axis.
# index is an array with the shape of z (2-d for this test data).
# It represents the index of the next greater
# observation for every 'element' of z.
index = np.argmax(mask, axis=-1)
# The next two statements construct arrays of indices
# for every element of z - the first n-1 dimensions of history.
indices = tuple([np.arange(j) for j in b.shape[:-1]])
indices = np.meshgrid(*indices, indexing='ij', sparse=True)
# Adding index to the end of indices (the last dimension of history)
# produces a 'group' of indices that will 'select' a single observation
# for every 'element' of z
indices.append(index)
indices = tuple(indices)
higherZ = b[indices]
mask = b >= a[..., -1:]
# Since b excludes the current observation, we want the
# index just before the next highest observation for lowerZ,
# hence the minus one.
index = np.argmax(mask, axis=-1) - 1
indices = tuple([np.arange(j) for j in b.shape[:-1]])
indices = np.meshgrid(*indices, indexing='ij', sparse=True)
indices.append(index)
indices = tuple(indices)
lowerZ = b[indices]
assert np.all(lowerZ == .1)
assert np.all(higherZ == .15)
似乎有用
答案 1 :(得分:0)
用于history
中下一个最高和最低观测值的z形阵列
相对于当前的观察,鉴于目前的观察是history[...,-1:]
通过操纵history
的步幅来构造更高和更低的数组
使得更容易迭代z的每个元素的观察结果。
这是使用numpy.lib.stride_tricks.as_strided
和n-dim泛化完成的
功能在Efficient Overlapping Windows with Numpy找到 - 我将在最后包含它的来源
有一个python循环,对{10},(10,20,x)的history.shape
进行200次迭代。
import numpy as np
history = np.tile(np.array([0.1, 0.3, 0.2, 0.15, 0.13])[np.newaxis,np.newaxis,:], (10, 20, 1))
remainder = -1*np.ones((10, 20))
z_shape = final_shape = history.shape[:-1]
number_of_observations = history.shape[-1]
number_of_elements_in_z = np.product(z_shape)
# manipulate histories to efficiently iterate over
# the observations of each "element" of z
s = sliding_window(history, (1,1,number_of_observations))
# s.shape will be (number_of_elements_in_z, number_of_observations)
# create arrays of the next lower and next higher observation
lowerZ = np.zeros(number_of_elements_in_z)
higherZ = np.zeros(number_of_elements_in_z)
for ndx, observations in enumerate(s):
current_observation = observations[-1]
a = np.sort(observations)
lowerZ[ndx] = a[a < current_observation][-1]
higherZ[ndx] = a[a > current_observation][0]
assert np.all(lowerZ == .1)
assert np.all(higherZ == .15)
lowerZ = lowerZ.reshape(z_shape)
higherZ = higherZ.reshape(z_shape)
来自Efficient Overlapping Windows with Numpy 的sliding_window
import numpy as np
from numpy.lib.stride_tricks import as_strided as ast
from itertools import product
def norm_shape(shape):
'''
Normalize numpy array shapes so they're always expressed as a tuple,
even for one-dimensional shapes.
Parameters
shape - an int, or a tuple of ints
Returns
a shape tuple
from http://www.johnvinyard.com/blog/?p=268
'''
try:
i = int(shape)
return (i,)
except TypeError:
# shape was not a number
pass
try:
t = tuple(shape)
return t
except TypeError:
# shape was not iterable
pass
raise TypeError('shape must be an int, or a tuple of ints')
def sliding_window(a,ws,ss = None,flatten = True):
'''
Return a sliding window over a in any number of dimensions
Parameters:
a - an n-dimensional numpy array
ws - an int (a is 1D) or tuple (a is 2D or greater) representing the size
of each dimension of the window
ss - an int (a is 1D) or tuple (a is 2D or greater) representing the
amount to slide the window in each dimension. If not specified, it
defaults to ws.
flatten - if True, all slices are flattened, otherwise, there is an
extra dimension for each dimension of the input.
Returns
an array containing each n-dimensional window from a
from http://www.johnvinyard.com/blog/?p=268
'''
if None is ss:
# ss was not provided. the windows will not overlap in any direction.
ss = ws
ws = norm_shape(ws)
ss = norm_shape(ss)
# convert ws, ss, and a.shape to numpy arrays so that we can do math in every
# dimension at once.
ws = np.array(ws)
ss = np.array(ss)
shape = np.array(a.shape)
# ensure that ws, ss, and a.shape all have the same number of dimensions
ls = [len(shape),len(ws),len(ss)]
if 1 != len(set(ls)):
error_string = 'a.shape, ws and ss must all have the same length. They were{}'
raise ValueError(error_string.format(str(ls)))
# ensure that ws is smaller than a in every dimension
if np.any(ws > shape):
error_string = 'ws cannot be larger than a in any dimension. a.shape was {} and ws was {}'
raise ValueError(error_string.format(str(a.shape),str(ws)))
# how many slices will there be in each dimension?
newshape = norm_shape(((shape - ws) // ss) + 1)
# the shape of the strided array will be the number of slices in each dimension
# plus the shape of the window (tuple addition)
newshape += norm_shape(ws)
# the strides tuple will be the array's strides multiplied by step size, plus
# the array's strides (tuple addition)
newstrides = norm_shape(np.array(a.strides) * ss) + a.strides
strided = ast(a,shape = newshape,strides = newstrides)
if not flatten:
return strided
# Collapse strided so that it has one more dimension than the window. I.e.,
# the new array is a flat list of slices.
meat = len(ws) if ws.shape else 0
firstdim = (np.product(newshape[:-meat]),) if ws.shape else ()
dim = firstdim + (newshape[-meat:])
# remove any dimensions with size 1
dim = filter(lambda i : i != 1,dim)
return strided.reshape(dim)