SciPy, uboreshaji na masharti

SciPy, uboreshaji na masharti

SciPy (inayotamkwa sai pie) ni kifurushi cha hisabati chenye msingi numpy ambacho pia kinajumuisha maktaba za C na Fortran. SciPy hubadilisha kipindi chako shirikishi cha Python kuwa mazingira kamili ya sayansi ya data kama MATLAB, IDL, Octave, R, au SciLab.

Katika makala hii, tutaangalia mbinu za msingi za programu ya hisabati - kutatua matatizo ya uboreshaji wa masharti kwa kazi ya scalar ya vigezo kadhaa kwa kutumia mfuko wa scipy.optimize. Kanuni za uboreshaji zisizo na kikomo tayari zimejadiliwa makala ya mwisho. Usaidizi wa kina na wa kisasa zaidi juu ya vitendaji vya scipy unaweza kupatikana kila wakati kwa kutumia help() amri, Shift+Tab au katika nyaraka rasmi.

Utangulizi

Kiolesura cha kawaida cha kutatua matatizo ya uboreshaji ya masharti na yasiyozuiliwa katika kifurushi cha scipy.optimize hutolewa na chaguo la kukokotoa. minimize(). Walakini, inajulikana kuwa hakuna njia ya ulimwengu wote ya kutatua shida zote, kwa hivyo uchaguzi wa njia ya kutosha, kama kawaida, huanguka kwenye mabega ya mtafiti.
Algorithm inayofaa ya uboreshaji imebainishwa kwa kutumia hoja ya kukokotoa minimize(..., method="").
Kwa uboreshaji wa masharti ya kazi ya anuwai kadhaa, utekelezaji wa njia zifuatazo zinapatikana:

  • trust-constr - tafuta kiwango cha chini cha ndani katika eneo la uaminifu. Makala ya Wiki, makala kuhusu Habre;
  • SLSQP - upangaji wa mpangilio wa quadratic na vikwazo, njia ya Newton ya kutatua mfumo wa Lagrange. Makala ya Wiki.
  • TNC - Newton Iliyopunguzwa Inadhibitiwa, idadi ndogo ya marudio, nzuri kwa vitendakazi visivyo na mstari na idadi kubwa ya vigeu vinavyojitegemea. Makala ya Wiki.
  • L-BFGS-B - mbinu kutoka kwa timu ya Broyden-Fletcher-Goldfarb-Shanno, iliyotekelezwa na utumiaji wa kumbukumbu uliopunguzwa kwa sababu ya upakiaji wa vekta kutoka kwa tumbo la Hessian. Makala ya Wiki, makala kuhusu Habre.
  • COBYLA - Uboreshaji Uliobanwa wa MARE Kwa Ukadiriaji wa Linear, uboreshaji uliozuiliwa na ukadiriaji wa mstari (bila hesabu ya upinde rangi). Makala ya Wiki.

Kulingana na njia iliyochaguliwa, masharti na vizuizi vya kutatua shida huwekwa tofauti:

  • kitu cha darasa Bounds kwa mbinu L-BFGS-B, TNC, SLSQP, trust-constr;
  • orodha (min, max) kwa njia sawa L-BFGS-B, TNC, SLSQP, trust-constr;
  • kitu au orodha ya vitu LinearConstraint, NonlinearConstraint kwa COBYLA, SLSQP, njia za uaminifu-constr;
  • kamusi au orodha ya kamusi {'type':str, 'fun':callable, 'jac':callable,opt, 'args':sequence,opt} kwa COBYLA, mbinu za SLSQP.

