注目キーワード
  1. Python
  2. コンペ

scipy.optimize.minimizeの使い方|bounds・constraints・methodを実例で解説

  • 2026年6月13日
  • 2026年6月13日
  • Python
  • 2回
  • 0件

scipy.optimize.minimizeとは

scipy.optimize.minimize は、Pythonの科学計算ライブラリSciPyに含まれる最適化関数です。与えた目的関数(最小化したい関数)の最小値と、そのときの変数の値を求めます。

機械学習のハイパーパラメータ調整、コスト最適化、物理シミュレーションなど、数値的に最小値を探したい場面で広く使われます。

この記事では、minimize の基本的な使い方から、実務でよく使う3つの要素である bounds(変数の範囲制限)constraints(制約条件)method(最適化手法) の設定方法を実例とともに解説します。

基本的な使い方

まず、引数なしで最もシンプルな形から確認します。

SciPyがインストールされていない場合は、以下のコマンドでインストールしてください。

pip install scipy

最小限のコード例

目的関数として f(x) = (x - 3)² を最小化します。最小値は x = 3 のときです。

from scipy.optimize import minimize

# 目的関数
def objective(x):
    return (x[0] - 3) ** 2

# 初期値(xの初期推定値)
x0 = [0.0]

result = minimize(objective, x0)

print(result.x)       # 最適解
print(result.fun)     # 目的関数の最小値
print(result.success) # 最適化が成功したか
[3.]
8.881784197001252e-16
True

result.x が最適解(ここでは x ≈ 3)、result.fun が目的関数の最小値です。数値誤差のためゼロに非常に近い値が出ますが、実質的にゼロとみなせます。

minimizeの主な引数

引数内容
fun最小化したい目的関数
x0変数の初期値(リストまたはnumpy配列)
method最適化アルゴリズムの指定
bounds各変数の下限・上限
constraints等式・不等式の制約条件
options最大繰り返し回数などの設定

bounds(変数の範囲制限)の使い方

bounds は、各変数に「この範囲の中だけで解を探してほしい」という制限をかけるときに使います。

たとえば、商品の仕入れ数量は0以上でなければならない、割引率は0〜1の範囲に収まる必要がある、といった場面で使います。

boundsの書き方

from scipy.optimize import minimize

# 目的関数(2変数)
def objective(x):
    return (x[0] - 3) ** 2 + (x[1] - 5) ** 2

x0 = [0.0, 0.0]

# 各要素が (下限, 上限)。Noneは制限なしを意味する
bounds = [(0, 2), (0, 4)]

result = minimize(objective, x0, bounds=bounds)

print(result.x)
print(result.fun)
[2. 4.]
2.0

x[0] の最適解は本来3ですが、上限が2のため x[0] = 2 に抑えられています。同様に x[1] は上限4で抑えられています。

Boundsクラスを使う方法

scipy.optimize.Bounds クラスを使って書くこともできます。変数が多い場合はこちらの方がコードが整理されます。

from scipy.optimize import minimize, Bounds

def objective(x):
    return (x[0] - 3) ** 2 + (x[1] - 5) ** 2

x0 = [0.0, 0.0]

# Boundsクラスで指定(lb=下限, ub=上限)
bounds = Bounds(lb=[0, 0], ub=[2, 4])

result = minimize(objective, x0, bounds=bounds)

print(result.x)
[2. 4.]

片方だけ制限する場合

下限だけ設けたい場合は上限に np.inf または None を使います。

import numpy as np
from scipy.optimize import minimize

def objective(x):
    return (x[0] - 3) ** 2

x0 = [0.0]

# 下限0、上限なし
bounds = [(0, None)]

result = minimize(objective, x0, bounds=bounds)
print(result.x)
[3.]

constraints(制約条件)の使い方

constraints は、変数の組み合わせに条件をかけるときに使います。boundsが「各変数の範囲」であるのに対して、constraintsは「複数の変数の関係」に制約をかけます。

constraintsの種類

種類キー内容
等式制約'eq'fun(x) = 0 を満たすように探す
不等式制約'ineq'fun(x) >= 0 を満たすように探す

辞書形式で {'type': 'eq', 'fun': 関数} のように指定します。

等式制約の例

x[0] + x[1] = 1(合計が1になる)という条件を設けます。

from scipy.optimize import minimize

def objective(x):
    return (x[0] - 0.3) ** 2 + (x[1] - 0.7) ** 2

x0 = [0.5, 0.5]

# x[0] + x[1] - 1 = 0 と書く
constraints = {'type': 'eq', 'fun': lambda x: x[0] + x[1] - 1}

result = minimize(objective, x0, constraints=constraints, method='SLSQP')

print(result.x)
print(f"合計: {result.x[0] + result.x[1]:.6f}")
[0.3 0.7]
合計: 1.000000

制約を満たしながら目的関数が最小化されました。

不等式制約の例

x[0] + x[1] >= 1(合計が1以上)という条件を設けます。

from scipy.optimize import minimize

def objective(x):
    return x[0] ** 2 + x[1] ** 2  # 原点に近づこうとする

x0 = [1.0, 1.0]

# x[0] + x[1] - 1 >= 0 と書く
constraints = {'type': 'ineq', 'fun': lambda x: x[0] + x[1] - 1}

result = minimize(objective, x0, constraints=constraints, method='SLSQP')

print(result.x)
print(f"合計: {result.x[0] + result.x[1]:.6f}")
[0.5 0.5]
合計: 1.000000

目的関数は原点(0,0)を目指しますが、制約 x[0] + x[1] >= 1 により [0.5, 0.5] が最適解になります。

