Оптимизация параметров с весами

Для этой функции:

import numpy as np

def my_function(param1 , param2 , param3 , param4) : 
    return param1 + 3*param2 + 5*param3 + np.power(5 , 3) + np.sqrt(param4)

print(my_function(1,2,3,4))

Это печатает 134,0

Как вернуть 100 вместо 134,0 или максимально близкое значение к 6 со следующими условиями параметров my_function: param1 должен быть в диапазоне 10-20, param2 должен быть в диапазоне 20-30, param3 должен быть в диапазоне 30-40, param4 должен быть в диапазоне 40-50

Я не прошу конкретных решений этой проблемы, но в какую область она попадает? Чтение https://docs.scipy.org/doc/scipy/reference/tutorial/optimize.html и оптимизация параметров в Python предполагают, что это возможно с Готовые решения (в малых размерах). Можно ли применить генетическое программирование к этой проблеме?


comment
Это задача нелинейной оптимизации. en.wikipedia.org/wiki/Nonlinear_programming Здесь есть набор инструментов для алгоритмов, а GA — нет. Ваш выбор.   -  person BadZen    schedule 21.02.2018
comment
param3 никогда не используется.   -  person sascha    schedule 21.02.2018
comment
Если вы спрашиваете, как решить value = my_function , это можно рассматривать как алгоритм поиска корня (очень связанный с оптимизацией). Вы можете посмотреть scipy docs.scipy.org/doc/scipy -0.18.1/reference/optimize.html   -  person jman    schedule 21.02.2018
comment
@BadZen благодарит что-то вроде: stackoverflow.com/questions/21765794 / также мне любопытно, почему бы не рекомендовать GA? Использование GA может инициализировать вес набором случайных значений в пределах диапазона, и GA должен найти оптимальный набор весов, который минимизирует функцию ?   -  person blue-sky    schedule 21.02.2018
comment
1) Это в наивной форме неограниченная оптимизация (с ограничениями). Гораздо проще, чем стесненный опт. 2) ГА — это просто (личное мнение: глупость) неполная эвристика без формальных гарантий, которая работает только в ограниченной априорно анализируемой области, будучи при этом хорошо настроенной. 3) Поскольку это выглядит невыпукло, вам нужно решить, подходят ли решения с локальными опциями (просто) или нужны глобальные опции (не так просто).   -  person sascha    schedule 21.02.2018
comment
Что @sascha только что сказал. :) Вы сказали, что вас интересует не конкретно эта проблема, а своего рода проблема. Я мог бы допустить, что алгоритмы становятся более специализированными/легче решать/более конкретными, чем больше вы ограничиваете проблемное пространство определенными способами меньше, чем я должен был...   -  person BadZen    schedule 21.02.2018
comment
Я мог бы добавить, что этот пример бесполезен, так как решение со всеми переменными @нижняя граница будет лучшим для обоих ваших значений примера.   -  person sascha    schedule 21.02.2018
comment
@sascha установка param1 на 10, param2 на 20, param3 на 30, param4 на 40 является оптимальным решением для этого примера? Это то, что подразумевается под установкой всех 'vars @нижняя граница'?   -  person blue-sky    schedule 21.02.2018
comment
Конечно. Каждый компонент влияет на результат только в возрастающей степени. Использование всех нижних границ дает минимальную цель с учетом этих границ. И эта цель все еще далека от того, что вы хотите.   -  person sascha    schedule 21.02.2018


Ответы (3)


По сути, вы хотите минимизировать ошибку между оценкой и реальной функцией.

EDIT: Очевидным выбором здесь является использование градиентного спуска по 4 параметрам. Если вы не хотите этого делать и просите более прагматичное решение, вот оно.

Основная проблема здесь в том, что есть 4 параметра. Чтобы решить эту проблему, вы можете сделать это:

  1. Исправьте любые 3 параметра, оставьте последний без изменений. Попробуем найти это значение.
  2. Найдите обратную функцию и решите ее либо явно, либо с помощью решателя (это может быть численный метод, такой как метод Ньютона-Рафсона или метод Брента).

Я опишу процесс, чтобы продемонстрировать эту идею. Мы будем использовать scalar_minimizer от scipy, который использует метод Брента.

Для обсуждения давайте сохраним вашу функцию, состоящую из 2 параметров, и предположим, что ваша функция:

def f(p1, p2):
    return p1 + np.sqrt(p2)

вы в основном спрашиваете, как найти и значения p1, p2 такие, что f (p1, p2) = 100. Предполагаемые диапазоны следующие:

  • диапазоны для p1: 10-20
  • диапазоны для p2: 20-30

Давайте зафиксируем p1 равным 10 (вы можете зафиксировать любое значение в этом диапазоне). Теперь функция становится

def g(p2):
    return 10 + np.sqrt(p2)

Мы хотим, чтобы это было как можно ближе к 100, поэтому давайте создадим функцию ошибки, которая измеряет, насколько наша оценка далека от 100.

def error(p2):
    return 100 - (10 + np.sqrt(p2)) # we want to minimize this

Вы можете найти значение, чтобы свести к минимуму эту ошибку, чтобы вы могли быть как можно ближе к 100 через

from scipy import optimize
optimize.minimize_scalar(error, bounds = (10,20), method = "bounded")   