Muhtasari wa makala:
1) Zingatia utumiaji wa kanuni ya uboreshaji wa masharti katika eneo la uaminifu (mbinu = "trust-constr") iliyo na vizuizi vilivyoainishwa kama vitu. Bounds, LinearConstraint, NonlinearConstraint ;
2) Zingatia upangaji mpangilio kwa kutumia mbinu ya miraba ndogo zaidi (mbinu = "SLSQP") na vizuizi vilivyobainishwa katika mfumo wa kamusi. {'type', 'fun', 'jac', 'args'};
3) Chambua mfano wa uboreshaji wa bidhaa za viwandani kwa kutumia mfano wa studio ya wavuti.

Mbinu ya uboreshaji wa masharti="trust-constr"

Utekelezaji wa mbinu trust-constr kulingana na EQSQP kwa matatizo na vikwazo vya aina ya usawa na kuendelea TRIP kwa matatizo na vikwazo kwa namna ya kutofautiana. Njia zote mbili zinatekelezwa na algoriti za kupata kiwango cha chini cha ndani katika eneo la kujiamini na zinafaa kwa shida kubwa.

Uundaji wa hisabati wa shida ya kupata kiwango cha chini katika fomu ya jumla:

SciPy, uboreshaji na masharti

SciPy, uboreshaji na masharti

SciPy, uboreshaji na masharti

Kwa vikwazo vikali vya usawa, mipaka ya chini imewekwa sawa na ya juu SciPy, uboreshaji na masharti.
Kwa kizuizi cha njia moja, kikomo cha juu au cha chini kinawekwa np.inf na ishara inayolingana.
Wacha iwe muhimu kupata kiwango cha chini cha kazi inayojulikana ya Rosenbrock ya anuwai mbili:

SciPy, uboreshaji na masharti

Katika kesi hii, vikwazo vifuatavyo vimewekwa kwenye kikoa chake cha ufafanuzi:

SciPy, uboreshaji na masharti

SciPy, uboreshaji na masharti

SciPy, uboreshaji na masharti

SciPy, uboreshaji na masharti

SciPy, uboreshaji na masharti

SciPy, uboreshaji na masharti

Kwa upande wetu, kuna suluhisho la kipekee kwa uhakika SciPy, uboreshaji na masharti, ambayo vikwazo vya kwanza na vya nne tu ni halali.
Hebu tupitie vikwazo kutoka chini hadi juu na tuangalie jinsi tunaweza kuziandika kwa scipy.
Vikwazo SciPy, uboreshaji na masharti ΠΈ SciPy, uboreshaji na masharti wacha tuifafanue kwa kutumia kitu cha Mipaka.

from scipy.optimize import Bounds
bounds = Bounds ([0, -0.5], [1.0, 2.0])

Vikwazo SciPy, uboreshaji na masharti ΠΈ SciPy, uboreshaji na masharti Wacha tuandike kwa njia ya mstari:

SciPy, uboreshaji na masharti

Wacha tufafanue vizuizi hivi kama kitu cha LinearConstraint:

import numpy as np
from scipy.optimize import LinearConstraint
linear_constraint = LinearConstraint ([[1, 2], [2, 1]], [-np.inf, 1], [1, 1])

Na mwishowe kizuizi kisicho cha mstari katika fomu ya matrix:

SciPy, uboreshaji na masharti

Tunafafanua matrix ya Jacobian kwa kizuizi hiki na mchanganyiko wa mstari wa tumbo la Hessian na vekta ya kiholela. SciPy, uboreshaji na masharti:

SciPy, uboreshaji na masharti

SciPy, uboreshaji na masharti

Sasa tunaweza kufafanua kizuizi kisicho na mstari kama kitu NonlinearConstraint:

from scipy.optimize import NonlinearConstraint

def cons_f(x):
     return [x[0]**2 + x[1], x[0]**2 - x[1]]

def cons_J(x):
     return [[2*x[0], 1], [2*x[0], -1]]

def cons_H(x, v):
     return v[0]*np.array([[2, 0], [0, 0]]) + v[1]*np.array([[2, 0], [0, 0]])

nonlinear_constraint = NonlinearConstraint(cons_f, -np.inf, 1, jac=cons_J, hess=cons_H)

