SciPy (pronúnciase sai pie) é un paquete matemático baseado en numpy que tamén inclúe bibliotecas C e Fortran. SciPy converte a túa sesión interactiva de Python nun ambiente completo de ciencia de datos como MATLAB, IDL, Octave, R ou SciLab.
Neste artigo, analizaremos as técnicas básicas de programación matemática: resolución de problemas de optimización condicional para unha función escalar de varias variables mediante o paquete scipy.optimize. Os algoritmos de optimización sen restricións xa foron discutidos en último artigo. Sempre se pode obter axuda máis detallada e actualizada sobre funcións scipy usando o comando help(), Maiús+Tab ou en documentación oficial.
Introdución
A función proporciona unha interface común para resolver problemas de optimización condicionais e non restrinxidos no paquete scipy.optimize. minimize(). Non obstante, sábese que non existe un método universal para resolver todos os problemas, polo que a elección dun método adecuado, como sempre, recae sobre os ombreiros do investigador.
O algoritmo de optimización apropiado especifícase mediante o argumento da función minimize(..., method="").
Para a optimización condicional dunha función de varias variables, están dispoñibles implementacións dos seguintes métodos:
SLSQP — programación cuadrática secuencial con restricións, método newtoniano para resolver o sistema de Lagrange. Artigo da wiki.
TNC - Newton truncado Constrinxido, número limitado de iteracións, bo para funcións non lineais cun gran número de variables independentes. Artigo da wiki.
L-BFGS-B — un método do equipo Broyden–Fletcher–Goldfarb–Shanno, implementado cun consumo de memoria reducido debido á carga parcial de vectores da matriz de Hesse. Artigo da wiki, artigo sobre Habré.
COBYLA — MARE Optimización restrinxida por aproximación lineal, optimización restrinxida con aproximación lineal (sen cálculo de gradientes). Artigo da wiki.
Dependendo do método elixido, as condicións e restricións para resolver o problema fíxanse de forma diferente:
obxecto de clase Bounds para os métodos L-BFGS-B, TNC, SLSQP, trust-constr;
a lista (min, max) para os mesmos métodos L-BFGS-B, TNC, SLSQP, trust-constr;
un obxecto ou unha lista de obxectos LinearConstraint, NonlinearConstraint para COBYLA, SLSQP, métodos trust-constr;
dicionario ou lista de dicionarios {'type':str, 'fun':callable, 'jac':callable,opt, 'args':sequence,opt} para métodos COBYLA, SLSQP.
Esquema do artigo:
1) Considere o uso dun algoritmo de optimización condicional na rexión de confianza (method="trust-constr") con restricións especificadas como obxectos Bounds, LinearConstraint, NonlinearConstraint ;
2) Considere a programación secuencial usando o método dos mínimos cadrados (método = "SLSQP") con restricións especificadas en forma de dicionario {'type', 'fun', 'jac', 'args'};
3) Analiza un exemplo de optimización de produtos fabricados utilizando o exemplo dun estudo web.
Método de optimización condicional = "trust-constr"
Implementación do método trust-constr baseado en EQSQP para problemas con restricións da forma de igualdade e así VIAXE para problemas con restricións en forma de desigualdades. Ambos métodos son implementados por algoritmos para atopar un mínimo local na rexión de confianza e son moi axeitados para problemas a gran escala.
Formulación matemática do problema de atopar un mínimo en forma xeral:
Para restricións de igualdade estritas, o límite inferior é igual ao límite superior .
Para unha restrición unidireccional, establécese o límite superior ou inferior np.inf co signo correspondente.
Sexa necesario atopar o mínimo dunha función de Rosenbrock coñecida de dúas variables:
Neste caso, establécense as seguintes restricións no seu dominio de definición:
No noso caso, hai unha solución única no punto , para o que só son válidas as restricións primeira e cuarta.
Imos repasar as restricións de abaixo a arriba e ver como podemos escribilas en scipy.
Restricións и imos definilo usando o obxecto Límites.
Ao calcular a matriz de Hesse require moito esforzo, podes usar unha clase HessianUpdateStrategy. As seguintes estratexias están dispoñibles: BFGS и SR1.
A matriz xacobiana para restricións tamén se pode calcular usando diferenzas finitas. Non obstante, neste caso non se pode calcular a matriz de Hesse usando diferenzas finitas. O Hessian debe definirse como unha función ou mediante a clase HessianUpdateStrategy.
Alternativamente, pódense aproximar as derivadas primeira e segunda da función que se está optimizando. Por exemplo, o hessiano pódese aproximar usando a función SR1 (aproximación cuasi newtoniana). O gradiente pódese aproximar mediante diferenzas finitas.
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)
Método de optimización condicional = "SLSQP"
O método SLSQP está deseñado para resolver problemas de minimización dunha función da forma:
Onde и — conxuntos de índices de expresións que describen restricións en forma de igualdades ou desigualdades. — conxuntos de límites inferiores e superiores para o dominio de definición da función.
As restricións lineais e non lineais descríbense en forma de dicionarios con teclas 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])
}
Optimization terminated successfully. (Exit mode 0)
Current function value: 0.34271757499419825
Iterations: 4
Function evaluations: 5
Gradient evaluations: 4
[0.41494475 0.1701105 ]
Exemplo de optimización
En relación coa transición á quinta estrutura tecnolóxica, vexamos a optimización da produción co exemplo dun estudo web, que nos aporta uns ingresos pequenos pero estables. Imaxinémonos como o director dunha galera que produce tres tipos de produtos:
x0 - venda de páxinas de destino, a partir de 10 tr.
x1 - sitios web corporativos, a partir de 20 tr.
x2 - tendas en liña, a partir de 30 tr.
O noso amable equipo de traballo está formado por catro xuvenís, dous medios e un sénior. O seu fondo de tempo de traballo mensual:
Xuño: 4 * 150 = 600 чел * час,
medios: 2 * 150 = 300 чел * час,
señor: 150 чел * час.
Permitir que o primeiro menor dispoñible pase (0, 1, 2) horas no desenvolvemento e implantación dun sitio de tipo (x10, x20, x30), medio - (7, 15, 20), senior - (5, 10, 15). ) horas do mellor momento da túa vida.
Como calquera director normal, queremos maximizar os beneficios mensuais. O primeiro paso para o éxito é escribir a función obxectivo value como a cantidade de ingresos dos produtos producidos ao mes:
E, finalmente, a hipótese máis optimista é que, debido ao baixo prezo e á alta calidade, unha fila de clientes satisfeitos está constantemente facendo cola para nós. Podemos escoller os volumes de produción mensuais nós mesmos, baseándonos en resolver o problema de optimización restrinxido scipy.optimize:
Redondeamos a números enteiros e calculemos a carga mensual de remeiros cunha distribución óptima de produtos x = (8, 6, 3) :
Xuño: 8 * 10 + 6 * 20 + 3 * 30 = 290 чел * час;
medios: 8 * 7 + 6 * 15 + 3 * 20 = 206 чел * час;
señor: 8 * 5 + 6 * 10 + 3 * 15 = 145 чел * час.
Conclusión: para que o director reciba o seu merecido máximo, é óptimo crear 8 landing pages, 6 sitios de tamaño medio e 3 tendas ao mes. Neste caso, o sénior debe arar sen levantar a vista da máquina, a carga dos medios será de aproximadamente 2/3, os xuvenís menos da metade.
Conclusión
O artigo describe as técnicas básicas para traballar co paquete scipy.optimize, usado para resolver problemas de minimización condicional. Persoalmente uso scipy con fins puramente académicos, polo que o exemplo dado é de carácter tan humorístico.
Pódense atopar unha gran cantidade de teoría e exemplos virtuais, por exemplo, no libro de I.L. Akulich "Programación matemática en exemplos e problemas". Aplicación máis hardcore scipy.optimize para construír unha estrutura 3D a partir dun conxunto de imaxes (artigo sobre Habré) pódese ver en libro de receitas scipy.
A principal fonte de información é docs.scipy.orgaqueles que desexen contribuír á tradución desta e doutras seccións scipy Benvido a GitHub.
Grazas mefistofeos para a participación na elaboración da publicación.