что дает значение x = 19,9 как значение, которое минимизирует ошибку.

person Emmet B    schedule 21.02.2018
comment
Итак, как это будет работать для его примера? Что это даст? - person sascha; 21.02.2018
comment
значение p1, которое приближается к 100, как он спросил, что еще это может быть? - person Emmet B; 21.02.2018
comment
Для этого вам не нужен код и ваш подход не приносит ничего стоящего (по крайней мере, он неполный в плане как передать) (это только мое мнение). Многомерный подход GD является локальным, но достаточно ли этого здесь? - person sascha; 22.02.2018
comment
Я просто рад, что ты хоть понял наконец, что это твое мнение. - person Emmet B; 22.02.2018

создайте новую функцию для оптимизации, добавив штраф к нарушениям ограничений.

param1 должен быть в диапазоне 10-20, поэтому для удовлетворения ограничений для param1 будет использоваться только новая функция для оптимизации.

f(p1,p2,p3,p4)=my_function(p1,p2,p3,p4)+1000*(p1-30)*2
param1=20+p1

с изменением переменной для оптимизации p1=param1-20 вы можете играть с величиной коэффициента перед ограничением, которое будет зависеть от используемого метода оптимизации.

квадрат необходим, чтобы градиент существовал для всех p1

добавить другие штрафы к новой оптимизированной функции по мере необходимости

person alexprice    schedule 19.11.2019

Просто для удовольствия, небольшая демонстрация в julia (как кто-то сказал: нет конкретного решения). ).

Это глобальный решатель с открытым исходным кодом, который будет работать с такими небольшими проблемами (и переходить к более сложным). Имейте в виду, что ваши примеры несколько тривиальны (обе цели приведут к нижним границам для всех переменных, для этого не требуется оптимизация; код выведет их, как и ожидалось), и я использую какое-то другое значение, где на самом деле есть есть что оптимизировать!

Когда модель становится более сложной, глобальная оптимизация становится неосуществимой (теоретически очень сложной, а иногда и невозможной). Вы можете просто переключить решатель на Ipopt, чтобы получить локальный оптимум.

Это можно сделать и в python, используя pyomo, но это менее удобно. Можно использовать модель и решатель. Меняется только код.

Код

using JuMP, AmplNLWriter

TARGET = 387

m = Model(solver=AmplNLSolver(CoinOptServices.couenne))

@variable(m, 10 <= param1 <= 20, start=10)
@variable(m, 20 <= param2 <= 30, start=20)
@variable(m, 30 <= param3 <= 40, start=30)
@variable(m, 40 <= param4 <= 50, start=40)
@variable(m, aux)

@NLconstraint(m, aux == TARGET - (param1 + 3*param2 + 5*param3 + 5^3 + sqrt(param4)))
@NLobjective(m, Min, aux^2)
solve(m)

println("objective: ", getobjectivevalue(m))
println("param1 = ", getvalue(param1))
println("param2 = ", getvalue(param2))
println("param3 = ", getvalue(param3))
println("param4 = ", getvalue(param4))

Вне

Mailing list: [email protected]
Instructions: http://www.coin-or.org/Couenne
couenne:
ANALYSIS TEST: Couenne: new cutoff value 0.0000000000e+000 (0.016 seconds)
NLP0012I
              Num      Status      Obj             It       time                 Location
NLP0014I             1         OPT 0        7 0.003
Loaded instance "C:\Users\Sascha\.julia\v0.5\AmplNLWriter\.solverdata\jl_21AE.tmp.nl"
Constraints:            1
Variables:              5 (0 integer)
Auxiliaries:            2 (0 integer)

Coin0506I Presolve 11 (0) rows, 4 (-3) columns and 22 (-3) elements
Clp0006I 0  Obj 0 Primal inf 0.0023740886 (2)
Clp0006I 1  Obj -4.0767235e-022
Clp0000I Optimal - objective value 0
Clp0032I Optimal objective 0 - 1 iterations time 0.012, Presolve 0.00
Clp0000I Optimal - objective value 0
NLP Heuristic: NLP0014I             2         OPT 0        3 0.001
no solution.
Cbc0010I After 0 nodes, 0 on tree, 1e+050 best solution, best possible 0 (0.01 seconds)
Clp0000I Optimal - objective value 3.90625e-007
Clp0006I 0  Obj 0 Primal inf 0.00098181331 (1)
Clp0006I 1  Obj -3.2730444e-022
Clp0000I Optimal - objective value 0
Optimality Based BT: 0 improved bounds
Cbc0004I Integer solution of 0 found after 2 iterations and 2 nodes (0.03 seconds)
Cbc0001I Search completed - best objective 0, took 2 iterations and 2 nodes (0.04 seconds)
Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost

        "Finished"

Linearization cuts added at root node:         11
Linearization cuts added in total:             11  (separation time: 0s)
Total solve time:                           0.065s (0.065s in branch-and-bound)
Lower bound:                                    0
Upper bound:                                    0  (gap: 0.00%)
Branch-and-bound nodes:                         2
WARNING: Nonlinear solver does not provide dual solutions
objective: 0.0
param1 = 10.0
param2 = 20.0
param3 = 37.13508893593264
param4 = 40.0
person sascha    schedule 21.02.2018