Ikiwa saizi ni kubwa, matrices pia yanaweza kubainishwa kwa fomu ndogo:

from scipy.sparse import csc_matrix

def cons_H_sparse(x, v):
     return v[0]*csc_matrix([[2, 0], [0, 0]]) + v[1]*csc_matrix([[2, 0], [0, 0]])

nonlinear_constraint = NonlinearConstraint(cons_f, -np.inf, 1,
                                            jac=cons_J, hess=cons_H_sparse)

au kama kitu LinearOperator:

from scipy.sparse.linalg import LinearOperator

def cons_H_linear_operator(x, v):
    def matvec(p):
        return np.array([p[0]*2*(v[0]+v[1]), 0])
    return LinearOperator((2, 2), matvec=matvec)

nonlinear_constraint = NonlinearConstraint(cons_f, -np.inf, 1,
                                jac=cons_J, hess=cons_H_linear_operator)

Wakati wa kuhesabu tumbo la Hessian SciPy, uboreshaji na masharti inahitaji juhudi nyingi, unaweza kutumia darasa HessianUpdateStrategy. Mikakati ifuatayo inapatikana: BFGS ΠΈ SR1.

from scipy.optimize import BFGS

nonlinear_constraint = NonlinearConstraint(cons_f, -np.inf, 1, jac=cons_J, hess=BFGS())

Hessian pia inaweza kuhesabiwa kwa kutumia tofauti za kikomo:

nonlinear_constraint = NonlinearConstraint (cons_f, -np.inf, 1, jac = cons_J, hess = '2-point')

Matrix ya Jacobian kwa vikwazo pia inaweza kuhesabiwa kwa kutumia tofauti za kikomo. Walakini, katika kesi hii matrix ya Hessian haiwezi kuhesabiwa kwa kutumia tofauti za kikomo. Hessian lazima ifafanuliwe kama chaguo za kukokotoa au kutumia darasa la HessianUpdateStrategy.

nonlinear_constraint = NonlinearConstraint (cons_f, -np.inf, 1, jac = '2-point', hess = BFGS ())

Suluhisho la shida ya utoshelezaji inaonekana kama hii:

from scipy.optimize import minimize
from scipy.optimize import rosen, rosen_der, rosen_hess, rosen_hess_prod

x0 = np.array([0.5, 0])
res = minimize(rosen, x0, method='trust-constr', jac=rosen_der, hess=rosen_hess,
                constraints=[linear_constraint, nonlinear_constraint],
                options={'verbose': 1}, bounds=bounds)
print(res.x)

`gtol` termination condition is satisfied.
Number of iterations: 12, function evaluations: 8, CG iterations: 7, optimality: 2.99e-09, constraint violation: 1.11e-16, execution time: 0.033 s.
[0.41494531 0.17010937]

Ikiwa ni lazima, kazi ya kuhesabu Hessian inaweza kufafanuliwa kwa kutumia darasa la LinearOperator

def rosen_hess_linop(x):
    def matvec(p):
        return rosen_hess_prod(x, p)
    return LinearOperator((2, 2), matvec=matvec)

res = minimize(rosen, x0, method='trust-constr', jac=rosen_der, hess=rosen_hess_linop,
                 constraints=[linear_constraint, nonlinear_constraint],
                 options={'verbose': 1}, bounds=bounds)

print(res.x)

au bidhaa ya Hessian na vekta ya kiholela kupitia kigezo hessp:

res = minimize(rosen, x0, method='trust-constr', jac=rosen_der, hessp=rosen_hess_prod,
                constraints=[linear_constraint, nonlinear_constraint],
                options={'verbose': 1}, bounds=bounds)
print(res.x)

