Python:用于更快动态编程的 Numba njit 模式
Python: Numba njit mode for faster dynamic programming
我是 Python 的新手。我想使用 Python 进行我的数值实验,其中我需要精确地解决许多动态规划问题。因此,优化我的代码以提高效率很重要。我的代码实际上与带有 Numba 的 @jit 一起使用,但我想使用 @njit 进一步提高性能。您可以从下面的代码中看到,为了提高效率,我尝试在 for 循环内矢量化我的操作。正如我之前提到的,@jit 工作正常,但是对于 @njit,它一直给我错误消息。众所周知,准确地解决动态程序是计算密集型的,因此我真的很想使用@njit 来进一步提高性能。我真的可以使用一些帮助来更改代码以允许@njit。提前致谢!
我的代码:
import numba as nb
import numpy as np
#DP computation
@nb.njit
def dp(beta,cost,wcost,decisions,number_of_stages,states):
tbeta=1-beta
odcost=min((cost[-max(decisions):]+wcost)/beta[-max(decisions):])
terminal=(max(states)-states)*odcost
L=max(states)
D=number_of_stages
value=np.zeros((D+1,L+1))
choice=np.zeros((D+1,L)).astype(np.int64)
value[-1]=terminal
for s in range(D-1,L-2,-1):
intmatrix=cost[:, None]+np.outer(beta,value[s+1][1:L+1])+np.outer(tbeta,value[s+1][0:L])
choice[s]=intmatrix.T.argmin(axis=1)
value[s][0:L]=intmatrix[choice[s],np.arange(intmatrix.shape[1])]
for s in range(L-2,-1,-1):
intmatrix=cost[:, None]+np.outer(beta,value[s+1][1:s+2])+np.outer(tbeta,value[s+1][0:s+1])
choice[s][0:s+1]=intmatrix.T.argmin(axis=1)
value[s][0:s+1]=intmatrix[choice[s][0:s+1],np.arange(intmatrix.shape[1])]
return value, choice
#initialization
decisions=np.arange(100)
number_of_stages=200
states=np.arange(101)
np.random.seed(2021)
beta=np.append(0,np.random.uniform(0,1,max(decisions)))
wcost=np.random.uniform(0,1)
cost=np.square(beta)
value, choice=dp(beta,cost,wcost,decisions,number_of_stages,states)
错误信息:
TypingError: No implementation of function Function(<built-in function getitem>) found for signature:
getitem(array(float64, 1d, C), Tuple(slice<a:b>, none))
There are 22 candidate implementations:
- Of which 20 did not match due to:
Overload of function 'getitem': File: <numerous>: Line N/A.
With argument(s): '(array(float64, 1d, C), Tuple(slice<a:b>, none))':
No match.
- Of which 2 did not match due to:
Overload in function 'GetItemBuffer.generic': File: numba\core\typing\arraydecl.py: Line 162.
With argument(s): '(array(float64, 1d, C), Tuple(slice<a:b>, none))':
Rejected as the implementation raised a specific error:
TypeError: unsupported array index type none in Tuple(slice<a:b>, none)
raised from C:\ProgramData\Anaconda3\lib\site-packages\numba\core\typing\arraydecl.py:68
似乎 numba 不支持所有类型的 numpy 奇特索引。你必须回到循环。这在 numba 中很常见,您需要忘记 numpy、向量化的编码方式才能回到显式循环。
这应该可以完成工作,我只是明确了循环。
@nb.njit
def dp(beta, cost, wcost, decisions, number_of_stages, states):
tbeta = 1 - beta
odcost = min((cost[-max(decisions) :] + wcost) / beta[-max(decisions) :])
terminal = (max(states) - states) * odcost
L = max(states)
D = number_of_stages
value = np.zeros((D + 1, L + 1))
choice = np.zeros((D + 1, L)).astype(np.int64)
value[-1] = terminal
for s in range(D - 1, L - 2, -1):
intmatrix = (
cost.reshape(-1, 1)
+ np.outer(beta, value[s + 1][1 : L + 1])
+ np.outer(tbeta, value[s + 1][0:L])
)
choice[s] = intmatrix.T.argmin(axis=1)
for i in range(intmatrix.shape[1]):
value[s][i] = intmatrix[choice[s][i], i]
for s in range(L - 2, -1, -1):
intmatrix = (
cost.reshape(-1, 1)
+ np.outer(beta, value[s + 1][1 : s + 2])
+ np.outer(tbeta, value[s + 1][0 : s + 1])
)
choice[s][0 : s + 1] = intmatrix.T.argmin(axis=1)
for i in range(intmatrix.shape[1]):
value[s][0 : s + 1][i] = intmatrix[choice[s][0 : s + 1][i], i]
return value, choice
我是 Python 的新手。我想使用 Python 进行我的数值实验,其中我需要精确地解决许多动态规划问题。因此,优化我的代码以提高效率很重要。我的代码实际上与带有 Numba 的 @jit 一起使用,但我想使用 @njit 进一步提高性能。您可以从下面的代码中看到,为了提高效率,我尝试在 for 循环内矢量化我的操作。正如我之前提到的,@jit 工作正常,但是对于 @njit,它一直给我错误消息。众所周知,准确地解决动态程序是计算密集型的,因此我真的很想使用@njit 来进一步提高性能。我真的可以使用一些帮助来更改代码以允许@njit。提前致谢!
我的代码:
import numba as nb
import numpy as np
#DP computation
@nb.njit
def dp(beta,cost,wcost,decisions,number_of_stages,states):
tbeta=1-beta
odcost=min((cost[-max(decisions):]+wcost)/beta[-max(decisions):])
terminal=(max(states)-states)*odcost
L=max(states)
D=number_of_stages
value=np.zeros((D+1,L+1))
choice=np.zeros((D+1,L)).astype(np.int64)
value[-1]=terminal
for s in range(D-1,L-2,-1):
intmatrix=cost[:, None]+np.outer(beta,value[s+1][1:L+1])+np.outer(tbeta,value[s+1][0:L])
choice[s]=intmatrix.T.argmin(axis=1)
value[s][0:L]=intmatrix[choice[s],np.arange(intmatrix.shape[1])]
for s in range(L-2,-1,-1):
intmatrix=cost[:, None]+np.outer(beta,value[s+1][1:s+2])+np.outer(tbeta,value[s+1][0:s+1])
choice[s][0:s+1]=intmatrix.T.argmin(axis=1)
value[s][0:s+1]=intmatrix[choice[s][0:s+1],np.arange(intmatrix.shape[1])]
return value, choice
#initialization
decisions=np.arange(100)
number_of_stages=200
states=np.arange(101)
np.random.seed(2021)
beta=np.append(0,np.random.uniform(0,1,max(decisions)))
wcost=np.random.uniform(0,1)
cost=np.square(beta)
value, choice=dp(beta,cost,wcost,decisions,number_of_stages,states)
错误信息:
TypingError: No implementation of function Function(<built-in function getitem>) found for signature:
getitem(array(float64, 1d, C), Tuple(slice<a:b>, none))
There are 22 candidate implementations:
- Of which 20 did not match due to:
Overload of function 'getitem': File: <numerous>: Line N/A.
With argument(s): '(array(float64, 1d, C), Tuple(slice<a:b>, none))':
No match.
- Of which 2 did not match due to:
Overload in function 'GetItemBuffer.generic': File: numba\core\typing\arraydecl.py: Line 162.
With argument(s): '(array(float64, 1d, C), Tuple(slice<a:b>, none))':
Rejected as the implementation raised a specific error:
TypeError: unsupported array index type none in Tuple(slice<a:b>, none)
raised from C:\ProgramData\Anaconda3\lib\site-packages\numba\core\typing\arraydecl.py:68
似乎 numba 不支持所有类型的 numpy 奇特索引。你必须回到循环。这在 numba 中很常见,您需要忘记 numpy、向量化的编码方式才能回到显式循环。
这应该可以完成工作,我只是明确了循环。
@nb.njit
def dp(beta, cost, wcost, decisions, number_of_stages, states):
tbeta = 1 - beta
odcost = min((cost[-max(decisions) :] + wcost) / beta[-max(decisions) :])
terminal = (max(states) - states) * odcost
L = max(states)
D = number_of_stages
value = np.zeros((D + 1, L + 1))
choice = np.zeros((D + 1, L)).astype(np.int64)
value[-1] = terminal
for s in range(D - 1, L - 2, -1):
intmatrix = (
cost.reshape(-1, 1)
+ np.outer(beta, value[s + 1][1 : L + 1])
+ np.outer(tbeta, value[s + 1][0:L])
)
choice[s] = intmatrix.T.argmin(axis=1)
for i in range(intmatrix.shape[1]):
value[s][i] = intmatrix[choice[s][i], i]
for s in range(L - 2, -1, -1):
intmatrix = (
cost.reshape(-1, 1)
+ np.outer(beta, value[s + 1][1 : s + 2])
+ np.outer(tbeta, value[s + 1][0 : s + 1])
)
choice[s][0 : s + 1] = intmatrix.T.argmin(axis=1)
for i in range(intmatrix.shape[1]):
value[s][0 : s + 1][i] = intmatrix[choice[s][0 : s + 1][i], i]
return value, choice