scipy.optimize.minimize에서 constraints 옵션을 제공하는 방법과 의미

제한된 최소화 문제를 scipy.optimize.minimize로 해결



scipy에는 minimize이라는 주어진 목적 함수 값을 현명하게 최소화하는 함수가 들어 있습니다.
주로 선형계획법 따로 사용되는 경우가 많습니다.

최소화에도
  • 가능한 값이 연속 OR 이산
  • 함수가 선형 OR 비선형
  • 변수의 차원이 하나 OR 복수
  • 제약 조건 있음 OR 없음

  • 같은 패턴이 있으며 그에 따라 최적의 알고리즘을 선택해야합니다.
    이러한 알고리즘은 후술하는 바와 같이 method 옵션에 캐릭터 라인으로 건네주는 것으로 지정할 수 있습니다.

    이번은 제약이 있는 비선형 최적화 문제를 다루는 경우의 이야기입니다.
    제약 조건부 비선형 최소화 문제를 다루는 알고리즘은 코빌라SLSQP 의 2 개입니다.
    호출은 다음과 같이 합니다.

    minimize 함수 호출 예
    from scipy.optimize import minimize
    
    result = minimize(func, x0=x, constraints=cons, method="SLSQP")
    

    여기서 func는 목적 함수에 대한 참조이고 x0는 해 찾기를 시작하는 시작점의 좌표입니다.
    constraints 가 제약을 주는 옵션이 되어 있어 내용적으로는 이하와 같은 딕셔너리를 건네줍니다.
    type은 제약 조건이 등호(eq)인지 부등호(ineq)인지를 나타내는 것입니다.

    제약 조건의 예 (이것은 적용 가능)
    cons = (
        {'type': 'ineq', 'fun': cons(x)},
        {'type': 'eq', lambda: x: x ** 2 - 2 * x + 1}
    )
    

    제약 조건 constraints를 줄 때의 질문



    그러나이 constraints 옵션의 사용법이 잘못 몰랐습니다.
    구체적으로 말하면
  • eq/ineq 는 무엇과 같거나 같지 않은 것을 나타내고 있는가??
  • ineq 의 부등호는 어느쪽으로 향하고 있는 것인가??

  • 라는 의문이 있었습니다.

    결론



    이 점은 공식 참조에 제대로 쓰여졌습니다.

    Equality constraint means that the constraint function result is to be zero whereas inequality means that it is to be non-negative. Note that COBYLA only supports inequality constraints.

    (역) 등호 제약 ( eq을 지정한 경우)은 주어진 제약 조건식의 값이 0과 같아지는 것을 의미하지만, 한편으로 부등호 제약 ( ineq를 지정한 경우)은 식의 값 가 음이 아닌 것을 의미합니다. COBYLA는 부등호 제약만 지원합니다.


    x \leq -1
    

    같은 부등호 제약의 경우, 한 번 좌변에 식을 올려 버려
    g(x) = x + 1
    

    그런 다음
    g(x) \leq 0
    

    라고 생각합니다.
    이 $g(x)$ 를 'type': 'ineq' 로 건네주는 것으로 "$g(x)$는 비음이야"라는 조건이 되어, 당초의 목적을 달성합니다.

    이상에서
  • eq/ineq는 각각 0과 같고 0 이상 (비 음수)임을 나타냅니다.
  • ineq 의 부등호는 항상 「$(준식)\geq 0$」가 된다

  • 너무 일본어로 번역 정보가 없었기 때문에 메모를 써 두었습니다.

    프로그램을 짜다



    그럼 실제로 프로그램을 짜 봅시다.
    이번에는 설명의 굳이 scipy를 사용할 때까지 없는 2차 함수의 최소화를 해보겠습니다.
    \underset{x}{minimize} \: f(x) = x^2\\
    s.t. x \leq -1
    

    그래프에 나타내면 이런 느낌으로 $(x,y) = (-1, 1)$이 해가 될 것입니다.



    우선 문제의 목적 함수 $f(x)$입니다.
    def func(x):
        return x**2
    

    이것은 간단합니다.

    다음에 제약 조건입니다만, 이쪽도 함수로 해 줍니다.
    간단한 식이라면 lambda로 줄 수 있지만, 이번에는 굳이 전자의 방식으로 하기 때문에
    def cons(x):
        return -(x + 1)
    

    와 같이, 최종적으로 이하와 같습니다.

    constraints_sample.py
    from scipy.optimize import minimize
    
    # 目的関数
    def func(x):
        return x ** 2
    
    # 制約条件式
    def cons(x):
        return -(x + 1)
    
    # 制約条件式が非負となるようにする
    cons = (
        {'type': 'ineq', 'fun': cons}
    )
    x = -10 # 初期値は適当
    
    result = minimize(func, x0=x, constraints=cons, method="SLSQP")
    print(result)
    

    결과로 (x, fun) = (-1,1) 를 얻으면 성공입니다.
    > python constraints_sample.py
        njev: 2
      status: 0
         fun: array([ 1.])
           x: array([-1.])
         nit: 2
     success: True
     message: 'Optimization terminated successfully.'
         jac: array([-1.99999999,  0.        ])
        nfev: 6
    

    물론 차원이 늘어난 경우도 numpy.array 등으로 취급할 수 있습니다.

    참고


  • scipy.optimize.minimize - SciPy v0.16.1 Reference Guide
  • 다중 변수 스칼라 함수의 제한된 로컬 최적화 org-기술
  • 좋은 웹페이지 즐겨찾기