Как оптимизировать или минимизировать функцию для нескольких массивов в Python?

У меня есть несколько массивов, которым я хотел бы соответствовать экспоненциальной функции в форме, приведенной ниже:

У меня есть пять массивов в MWE, y1, y2, y3 ..., y5; с M и N принимает значения, показанные в MWE. Теперь я хотел бы найти оптимальное значение A, E, m и n, такое, чтобы остатки были минимизированы.

MWE, приведенный ниже, делает это индивидуально для каждого массива y1, или y2, или y3; давая мне (A1, E1, m1, n1), (A2, E2, m2, n2), ... (A5, E5, m5, n5). Как я могу применить оптимизацию для всех массивов таким образом, чтобы для определенного значения A, E, m и n (т. Е. Одинаковые значения A, E, m и n) давало мне наименьшую ошибку?

MWE

from __future__ import division
import numpy as np
from scipy import optimize
import matplotlib.pyplot as plt
def f(params, y, M, N):
    A, E, m, n, = params
    residuals = y - (A * np.exp(E*x/1000) * (M ** m) * (N ** n))
    objective = (residuals**2).sum()
    return objective

x = np.array([1.170, 1.194, 1.223, 1.255, 1.282, 1.325, 1.358, 1.389, 1.435, 1.471])
y_1 = np.array([16.96, 18.45, 20.58, 21.62, 27.22, 33.98, 41.32, 55.64, 72.66, 95.68])
y_2 = np.array([22.74, 25.69, 34.54, 35.77, 40.88, 45.53, 60.12, 72.65, 91.54, 102.58])
y_3 = np.array([26.11, 21.99, 26.88, 31.63, 41.06, 45.47, 59.04, 60.11, 79.79, 97.79])
y_4 = np.array([33.73, 36.01, 35.12, 35.94, 47.02, 56.55, 63.94, 66.78, 96.06, 116.07])
y_5 = np.array([30.87, 33.09, 32.51, 41.72, 42.75, 54.52, 63.02, 78.15, 89.02, 102.54])

M = np.array([40, 20, 20, 15, 12])
N = np.array([0.5, 0.5, 1.0, 1.0, 1.5])

result = optimize.minimize(f, [45, 2000, -1.0, -0.5], y_1)
A1, E1, m1, n1 = result.x
y_predicted_1 = (A1 * np.exp(E1*x/1000) * (40 ** m1) * (0.50 ** n1))

result = optimize.minimize(f, [45, 2000, -1.0, -0.5], y_2)
A2, E2, m2, n2 = result.x
y_predicted_2 = (A2 * np.exp(E2*x/1000) * (40 ** m2) * (0.50 ** n2))

result = optimize.minimize(f, [45, 2000, -1.0, -0.5], y_3)
A3, E3, m3, n3 = result.x
y_predicted_3 = (A3 * np.exp(E3*x/1000) * (40 ** m3) * (0.50 ** n3))

result = optimize.minimize(f, [45, 2000, -1.0, -0.5], y_4)
A4, E4, m4, n4 = result.x
y_predicted_4 = (A4 * np.exp(E4*x/1000) * (40 ** m4) * (0.50 ** n4))

result = optimize.minimize(f, [45, 2000, -1.0, -0.5], y_5)
A5, E5, m5, n5 = result.x
y_predicted_5 = (A5 * np.exp(E5*x/1000) * (40 ** m5) * (0.50 ** n5))

Всего 1 ответ


Вы на самом деле почти там. Просто используйте несколько аргументов в качестве аргумента (работает из-за способа, которым вы создали свой f ):

result = optimize.minimize(f, [45, 2000, -1., -.5], [y_1, y_2, y_3, y_4, y_5])
A_, E_, m_, n_ = result.x
y_predicted_all = (A_ * np.exp(E_*x/1000) * (40 ** m_) * (0.50 ** n_))

Тогда вы получите эти остатки:

Residuals (overall): 
1: 1361.14349
2: 107.87036
3: 165.67150
4: 713.73400
5: 358.97836

Residuals (individual): 
1: 53.10579
2: 72.27874
3: 76.72340
4: 206.37223
5: 60.04984

Так что немного хуже, чем индивидуальные припадки, что и ожидается. Некоторые из них в таком случае довольно хороши, например y_1, но другие могут быть довольно приличными.

введите описание изображения здесь введите описание изображения здесь


Есть идеи?

10000