因为没有找到合适的资料,看到的很多要么用了一堆功能要么给出一堆复杂的式子直接优化,感觉不够简单,于是自己整理了一下,希望能一看就懂,也能自己轻松在草稿纸上手动算出优化结果。
1.一元无约束优化:
from scipy.optimize import minimize
import numpy as np
func = lambda x: x ** 2
x_init = np.random.random(1)
res = minimize(func, x_init)
print("最小值:", res.fun)
print("最优解:", res.x)
print("迭代终止是否成功", res.success)
print("迭代终止原因", res.message)
输出:
最小值: 1.1488908661148124e-17
最优解: [3.38952927e-09]
迭代终止是否成功 True
迭代终止原因 Optimization terminated successfully.
下文不再显式导入包,也不显式给出这4行print代码,大家自己加上。
2.一元带约束优化:
2-1.使用constraints
func = lambda x: x ** 2
cons = ({'type': 'ineq', 'fun': lambda x: x - 2})
x_init = np.array(1)
res = minimize(func, x_init, constraints=cons) # 最优解x=2
2-2.使用bounds
func = lambda x: x ** 2
x_init = np.array(1)
res = minimize(func, x_init, bounds=((3, 5), )) # 最优解x=3
两种约束差不多,而constrains更适合复杂情况下的约束。
3.一元带超参数优化:
def func(x, a):
return x**2 - 4*a*x
a = 2
x_init = np.array(1)
res = minimize(func, x_init, args=(a,)) # 最优解x=4
这里也是可以用func = lambda x, a: x**2 + 4*a*x的。而因为PEP 8: E731规范,不建议将匿名函数表达式赋值给一个变量再用这个变量调用函数,因此除非需要简短的代码,此时还是更建议用def,之后也以def为主。
4.二元函数带约束和超参数优化:
def func(x, a):
return x[0]**2 + a*x[1]
cons = ({'type': 'eq', 'fun': lambda x: x[0] * x[1] - 10}, # 约束条件:xy=10
{'type': 'ineq', 'fun': lambda x: x[0]}, # x>0
{'type': 'ineq', 'fun': lambda x: x[1]}) # y>0
a = 2
x_init = np.random.random(2)
res = minimize(func, x_init, args=(a,), constraints=cons)
手动验证:
更多元的函数的优化是类似的。
对于优化算法的选择可参考其他文章。