如何求解 python 中参数向量的非线性函数

How to solve a nonlinear function for a vector of parameters in python

我有一个非线性函数,我想在不同的参数值下求解。

这是一个 MWE:

import numpy  as np 
import tensorflow as tf
import scipy.optimize 

# fixed parameters
kon = 0.01
mu  = 1.5
fi  = 0.5 
kappa = 22
w = 0.63

# varying parameters 
n =100
xs = tf.random.normal(shape=(n,), stddev=0.2)
eps = tf.random.normal(shape=(n,), stddev=0.17)
z = tf.sigmoid(tf.random.normal(shape=(n,), stddev=0.22))

我的解决方案

def get_leisure(z, eps, x0):
    hvec = np.empty((0,))
    # leisure today
    for ze,ei,xs in zip(z, eps, x0):
        ei=np.exp(ei)
        xs=np.exp(xs)
        # define the function for leisure 
        def leisure_function(hi):
            return (mu/fi)*np.log(hi) -(1-mu)*kappa*(hi)**(1+(1/fi))- mu*(np.log(w*ei*xs)-np.log(kon))-np.log(ze)

        htemp = scipy.optimize.newton_krylov(leisure_function, 0.5)
        hvec = np.append(hvec, htemp)
    return hvec

我的问题:

因为我必须循环解决 hi 未知的案例数量,可能很大,有没有更好的方法呢?例如避免循环?

我不是经验丰富的 python 用户,如果有任何帮助,我将不胜感激。

只是为了说明我想在评论中表达的观点。

如果我 运行 你的代码按原样计时:

import numpy  as np 
import tensorflow as tf
import scipy.optimize 

from timeit import default_timer as timer
# fixed parameters
kon = 0.01
mu  = 1.5
fi  = 0.5 
kappa = 22
w = 0.63

# varying parameters 
n=10000
x0 = tf.random.normal(shape=(n,), stddev=0.2)
eps = tf.random.normal(shape=(n,), stddev=0.17)
z = tf.sigmoid(tf.random.normal(shape=(n,), stddev=0.22))

def get_leisure(z, eps, x0):
    hvec = np.empty((0,))
    # leisure today
    for ze,ei,xs in zip(z, eps, x0):
        ei=np.exp(ei)
        xs=np.exp(xs)
        # define the function for leisure 
        def leisure_function(hi):
            return (mu/fi)*np.log(hi) -(1-mu)*kappa*(hi)**(1+(1/fi))- mu*(np.log(w*ei*xs)-np.log(kon))-np.log(ze)

        htemp = scipy.optimize.newton_krylov(leisure_function, 0.5)
        hvec = np.append(hvec, htemp)
    return hvec

start = timer()
msh855_result = get_leisure(z, eps, x0)
end = timer()
print(f'elapsed time: { end - start} s')

在普通机器上大约需要 30.04823809700065 s

同一台机器上的相同问题,但采用矢量化方法

start = timer()
e_eps = np.exp(eps)
e_x0 = np.exp(x0)
c_1=mu/fi * np.ones(n)
c_2=(1-mu)*kappa * np.ones(n)
c_3= 1 + (1/fi)
c_4=mu*np.log(w*e_eps*e_x0/kon)+np.log(z)
def fun(x):
    return c_1[0] * np.log(x) - c_2[0] * ((x) ** c_3)-c_4
v_result = scipy.optimize.newton_krylov(fun, 0.5 * np.ones(n))
end = timer()
print(f'elapsed time: { end - start} s')

只需0.051494838000508025 s

如果您不相信结果非常接近:

>>> sum(np.sqrt(((msh855_result - v_result)**2)/n))
2.0087031341897715e-06