Python scipy.optimize 非線形計画法は局所最適と大域最適を解決します

1. 非線形計画法で局所最適を解く

まず最も単純な例を示します。

from scipy.optimize import minimize

def fun_convex(x):
    return (x - 1) ** 2 + 3

minimize(fun=fun_convex, x0=0, bounds=[(-10,10)])

ここに画像の説明を挿入

scipy.optimize.minimize(fun, x0, args=(), method=None, jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None)

fun: 求最小值的目标函数
x0: 变量的初始猜测值,如果有多个变量,需要给每个变量一个初始猜测值
args: 常数值,fun中的可变常量
method: 求极值的方法,官方文档给了很多种。一般使用默认
constraints: 约束条件,针对fun中为参数的部分进行约束限制

scipy.optimize.minimizel 公式ドキュメント
これによりscipy.optimize.minimize、凸関数の局所的な最適数値解を簡単に解くことができます. ここでいくつかの注意点があります:
① 解関数が非凸関数の場合、得られる結果は局所的なものになります最適化
② 解関数が凸関数の場合、得られる結果は最小値となる
③ 得られる解はすべて理論解ではなく数値解となる

非凸関数の例を以下に示します。

from scipy.optimize import minimize

def fun_nonconvex(x): 
    if x<0:
        return ( x + 2 ) ** 2 + 1
    else:
        return ( x - 2 ) ** 2 + 2

minimize(fun=fun_nonconvex, x0=0, bounds=[(-10,10)])

ここに画像の説明を挿入
x=2私たちが探しているのは大域的な最適解ではなく (そうであるはずです)、局所的な最適解であることがわかります。x=-2そして、私たちが探している結果は初期値 x0 の設定と大きく関係しています。

2. 全体的な最適値を見つける

scipy.optimize.minimize上記の内容から、局所最適解しか解けないことが分かりましたが、ではどうすれば大域最適解を解くことができるのでしょうか?この記事では、scipy.optimize の 3 つの方法を紹介します:
brute(): 暴力的なグローバル最適化に属するグリッド検索の最適化。Brute 公式ドキュメント
differential_evolution(): 微分進化は基本的に (勾配法を使用せずに) 確率的に最小値を見つけ、候補空間の広い領域を検索できますが、通常は従来の勾配ベースの手法よりも多くの関数評価が必要です。Differential_evolution 公式ドキュメント
basinhopping(): Basin-hopping は、グローバル ステッピング アルゴリズムと各ステップの局所最小値を組み合わせ、各ランダム ジャンプ後に局所緩和を使用する 2 段階の手法で、原子クラスターの自然プロセスのエネルギー最小化をシミュレートすることを目的としています。ベイシンホッピングの公式ドキュメント

ブルート フォースの使用についてはbrute()詳しく説明しません。合計の簡単なルーチンを次にdifferential_evolution()示します。basinhopping()

from scipy.optimize import differential_evolution, basinhopping

def fun_nonconvex(x): 
    if x<0:
        return ( x + 2 ) ** 2 + 1
    else:
        return ( x - 2 ) ** 2 + 2

res_differential_evolution = differential_evolution(func=fun_nonconvex, bounds=[(-10,10)])
print('differential_evolution()的结果为:\n', res_differential_evolution)

res_basinhopping = basinhopping(func=fun_nonconvex, x0=0, niter=1000)
print('\n basinhopping()的结果为:\n', res_basinhopping)

どちらの方法でも大域的な最適解を見つけることができます。
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/qq_40039731/article/details/130126800