#python #python-3.x #list #optimization #scipy
#python #python-3.x #Список #оптимизация #scipy
Вопрос:
Я определил python-функцию, принимающую четыре входных параметра и возвращающую скаляр. Первые два входа являются векторами, в то время как последние два входа являются скалярами. Для заданных двух векторов (первых двух входных данных) я хочу найти значения y0
и y1
, которые минимизируют функцию. Каков наилучший способ сделать это?
Вот пример кода функции:
def f(y_,y,y0,y1):
xy1 = [i*y1 for i in range(len(y_))]
diff = [(y_[i] y0 xy1[i] - y[i])**2 for i in range(len(y_))]
return sum(diff)
y_ = [x**2 1.4 for x in range(-10,11,1)]
y= [x**2 1. for x in range(-10,11,1)]
x = [3*i for i in range(len(y_))]
print('x:',x)
print('y_:',y_,'n','y:',y)
print('f:',f(y_,y,0,0))
Вывод:
x: [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60]
y_: [101.4, 82.4, 65.4, 50.4, 37.4, 26.4, 17.4, 10.4, 5.4, 2.4, 1.4, 2.4, 5.4, 10.4, 17.4, 26.4, 37.4, 50.4, 65.4, 82.4, 101.4]
y: [101.0, 82.0, 65.0, 50.0, 37.0, 26.0, 17.0, 10.0, 5.0, 2.0, 1.0, 2.0, 5.0, 10.0, 17.0, 26.0, 37.0, 50.0, 65.0, 82.0, 101.0]
f: 3.360000000000019
Ответ №1:
Вот ваша функция, завернутая в python lambda, поэтому она принимает один векторный аргумент и может быть передана в scipy.minimize.
from scipy.optimize import minimize
def f(y_,y,y0,y1):
xy1 = [i*y1 for i in range(len(y_))]
diff = [(y_[i] y0 xy1[i] - y[i])**2 for i in range(len(y_))]
return sum(diff)
y_ = [x**2 1.4 for x in range(-10,11,1)]
y= [x**2 1. for x in range(-10,11,1)]
x = [3*i for i in range(len(y_))]
print('x:',x)
print('y_:',y_,'n','y:',y)
print('f:',f(y_,y,0,0))
toMinimize = lambda x: f(y_,y, x[0], x[1])
res = minimize(toMinimize, (0, 0))
print(res.message)
print('optimizal position: ',res.x)
print('minimal value: ',res.fun)
Это дает следующий результат.
x: [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60]
y_: [101.4, 82.4, 65.4, 50.4, 37.4, 26.4, 17.4, 10.4, 5.4, 2.4, 1.4, 2.4, 5.4, 10.4, 17.4, 26.4, 37.4, 50.4, 65.4, 82.4, 101.4]
y: [101.0, 82.0, 65.0, 50.0, 37.0, 26.0, 17.0, 10.0, 5.0, 2.0, 1.0, 2.0, 5.0, 10.0, 17.0, 26.0, 37.0, 50.0, 65.0, 82.0, 101.0]
f: 3.360000000000019
Optimization terminated successfully.
optimizal position: [-4.00000011e-01 -5.25897060e-09]
minimal value: 1.0614222972874884e-13
Ответ №2:
Просто публикую альтернативное решение для «полноты»:
from scipy.optimize import minimize
def f(params,y_,y):
y0,y1 = params
xy1 = [i*y1 for i in range(len(y_))]
diff = [(y_[i] y0 xy1[i] - y[i])**2 for i in range(len(y_))]
return sum(diff)
y_ = [(x-3)**2 1.4 for x in range(-10,11,1)]
y= [x**2 1. for x in range(-10,11,1)]
x = [3*i for i in range(len(y_))]
print('x:',x)
print('y_:',y_,'n','y:',y)
print('f:',f([0,0],y_,y))
y0 = 0.
y1 = 0.
minimize(f, [y0, y1], args=(y,y_))