boundsとconstraintsを同時に使う

from scipy.optimize import minimize

def objective(x):
    return -x[0] * x[1]  # x[0] * x[1] を最大化 = -x[0]*x[1] を最小化

x0 = [1.0, 1.0]

# 各変数は0以上
bounds = [(0, None), (0, None)]

# x[0] + x[1] <= 10(合計が10以下)
# 'ineq' は fun(x) >= 0 なので 10 - x[0] - x[1] >= 0 と書く
constraints = {'type': 'ineq', 'fun': lambda x: 10 - x[0] - x[1]}

result = minimize(objective, x0, bounds=bounds, constraints=constraints, method='SLSQP')

print(result.x)
print(f"最大積: {result.x[0] * result.x[1]:.4f}")
[5. 5.]
最大積: 25.0000

method(最適化手法)の選び方

method では、どのアルゴリズムで最適化を行うかを指定します。指定しない場合は問題の種類に応じて自動的に選ばれますが、boundsconstraints を使う場合は明示的に指定する方が安全です。

主なmethodと使い分け

method特徴向いているケース
'SLSQP'boundsとconstraints両方に対応制約付き問題の標準的な選択
'L-BFGS-B'boundsに対応、大規模問題に強い変数が多い、boundsのみの問題
'Nelder-Mead'微分不要(勾配情報不要)目的関数が複雑・不連続な場合
'BFGS'勾配ベース、高精度boundsなし・constraintsなしの滑らかな問題
'trust-constr'boundsとconstraints両方に対応大規模・高精度が必要な制約付き問題

boundsのみ → L-BFGS-Bの例

from scipy.optimize import minimize

def objective(x):
    return (x[0] - 2) ** 2 + (x[1] - 4) ** 2

x0 = [0.0, 0.0]
bounds = [(0, 1.5), (0, 3.0)]

result = minimize(objective, x0, method='L-BFGS-B', bounds=bounds)

print(result.x)
print(result.message)
[1.5 3. ]
b'CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PRTOL'

constraints付き → SLSQPの例

boundsconstraints を同時に使う場合は SLSQP が基本の選択肢です。

from scipy.optimize import minimize

def objective(x):
    return (x[0] - 1) ** 2 + (x[1] - 2) ** 2

x0 = [0.0, 0.0]
bounds = [(0, 3), (0, 3)]
constraints = {'type': 'eq', 'fun': lambda x: x[0] + x[1] - 2}

result = minimize(
    objective, x0,
    method='SLSQP',
    bounds=bounds,
    constraints=constraints
)

print(result.x)
print(result.success)
[1. 1.]
True

よくあるミスと注意点

初期値が結果に影響する

minimize は局所最小値を探すアルゴリズムです。初期値によっては、全体の最小値(大域最小値)ではなく、局所的な最小値に収束することがあります。

複数の初期値で試して結果を比較するのが安全です。

from scipy.optimize import minimize
import numpy as np

def objective(x):
    # 複数の局所最小値を持つ関数
    return np.sin(x[0]) + 0.1 * x[0] ** 2

results = []
for x0_val in [-5, 0, 5]:
    res = minimize(objective, [x0_val])
    results.append((x0_val, res.x[0], res.fun))

for x0, x_opt, f_opt in results:
    print(f"初期値={x0:3d} → x={x_opt:.4f}, f(x)={f_opt:.4f}")
初期値= -5 → x=-4.6746, f(x)=-0.9988
初期値=  0 → x=-1.5708, f(x)=-1.0000
初期値=  5 → x=4.7124, f(x)=-0.9974

初期値によって異なる局所最小値に収束しています。

constraintsのineqの方向に注意

'ineq' は「fun(x) >= 0」という方向です。「以下(≦)」の制約を書くときは符号を反転します。

# x[0] + x[1] <= 10 を書く場合
# 10 - x[0] - x[1] >= 0 に変換する
constraints = {'type': 'ineq', 'fun': lambda x: 10 - x[0] - x[1]}

符号が逆だと意図とは逆の制約になるため注意してください。

result.successを必ず確認する

minimize は失敗しても例外を出さず、result.success = False で通知します。最適化後は必ず確認します。

result = minimize(objective, x0, bounds=bounds, constraints=constraints, method='SLSQP')

if not result.success:
    print(f"最適化失敗: {result.message}")
else:
    print(f"最適解: {result.x}")

boundsとmethodの組み合わせミス

bounds を指定しても、method='BFGS' など bounds に対応していないmethodを使うと、範囲制限が無視されます。bounds を使う場合は L-BFGS-B または SLSQPconstraints も使う場合は SLSQP を指定してください。

AI時代での補足

AIにコード生成を任せる場面でも、bounds の設定ミスや constraints の符号間違いは人間が確認しなければ気づきにくいエラーです。最適化の構造を理解しておくと、生成されたコードの意図を読み取って修正できます。

まとめ

この記事では scipy.optimize.minimize の基本的な使い方と、boundsconstraintsmethod の設定方法を解説しました。

  • bounds:変数の上限・下限を設ける。タプルのリストまたは Bounds クラスで指定
  • constraints:変数間の関係に等式('eq')または不等式('ineq')の制約をかける
  • method:boundsのみなら L-BFGS-B、constraintsも使うなら SLSQP が基本の選択
  • 注意点:初期値依存・ineq の符号・result.success の確認を忘れずに

最適化問題は機械学習モデルのハイパーパラメータ探索とも関連します。scikit-learnのGridSearchCVによる探索方法に興味がある場合は、グリッドサーチ(GridSearchCV)の使い方も参考にしてください。

最新情報をチェックしよう!