Одновременная оптимизация двух разных функций, чтобы обеспечить универсальное решение для обоих - PullRequest
0 голосов
/ 15 апреля 2020

В январе я задал похожий вопрос , на который @ Miłosz Wieczór был любезен ответить. Теперь я столкнулся с аналогичной, но другой проблемой, поскольку мне нужно одновременно разместить два параметра (fc и alpha) в двух наборах данных (e_exp и iq_exp). Мне в основном нужно найти значения fc и alpha, которые лучше всего подходят для данных e_exp и iq_exp.

import numpy as np
import math
from scipy.optimize import curve_fit, least_squares, minimize

f_exp  = np.array([1, 1.6, 2.7, 4.4, 7.3, 12, 20, 32, 56, 88, 144, 250000])
e_exp  = np.array([7.15, 7.30, 7.20, 7.25, 7.26, 7.28, 7.32, 7.25, 7.35, 7.34, 7.37, 11.55])
iq_exp = np.array([0.010, 0.009, 0.011, 0.011, 0.010, 0.012, 0.019, 0.027, 0.038, 0.044, 0.052, 0.005])

ezero  = np.min(e_exp)
einf   = np.max(e_exp)

ig_fc     = 500
ig_alpha  = 0.35

def CCRI(f_exp, fc, alpha):
    x   = np.log(f_exp/fc)
    R  = ezero + 1/2 * (einf - ezero) * (1 + np.sinh((1 - alpha) * x) / (np.cosh((1 - alpha) * x) + np.sin(1/2 * alpha * math.pi)))
    I  = 1/2 * (einf - ezero) * np.cos(alpha * math.pi / 2) / (np.cosh((1 - alpha) * x) + np.sin(alpha * math.pi / 2))
    RI = np.sqrt(R ** 2 + I ** 2)
    return RI

def CCiQ(f_exp, fc, alpha):
    x   = np.log(f_exp/fc)
    R  = ezero + 1/2 * (einf - ezero) * (1 + np.sinh((1 - alpha) * x) / (np.cosh((1 - alpha) * x) + np.sin(1/2 * alpha * math.pi)))
    I  = 1/2 * (einf - ezero) * np.cos(alpha * math.pi / 2) / (np.cosh((1 - alpha) * x) + np.sin(alpha * math.pi / 2))
    iQ = I / R
    return iQ

poptRI, pcovRI = curve_fit(CCRI, f_exp, e_exp, p0=(ig_fc, ig_alpha))

poptiQ, pcoviQ = curve_fit(CCiQ, f_exp, iq_exp, p0=(ig_fc, ig_alpha))

einf, ezero и f_exp все константы плюс переменные, которые мне нужно оптимизировать, это ig_fc и ig_alpha, в которых ig обозначает начальное предположение. В приведенном выше коде я получаю два разных значения fc и alpha, потому что я решаю их независимо. Однако мне нужно решить их одновременно, чтобы fc и alpha были универсальными.

  • Есть ли способ решить две разные функции, чтобы обеспечить универсальные решения для fc и alpha?

1 Ответ

1 голос
/ 15 апреля 2020

Состояние документов для второго возвращаемого значения из curve_fit :

pcov

Расчетная ковариация поп. Диагонали обеспечивают дисперсию оценки параметра. Чтобы вычислить одно стандартное отклонение ошибок по параметрам, используйте perr = np.sqrt(np.diag(pcov)).

Поэтому, если вы хотите минимизировать общую ошибку, вам нужно объединить ошибки обоих ваших подгонок.

def objective(what, ever):

    poptRI, pcovRI = curve_fit(CCRI, f_exp, e_exp, p0=(ig_fc, ig_alpha))

    poptiQ, pcoviQ = curve_fit(CCiQ, f_exp, iq_exp, p0=(ig_fc, ig_alpha))

    # not sure if this the correct equation, but you can start with it
    err_total = np.sum(np.sqrt(np.diag(pcovRI))) + np.sum(np.sqrt(np.diag(pcoviQ)))

    return err_total

Об общих ошибках 2d гауссовых функций:

https://www.visiondummy.com/2014/04/draw-error-ellipse-representing-covariance-matrix/

Обновление: поскольку вы хотите, чтобы poptRI и poptiQ были одинаковыми, вы нужно минимизировать их расстояние.

Это можно сделать, как

from numpy import linalg

def objective(what, ever):

    poptRI, pcovRI = curve_fit(CCRI, f_exp, e_exp, p0=(ig_fc, ig_alpha))

    poptiQ, pcoviQ = curve_fit(CCiQ, f_exp, iq_exp, p0=(ig_fc, ig_alpha))

    delta = linalg.norm(poptiQ - poptRI)
    return delta

Минимизация этой функции приведет (должна) привести к аналогичным значениям для poptRI и poptiQ. Вы берете параметры как векторы и пытаетесь минимизировать длину их дельта-вектора.

Однако этот подход предполагает, что poptRI и poptiQ (и их коэффициенты) находятся примерно в одном диапазоне, так как вы используют некоторые метри c на них. Если, скажем, один, если они находятся в диапазоне 2000, а другой в диапазоне 2. Тогда оптимизатор предпочтет настроить первый. Но, возможно, это нормально.

Если вы как-то хотите относиться к ним одинаково, вам нужно нормализовать их. Один подход (при условии, что все коэффициенты одинаковы) может быть

linalg.norm((poptiQ / linalg.norm(poptiQ)) - (poptRI / linalg.norm(poptRI))))

. Вы нормализуете результаты по единичным векторам, затем вычитаете их, затем создаете норму.

То же самое верно для входных данных. к функции, но это может быть не так важно, там. См. Ссылки ниже.

Но это сильно зависит от проблемы, которую вы пытаетесь решить. Не существует общего решения.

Некоторые ссылки, связанные с этим:

Является ли нормализация полезной / необходимой в оптимизации?

Почему мы Нужно ли нормализовать вход для искусственной нейронной сети?

Еще одна целевая функция:

Это то, что вы пытаетесь сделать? Вы хотите найти лучшие fc и alpha, чтобы результаты подгонки обеих функций были как можно ближе?

def objective(fc, alpha):

    poptRI, pcovRI = curve_fit(CCRI, f_exp, e_exp, p0=(fc, alpha))

    poptiQ, pcoviQ = curve_fit(CCiQ, f_exp, iq_exp, p0=(fc, alpha))

    delta = linalg.norm(poptiQ - poptRI)
    return delta
...