Vinginevyo, viini vya kwanza na vya pili vya chaguo za kukokotoa vinavyoboreshwa vinaweza kukadiriwa. Kwa mfano, Hessian inaweza kukadiriwa kwa kutumia chaguo la kukokotoa SR1 (makadirio ya nusu-Newtonian). Upinde rangi unaweza kukadiriwa na tofauti zenye kikomo.

from scipy.optimize import SR1
res = minimize(rosen, x0, method='trust-constr',  jac="2-point", hess=SR1(),
               constraints=[linear_constraint, nonlinear_constraint],
               options={'verbose': 1}, bounds=bounds)
print(res.x)

Mbinu ya uboreshaji wa masharti="SLSQP"

Njia ya SLSQP imeundwa kutatua shida za kupunguza kazi katika fomu:

SciPy, uboreshaji na masharti

SciPy, uboreshaji na masharti

SciPy, uboreshaji na masharti

SciPy, uboreshaji na masharti

Je! SciPy, uboreshaji na masharti ΠΈ SciPy, uboreshaji na masharti - seti za fahirisi za maneno zinazoelezea vikwazo kwa namna ya usawa au usawa. SciPy, uboreshaji na masharti - seti za mipaka ya chini na ya juu kwa kikoa cha ufafanuzi wa chaguo la kukokotoa.

Vikwazo vya mstari na visivyo vya mstari vinaelezewa kwa namna ya kamusi zilizo na funguo type, fun ΠΈ jac.

ineq_cons = {'type': 'ineq',
             'fun': lambda x: np.array ([1 - x [0] - 2 * x [1],
                                          1 - x [0] ** 2 - x [1],
                                          1 - x [0] ** 2 + x [1]]),
             'jac': lambda x: np.array ([[- 1.0, -2.0],
                                          [-2 * x [0], -1.0],
                                          [-2 * x [0], 1.0]])
            }

eq_cons = {'type': 'eq',
           'fun': lambda x: np.array ([2 * x [0] + x [1] - 1]),
           'jac': lambda x: np.array ([2.0, 1.0])
          }

Utafutaji wa kiwango cha chini unafanywa kama ifuatavyo:

x0 = np.array([0.5, 0])
res = minimize(rosen, x0, method='SLSQP', jac=rosen_der,
               constraints=[eq_cons, ineq_cons], options={'ftol': 1e-9, 'disp': True},
               bounds=bounds)

print(res.x)

Optimization terminated successfully.    (Exit mode 0)
            Current function value: 0.34271757499419825
            Iterations: 4
            Function evaluations: 5
            Gradient evaluations: 4
[0.41494475 0.1701105 ]

Mfano wa Uboreshaji

Kuhusiana na mpito kwa muundo wa tano wa kiteknolojia, hebu tuangalie uboreshaji wa uzalishaji kwa kutumia mfano wa studio ya mtandao, ambayo hutuletea mapato madogo lakini imara. Wacha tujiwazie kama mkurugenzi wa gali ambayo hutoa aina tatu za bidhaa:

  • x0 - kuuza kurasa za kutua, kutoka 10 tr.
  • x1 - tovuti za ushirika, kutoka 20 tr.
  • x2 - maduka ya mtandaoni, kutoka 30 tr.

Timu yetu ya kazi ya kirafiki inajumuisha vijana wanne, wa kati wawili na mwandamizi mmoja. Hazina yao ya kila mwezi ya wakati wa kufanya kazi:

  • Juni: 4 * 150 = 600 Ρ‡Π΅Π» * час,
  • kati: 2 * 150 = 300 Ρ‡Π΅Π» * час,
  • seneta: 150 Ρ‡Π΅Π» * час.

Acha mtoto wa kwanza anayepatikana atumie (0, 1, 2) masaa katika ukuzaji na usambazaji wa tovuti moja ya aina (x10, x20, x30), katikati - (7, 15, 20), mwandamizi - (5, 10, 15). ) masaa ya wakati mzuri wa maisha yako.

