Pregunta

Soy nuevo en la optimización. Estoy tratando de resolver un problema lineal de mínimos cuadrados usando el fmin_slsqp función en scipy.optimize.

Tengo la función objetivo como Frobenius Norm de |q0_T*P-q1_T| cuadrado, donde q0_T es la transposición de un nX1 vector y P es nXn matriz y q1_T es una transposición de un nX1 vector. Este es básicamente un proceso de Markov con q vectores como la probabilidad de estar en un estado y P siendo la matriz de las probabilidades de transición.

La función objetivo se minimizaría WRT P donde están las limitaciones:

1) Todos los elementos en P debe ser no negativo

2) Todas las filas en P Debe sumar a 1

He definido esta función objetivo que no estoy seguro es correcta:

def func(P, q):
  return (np.linalg.norm(np.dot(transpose(q[0,]),P)-transpose(q[1,])))**2

El segundo argumento en fmin_slsqp pide un 1D NDarray X0, que es la suposición inicial para la variable independiente. Pero aquí, dado que mi variable independiente sería P, necesitaría una matriz 2D para mi suposición inicial. No estoy seguro de si estoy enmarcando el problema correctamente o tendré que usar otra función. Gracias.

¿Fue útil?

Solución

Por lo tanto, hay un problema en que solo acepta una matriz 1D como la variable independiente, una solución hackish sería pasarla como 1D y remodelar en la función.

import numpy as np
from scipy.optimize import fmin_slsqp

# some fake data
d = 3 # dimensionality of the problem
P0 = np.arange(d*d).reshape(d, d)
P0 /= P0.sum(1, keepdims=True) # so that each row sums to 1
q = np.random.rand(2, d)       # assuming this is the structure of your q
q /= q.sum(1, keepdims=True)

# the function to minimize
def func(P, q):
    n = q.shape[-1] # or n = np.sqrt(P.size)
    P = P.reshape(n, n)
    return np.linalg.norm(np.dot(q[0], P) - q[1])**2  # no changes here, just simplified syntax

def row_sum(P0, q):
    """ row sums - 1 are zero """
    n = np.sqrt(P0.size)
    return P0.reshape(n,n).sum(1) - 1.

def non_neg(P0, q):
    """ all elements >= 0 """
    return P0

P_opt = fmin_slsqp(func, P0.ravel(), args=(q,), f_eqcons=row_sum, f_ieqcons=non_neg).reshape(d, d)

assert np.allclose(P_opt.sum(1), 1)
assert np.all(P_opt >= 0)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top