>

파이썬 차별화와 관련하여 어제 질문을했습니다 함수를 작성한 다음 게시 된 답변 중 어느 것도 (일부 변수로) 평가하고 파생물을 플로팅 해야하는 데 만족스럽지 않다는 것을 알았을 때 내 자신의 솔루션을 알아낼 수있었습니다.

이전 코드 :
import sympy as sym
import math

def f(x,y):
    return x**2 + x*y**2

x, y = sym.symbols('x y')
def fprime(x,y):
    return sym.diff(f(x,y),x)
print(fprime(x,y)) #This works.
print(fprime(1,1))

새로운 코드 :
import sympy as sym
import math

def f(x,y):
    return x**2 + x*y**2

x, y = sym.symbols('x y')
def fprime(x,y):
    return sym.diff(f(x,y),x)
print(fprime(x,y)) #This works.
DerivativeOfF = sym.lambdify((x,y),fprime(x,y),"numpy")
print(DerivativeOfF(1,1))

보시다시피, 나는 flamme의 "lambdified"버전 인 새로운 함수 DerivativeOfF를 생성함으로써 파생 fprime을 평가할 수 없다는 것을 극복했습니다. 거기서 DerivativeOfF를 평가하고 변수 중 하나로 플롯 할 수있었습니다.

My question is:why did this work? What exactly have I done? And what are some downsides to this method? I have tried reading the lambdify documentation but it's extremely confusing to me (I'm a beginner in Python). My guess is that I converted the Python function fprime to a Sympy expression DerivativeOfF, or something like that. Any help explaining what happened and why, and what exactly lambdify does (in layman's terms), would be appreciated.


  • 답변 # 1

    이 동작을 설명 할 수 있는지 봅시다. 나는 파이썬과 numpy 를 알고 있었다  글쎄, 그러나 sympy 를 사용하지 않은  많이 (그러나 macsyma 와 같은 다른 상징적 대수 패키지를 사용했습니다. ).

    ipython numpy 세션에서 :

    In [1]: def f(x,y):
       ...:     return x**2 + x*y**2
       ...: 
    In [2]: f(1,3)
    Out[2]: 10
    In [3]: f(np.arange(1,4), np.arange(10,13))
    Out[3]: array([101, 246, 441])
    
    

    f  파이썬 함수입니다. 그것이 반환하는 것은 입력이 * 와 같은 연산을 처리하는 방법에 달려 있습니다. , **  그리고 + . 스칼라와 배열이 작동합니다. + 를 처리하는 목록  그리고 *  (연결, 복제), ** 는 아님 .

    In [4]: import sympy as sym
    In [5]: x, y = sym.symbols('x y')
    In [6]: type(x)
    Out[6]: sympy.core.symbol.Symbol
    In [7]: x+y
    Out[7]: x + y
    In [8]: type(_)
    Out[8]: sympy.core.add.Add
    
    

    와이즈 비즈 정의  몇 가지 새로운 객체를 만듭니다. 그들은 symbols 를 처리  등 자신의 상징적 인 방식으로.

    +
    
    

    와이즈 비즈에게 전화하기  이 2 개의 심볼 객체로 새로운 sym 객체를 만듭니다. 다른 기호와 숫자 조합 또는 배열로도 호출 할 수 있습니다.

    In [9]: fsym = f(x,y)
    In [10]: type(fsym)
    Out[10]: sympy.core.add.Add
    In [11]: print(fsym)
    x**2 + x*y**2
    
    

    f 를 통과하면   In [12]: f(x,0) Out[12]: x**2 In [13]: f(1,x) Out[13]: x**2 + 1 In [14]: f(np.arange(3), x) Out[14]: array([0, x**2 + 1, 2*x**2 + 4], dtype=object) 에 개체  나는 새로운 Add 를 얻는다  개체

    sym.diff
    
    

    와이즈 비즈  또는 Add  호출 가능합니다. 그것들은 파이썬 함수가 아닙니다. 와이즈 비즈  작동하지 않습니다.

    그러나 pyzwyz   In [15]: fprime = sym.diff(fsym,x) In [16]: fprime Out[16]: 2*x + y**2 를 대체하는 데 사용할 수 있습니다  또는 fsym  숫자 든 다른 기호 든 다른 값으로 :

    fprime
    
    

    fsym(1,2)   fsym.subs 입니다  sympy 객체를 받아 파이썬 함수를 반환하는 함수, 아마도 x  호환 가능합니다.

    y
    
    In [19]: fsym.subs(x,1) Out[19]: y**2 + 1 In [20]: fsym.subs(y,2*x) Out[20]: 4*x**3 + x**2 In [21]: fsym.subs([(x,1),(y,2)]) Out[21]: 5 In [22]: fprime.subs([(x,1),(y,2)]) Out[22]: 6  기능은 원래 lambdify 와 유사합니다 . 동일하지 않습니다. 예를 들어 sympy 가 있습니다.  표현.

    numpy   In [24]: fl = sym.lambdify((x,y), fsym, "numpy") In [25]: fl Out[25]: <function numpy.<lambda>> In [26]: fl(1,2) Out[26]: 5 In [27]: fl(np.arange(1,4), np.arange(10,13)) # cf with f(same) above Out[27]: array([101, 246, 441]) 에 적용  똑같은 일을하지만 다른 상징적 표현으로

    fl
    
    
    파이썬/NumPy와 기능이나 표현과 sympy들 간의 투명성은 한계가있다. 다른 (삭제 된) 답변은 그것들을 탐구하려고했습니다. 예를 들어 f 에는 차이가 있습니다 , help/doc  그리고 lambdify .

    는 이러한 예에서, 분화는 fprime 상징적으로 수행  기능.

    In [28]: fpl = sym.lambdify((x,y), fprime, "numpy")
    In [29]: fpl(1,2)
    Out[29]: 6
    In [30]: fpl(np.arange(1,4), np.arange(10,13))
    Out[30]: array([102, 125, 150])
    
    

    math.sin  이 sympy 객체 중 하나를 Python 함수로 변환하는 방법입니다.

    트리거 예

    다른 답변에 대한 토론에서 예제를 선택

    numpy.sin 를 사용하는 함수 정의  sin/cos 버전 :

    sym.sin
    
    

    sym.diff 때문에  작동하지 않습니다. 그것은 In [35]: fsym Out[35]: x**2 + x*y**2 In [36]: fprime Out[36]: 2*x + y**2 해야 할 것입니다 하지만 기호에서는 작동하지 않습니다.

    기호 파생물을 가져 오기 전에 :

    sym.lambdify
    
    

    이 기능들 중 어느 것도 다시는 없습니다. sym 로 평가를 수행해야합니다  또는 In [53]: def f1(x,y): ...: return sym.sin(x) + x*sym.sin(y) ...: In [54]: f1(x,y) Out[54]: x*sin(y) + sin(x) In [55]: f1(1,2) Out[55]: sin(1) + sin(2) In [56]: f1(1, np.arange(3) ... SympifyError: Sympify of expression 'could not parse '[0 1 2]'' failed, because of exception being raised: SyntaxError: invalid syntax (<string>, line 1) .

    sym.sin(<array>)
    
    

    np.sin(...) 를 평가할 수 있습니다   In [57]: sym.diff(f1(x,y),x) Out[57]: sin(y) + cos(x) In [58]: sym.diff(f1(x,y),y) Out[58]: x*cos(y) In [59]: sym.diff(sym.diff(f1(x,y),x),y) Out[59]: cos(y) 로 할 수 없었던 배열 입력 . 아마도 subs  치환 된 lambdify 로   In [60]: f2 = sym.lambdify((x,y),f1(x,y),"numpy") In [61]: f2 Out[61]: <function numpy.<lambda>> In [62]: f2(1, np.arange(3)) Out[62]: array([ 0.84147098, 1.68294197, 1.75076841]) 를 위해 .

    사실 f2 를 평가하려고 할 때  상징, f1  불평 :

    sympy
    
    

  • 답변 # 2

    예제 np.sin  다음과 같은 파이썬 함수를 만들었습니다.

    sym.sin
    
    

    여기서 덧셈, 덧셈 및 taking은 원래의 파이썬 함수이기 때문에 numpy 백엔드는 아무런 역할을하지 않습니다. 따라서 f2 에 인수를 전달할 수 있습니다 특히 상징적 인 기호들. numpy 사용해보기  코드 끝에서.

    이제 파이썬 자체가 처리 할 수없는 더 복잡한 표현식을 함수에 포함하면 상황이 바뀝니다. 다음 예제를 보자 :

    In [63]: f2(1,y)
    ...
    /usr/local/lib/python3.5/dist-packages/numpy/__init__.py in <lambda>(_Dummy_30, _Dummy_31)
    AttributeError: 'Symbol' object has no attribute 'sin'
    In [66]: sym.diff(f2(x,y),x)
     ....
    AttributeError: 'Symbol' object has no attribute 'sin'
    
    
    이 예제에서 lambdify는 sin 함수를 비표준 파이썬으로 대체해야합니다. 그렇게하려면 numpy에 의존합니다 (이 경우 정확히 "numpy"를 지정했습니다). 따라서 DerivatifeOff2는 다음과 같습니다

    sym.lambdify
    
    

    그리고 분명히 numpy는 sympy 기호를 처리 할 수 ​​없습니다 ...

    이제 플로팅 만하려면 sympy에 일부 플로팅 모듈 (matplotlib에 의존)이 있습니다 : http://docs.sympy.org/latest/modules/plotting.html

    그걸로 3 차원 작전을 만들 수도 있습니다.

    수정 : 다음도 작동합니다.

    def DerivativeOff(x,y):
        return 2*x + y**2
    
    

  • 답변 # 3

    DerivativeOff  SymPy 표현식을 숫자로 평가할 수있는 함수로 변환하려는 경우 사용해야합니다. 여기에 관심이있는 것은 기호 계산 (차등화)을 수행하는 것이므로 lambdify를 사용해서는 안됩니다 (현재 계산에서).

    문제는이 코드에있다

    DeravativeOff(x,y)
    
    

    변수 이름을 "def fprime (x,y)"와 같은 함수로 설정하면 이러한 변수 이름이 def f2(x,y): return sym.sin(x)*y def fprime2(x,y): return sym.diff(f2(x,y),x) DerivativeOff2 = sym.lambdify((x,y), fprime2(x,y), "numpy") print(DerivativeOff2(1,2)) #will return a number print(DerivativeOff2(x,y)) #will give an error 의 변수 이름을 효과적으로 재정의합니다.  그리고 def DerivativeOff2(x,y): return numpy.cos(x)*y  함수 내부의 모든 코드에 대해 함수 위에 정의됩니다. 따라서 코드 import sympy as sym def f(x,y): return sym.sin(x) + x*sym.sin(y) def fprime(x,y): return sym.diff(f(x,y),y) x, y = sym.symbols('x y') print(fprime(1,y)) #works perfectly fine print(fprime(x,1)) #does not work because it would mean to derive with respect to 1 print(fprime(x,y).subs(y,1)) #works, derives with respect to y, then substitutes 1 for y   lambdify 에서 리턴 된 Symbol 오브젝트에서 작동하지 않습니다. 그러나 x, y = sym.symbols('x y') def fprime(x,y): return sym.diff(f(x,y),x) 에 전달 된 모든 값 . 물론 이러한 객체를 인수로 전달하면 동일하지만 아무 것도 전달할 수 있습니다. x 와 정확히 동일합니다. .

    대신, 나는 함수를 전혀 사용하지 않을 것이다. 오히려 두 개의 상징적 표현을 만드십시오.

    y
    
    

    이제 sym.diff(f(x,y),x) 평가  숫자로, 당신은 symbols('x y') 를 사용할 수 있습니다 .

    fprime
    
    

    이 시점에서 NumPy를 사용하여 표현식을 숫자 또는 숫자 배열로 평가하는 빠른 함수를 작성하려면 여기서 f(x, y) 를 사용하십시오. .

    x, y = sym.symbols('x y')
    expr = x**2 + x*y**2
    fprime = diff(expr, x)
    
    

    (또한 일반적으로 fprime   subs 를 사용한 표현 , 당신은 람피 함수에 대한 인수로 NumPy 배열을 전달해야합니다)

    fprime.subs({x: 1, y: 1})

관련 자료

  • 이전 javascript - 장소 검색 창 | 구글지도
  • 다음 c# - AspNet 동적 페이지에서 정적 HTML 파일 만들기