Kama mkurugenzi yeyote wa kawaida, tunataka kuongeza faida ya kila mwezi. Hatua ya kwanza ya mafanikio ni kuandika kazi ya lengo value kama kiasi cha mapato kutoka kwa bidhaa zinazozalishwa kwa mwezi:

def value(x):
    return - 10*x[0] - 20*x[1] - 30*x[2]

Hili sio kosa; wakati wa kutafuta kiwango cha juu, chaguo la kukokotoa la lengo linapunguzwa kwa ishara tofauti.

Hatua inayofuata ni kuwakataza wafanyikazi wetu kufanya kazi kupita kiasi na kuanzisha vizuizi vya saa za kazi:

SciPy, uboreshaji na masharti

Ni nini kinacholingana:

SciPy, uboreshaji na masharti

ineq_cons = {'type': 'ineq',
             'fun': lambda x: np.array ([600 - 10 * x [0] - 20 * x [1] - 30 * x[2],
                                         300 - 7  * x [0] - 15 * x [1] - 20 * x[2],
                                         150 - 5  * x [0] - 10 * x [1] - 15 * x[2]])
            }

Kizuizi rasmi ni kwamba pato la bidhaa lazima liwe chanya tu:

bnds = Bounds ([0, 0, 0], [np.inf, np.inf, np.inf])

Na hatimaye, dhana ya kupendeza zaidi ni kwamba kwa sababu ya bei ya chini na ubora wa juu, foleni ya wateja walioridhika inatupanga kila wakati. Tunaweza kuchagua kiasi cha uzalishaji cha kila mwezi sisi wenyewe, kulingana na kutatua tatizo la uboreshaji lililodhibitiwa scipy.optimize:

x0 = np.array([10, 10, 10])
res = minimize(value, x0, method='SLSQP', constraints=ineq_cons, bounds=bnds)
print(res.x)

[7.85714286 5.71428571 3.57142857]

Wacha tuzunguke kwa urahisi kwa nambari nzima na tuhesabu mzigo wa kila mwezi wa wapiga makasia na usambazaji bora wa bidhaa. x = (8, 6, 3) :

  • Juni: 8 * 10 + 6 * 20 + 3 * 30 = 290 Ρ‡Π΅Π» * час;
  • kati: 8 * 7 + 6 * 15 + 3 * 20 = 206 Ρ‡Π΅Π» * час;
  • seneta: 8 * 5 + 6 * 10 + 3 * 15 = 145 Ρ‡Π΅Π» * час.

Hitimisho: ili mkurugenzi apate kiwango chake cha juu kinachostahili, ni bora kuunda kurasa 8 za kutua, tovuti 6 za ukubwa wa kati na maduka 3 kwa mwezi. Katika kesi hiyo, mwandamizi lazima alime bila kuangalia juu kutoka kwa mashine, mzigo wa katikati utakuwa takriban 2/3, vijana chini ya nusu.

Hitimisho

Nakala hiyo inaelezea mbinu za msingi za kufanya kazi na kifurushi scipy.optimize, kutumika kutatua matatizo ya kupunguza masharti. Binafsi natumia scipy kwa madhumuni ya kielimu tu, ndiyo maana mfano uliotolewa ni wa hali ya ucheshi.

Nadharia nyingi na mifano halisi inaweza kupatikana, kwa mfano, katika kitabu cha I.L. Akulich "Programu ya hisabati katika mifano na matatizo." Programu ngumu zaidi scipy.optimize kuunda muundo wa 3D kutoka kwa seti ya picha (makala kuhusu Habre) inaweza kutazamwa ndani scipy-cookbook.

Chanzo kikuu cha habari ni docs.scipy.orgwanaotaka kuchangia katika tafsiri ya sehemu hii na nyinginezo scipy Karibu GitHub.

Shukrani mephistophees kwa ajili ya kushiriki katika maandalizi ya uchapishaji.

Chanzo: mapenzi.com

Kuongeza maoni