代码之家  ›  专栏  ›  技术社区  ›  CAF

多元函数的辛微分与点求值

  •  1
  • CAF  · 技术社区  · 7 年前

    我想用Symphy求一个多变量函数的导数,然后a)要打印的符号结果,然后b)要打印的点的导数结果。我正在使用以下代码

     import math as m
     import numpy
     import scipy
    
     #define constants                                                               
     lambdasq = 0.09
     Ca = 3
     qOsq = 2
    
     def  f1(a,b,NN,ktsq,x):
          return NN*x**(-a)*ktsq**b*m.exp(m.sqrt(16*Ca/9*m.log(1/x)*m.log((m.log(ktsq/lambdasq))/m.log(qOsq/lambdasq))))
    
    from sympy import *
    x = symbols('x')
    
    def f2(NN,a,b,x,ktsq):
        return  -x*diff(m.log(f1),x)
    

    这可以运行,但我找不到一种方法来打印符号结果,当我尝试在某个点进行评估时,比如添加 print(f2(0.3,0.1,-0.2,0.1,3)) 我出错了

      TypeError: must be real number, not function
    

    当我更换时 f1 通过它的符号表示,我得到了错误

      ValueError: 
      Can't calculate 1st derivative wrt 0.100000000000000.
    

    所以我可以把我的问题总结如下

    a) 如何在调用时打印符号导数及其值 diff(m.log(f1),x) (即无需更换 f1级 按其实际代表)

    b) 如果我必须在微分中使用符号表示(即使用 diff(m.log(NN*x**(-a)*ktsq**b*m.exp(m.sqrt(16*Ca/9*m.log(1/x)*m.log((m.log(ktsq\ /lambdasq))/m.log(qOsq/lambdasq))))),x) 那么,如何打印出符号导数及其在某一点上的值?

    Python新手,希望有一个相对简单的补丁。 谢谢

    2 回复  |  直到 7 年前
        1
  •  1
  •   user6655984 user6655984    7 年前

    第一 math 函数是数值函数,不能使用Symphy符号。使用已导入的Symphy(exp、log、sqrt)中的相应函数 from sympy import * :

    def f1(a, b, NN, ktsq, x):
        return NN*x**(-a)*ktsq**b*exp(sqrt(16*Ca/9*log(1/x)*log((log(ktsq/lambdasq))/log(qOsq/lambdasq))))
    

    其次,在f2中,您试图区分 f1 . 但f1是一个可调用的Python函数,而不是Symphy表达式。您需要传入一些参数以获得Symphy表达式,然后可以对其进行区分。

    def f2(NN, a, b, x0, ktsq):
        return (-x*diff(log(f1(a, b, NN, ktsq, x)), x)).subs(x, x0)
    

    在这里,数值参数(值x0除外)被传递给f1,从而得到一个包含x的Symphy表达式。这是需要区分的。之后,用数值x0代替x。

    打印(f2(0.3,0.1,-0.2,0.1,3))#0.366748952743614

    一个要点是SymPy与众不同 表达 功能 . 没有 f' 仅在SymPy中 f'(x) .

        2
  •  1
  •   charelf    4 年前

    我之所以发布这个答案,是因为在搜索“简单多元微分”时,这个帖子在我的搜索引擎上是#1,可能会对某人有所帮助。

    示例1

    import sympy as sp
    
    def f(u):
        return (u[0]**2 + u[1]**10 + u[2] - 4)**2
    
    u = sp.IndexedBase('u')
    
    print(sp.diff(f(u), u[0]))
    

    输出

    4*(u[0]**2 + u[1]**10 + u[2] - 4)*u[0]
    

    这是f(u)wrt u[0]的导数


    示例2

    如果我们想要整个雅可比矩阵,我们可以:

    for i in range(3):
        print(sp.diff(f(u), u[i]))
    

    哪些输出

    4*(u[0]**2 + u[1]**10 + u[2] - 4)*u[0]
    20*(u[0]**2 + u[1]**10 + u[2] - 4)*u[1]**9
    2*u[0]**2 + 2*u[1]**10 + 2*u[2] - 8
    

    我们可以定义一个临时函数并复制粘贴这些行

    def temp(u):
        return np.array([
            4*(u[0]**2 + u[1]**10 + u[2] - 4)*u[0],
            20*(u[0]**2 + u[1]**10 + u[2] - 4)*u[1]**9,
            2*u[0]**2 + 2*u[1]**10 + 2*u[2] - 8,
        ])
    
    temp([1., 1., 1.])
    

    此输出 array([ -4., -20., -2.])

    并验证

    from autograd import grad
    gradient = grad(f)
    gradient([1., 1., 1.])
    

    这将输出: [array(-4.), array(-20.), array(-2.)]

    注:这只是一个简单的演示,演示如何在Symphy中进行多元导数。我希望我能在这方面帮助别人