「Pythonで最適化しても、現場では試し切りの回数は逆に増える。」

金属加工の現場では、「もっと早く削りたい」「でも表面粗さは悪化させたくない」「工具の寿命も保ちたい」というように、複数の要求が常にぶつかり合います。これが多目的最適化問題の本質です。
通常の最適化(単目的最適化)では、たとえば「加工コストを最小化せよ」という1つの指標を目標にします。しかし現実の金属加工では、目標は1つではありません。加工コスト・表面粗さ・工具摩耗量・加工時間など、複数の目的関数を同時に扱う必要があります。
つまり多目的最適化とは、こうした相反する目標を一括して扱う手法です。
| 単目的最適化 | 多目的最適化 |
|---|---|
| 目的関数が1つ | 目的関数が2つ以上 |
| 最適解は1点に定まる | 最適解は「パレート解」の集合になる |
| 答えが明確 | 答えはトレードオフ曲線として与えられる |
| 例:加工コスト最小化 | 例:コスト最小化 + 表面粗さ最小化 |
多目的最適化の核心は「パレート解」にあります。パレート解とは、「他のどの解と比べても、少なくとも1つの目的で優れており、どの目的でも劣っていない解の集合」のことです。わかりやすく言えば、「どこかを改善しようとすると、必ず別のどこかが悪化する、ギリギリのバランス点の集まり」です。
この集合全体を「パレートフロント」と呼び、グラフ上では弓なりの曲線として現れます。金属加工で言えば、「切削速度を上げると表面粗さが悪化する」というトレードオフがまさにパレートフロントを形成します。
Pythonで多目的最適化を行う際は、このパレートフロントを計算・可視化することが出発点になります。現場の技術者が「どの加工条件を採用するか」を判断するための科学的根拠を、データとして提示することができるのです。
参考:多目的最適化の用語解説(パレート解・パレートフロントなど)
多目的最適化 (Multi-objective optimization) - サイバネットシステム
Pythonで多目的最適化を実装する場合、主要なライブラリは3つです。選び方を間違えると、現場でコードが使い物にならないという事態になります。これは痛いですね。それぞれの特徴と向き不向きをまとめます。
| ライブラリ名 | 主なアルゴリズム | 向いている用途 | 難易度 |
|---|---|---|---|
| pymoo | NSGA-II, NSGA-III, MOEA/D | 制約条件が多い加工条件最適化 | 中級 |
| Optuna | TPE, NSGAIISampler | 機械学習パラメータ探索・実験計画 | 初級~中級 |
| Platypus | NSGA-II, SPEA2, MOEA/D | シンプルな多目的問題・学習用 | 初級 |
pymoo は多目的最適化に特化したライブラリで、ドイツのKalyanmoy Deb教授の研究室出身のJulian Blankらが開発しました。NSGA-IIをはじめとする進化的アルゴリズムが充実しており、制約条件(例:工具への負荷が上限を超えないなど)も柔軟に設定できます。金属加工のような複雑な制約条件を伴う最適化に最も適しています。
Optuna はベイズ最適化ベースで、少ない試行回数で効率よく最適解を探索できます。1回の試し切りに時間やコストがかかる場合に特に有効です。実際の加工実験の回数を減らす目的で使うなら、Optunaが条件です。
Platypus は構文がシンプルで、学習コストが最も低いライブラリです。これは使えそうです。ただし、大規模な制約条件や精密な調整には向かないため、概念理解や小規模なプロトタイプ作成に向いています。
金属加工の現場への導入を考えるなら、まずPlatypusで概念を掴み、次にpymooで本番実装に移行する、という2段階のアプローチが現実的です。インストールはいずれも `pip install` コマンド1行で完了します。
```python
# 各ライブラリのインストール
pip install pymoo # 本番用・制約条件が多い場合
pip install optuna # 試行回数を減らしたい場合
pip install platypus-opt # 学習・プロトタイプ用
```
参考:pymooの使い方まとめ(アルゴリズム別の実装例が豊富)
多目的最適化に特化したPythonライブラリpymooの使い方まとめ
NSGA-II(Non-dominated Sorting Genetic Algorithm II)は、多目的最適化の世界で最も広く使われているアルゴリズムです。遺伝的アルゴリズムを多目的最適化に拡張したもので、「高速非優越ソート」と「混雑度距離」という2つの仕組みによって、パレートフロントに近い多様な解を効率よく探索します。
NSGA-IIの特徴は次の3点にまとめられます。
- 高速非優越ソート:解集団を「パレートランク」順にソートし、より優れた解を優先的に次世代に残します
- 混雑度距離:同じランクの解の中でも、多様性を確保するために、解が密集している領域の解を淘汰します
- エリート保存:良い解を次世代に必ず引き継ぐため、探索が安定しています
pymooを使ったNSGA-IIの基本的な実装コードは以下の通りです。金属加工の切削条件(切削速度・送り量)を最適化し、「加工時間を最小化」かつ「表面粗さを最小化」する2目的問題として設定した例です。
```python
import numpy as np
from pymoo.core.problem import Problem
from pymoo.algorithms.moo.nsga2 import NSGA2
from pymoo.optimize import minimize
from pymoo.visualization.scatter import Scatter
# ---- 問題定義 ----
class MachiningProblem(Problem):
def __init__(self):
super().__init__(
n_var=2, # 設計変数の数(例:切削速度・送り量)
n_obj=2, # 目的関数の数(加工時間・表面粗さ)
n_constr=1, # 制約条件の数(例:工具負荷の上限)
xl=np.array(50, 0.05), # 下限(切削速度50m/min, 送り量0.05mm/rev)
xu=np.array(300, 0.5), # 上限(切削速度300m/min, 送り量0.5mm/rev)
)
def _evaluate(self, X, out, *args, kwargs):
v = X:, 0 # 切削速度 m/min
f = X:, 1 # 送り量 mm/rev
# 目的関数1:加工時間(簡易モデル)→ 最小化
obj1 = 1000 / (v * f)
# 目的関数2:表面粗さ Ra(簡易モデル)→ 最小化
obj2 = (f 2) / (8 * 0.4) # 0.4mm = ノーズR
# 制約条件:工具負荷(切削速度×送り量)が100を超えない
constraint = v * f - 100
out"F" = np.column_stack(obj1, obj2)
out"G" = constraint.reshape(-1, 1)
# ---- アルゴリズム設定と実行 ----
problem = MachiningProblem()
algorithm = NSGA2(pop_size=100) # 集団サイズ100
res = minimize(
problem,
algorithm,
('n_gen', 200), # 200世代繰り返す
seed=1,
verbose=False
)
# ---- パレートフロントの可視化 ----
plot = Scatter(title="切削条件の多目的最適化(加工時間 vs 表面粗さ)")
plot.add(res.F, color="red")
plot.show()
print("パレート解の数:", len(res.F))
print("最適解一覧(加工時間, 表面粗さ):\n", res.F:5)
```
このコードで押さえておくべき設定は3点です。
- `n_var`:設計変数(切削速度・送り量・切込み量など)の数
- `n_obj`:最適化する目的の数(加工時間・表面粗さ・工具摩耗など)
- `n_constr`:守らなければならない制約の数(工具への負荷限界など)
`pop_size=100` は集団サイズで、大きくするほど精度が上がりますが計算時間も増えます。製造現場での試算用途なら `pop_size=50〜100`、精密な最適化には `200以上` が目安です。`n_gen=200` は世代数で、これも同様に大きいほど精度向上します。
参考:pymooを使ったNSGA-IIの実装例(製造業出身者によるコード解説)
pymooを使って多目的最適化のNSGA-Ⅱを実装してみた - Qiita
パレートフロントを求めることがゴールではありません。真の目的は、その曲線の中から「現場で採用する加工条件を1点選ぶ」ことです。パレートフロントが「地図」だとすれば、最終的な意思決定は技術者が行います。
パレートフロント上の解の選び方は、主に3パターンあります。
実際の金属加工の現場では、「表面粗さはどうしてもRa 1.6以下でないと客先検査をパスできない」などの固定条件があることがほとんどです。その場合は制約法が最も現実的です。
Pythonでは、パレートフロントの各解を `res.X`(設計変数の値)と `res.F`(目的関数の値)として取得できます。以下はその後の絞り込み処理の例です。
```python
import pandas as pd
# パレート解の一覧をDataFrameに変換
df_pareto = pd.DataFrame({
"切削速度 m/min": res.X:, 0,
"送り量 mm/rev": res.X:, 1,
"加工時間 s": res.F:, 0,
"表面粗さ Ra μm": res.F:, 1,
})
# 品質基準フィルタ:表面粗さ Ra 1.6 以下に限定
df_filtered = df_paretodf_pareto"表面粗さ Ra μm" <= 1.6
# 残った候補の中で加工時間が最短の条件を選択
best = df_filtered.sort_values("加工時間 s").iloc
print("採用条件:\n", best)
```
このアプローチにより、「Excelに貼り付けた試し切りデータの感覚値」ではなく、数学的に最良な加工条件を提示できるようになります。品質基準が明文化されている部品加工では特に有効です。
また、パレートフロントの可視化には `matplotlib` を使ったカスタムグラフも有効です。横軸に加工時間、縦軸に表面粗さをとって散布図を描き、採用候補点を赤丸でマークする、という資料を加工計画の打合せで提示すると、技術的な判断がグッとしやすくなります。これは使えそうです。
参考:PythonのPlatypusを使ったパレートフロント可視化の具体例
Platypusで多目的最適化からパレートフロントを求める方法 - WATLAB
「Pythonで最適化しても、結局は試し切りが増える」という声は現場で少なくありません。しかし実態は逆です。正しく使えば、試し切りの回数は大幅に削減できます。
その鍵を握るのが「サロゲートモデル(代替モデル)」との組み合わせです。NSGA-IIなどの進化的アルゴリズムは、目的関数を何百・何千回も評価することで最適解に近づきます。これを実際の機械加工で全部やると、当然コストと時間が爆発します。そこで登場するのが、少数の実験データから目的関数の「近似式」をPythonで学習させ、その近似式に対して最適化を走らせるアプローチです。
具体的なフローは以下の通りです。
このアプローチをマテリアルズ・インフォマティクス(MI)の文脈で応用した事例では、鋼材の「降伏強度」と「引張強さ」の両方を最大化する組成を探索した研究があります。CatBoostとMatminerの公開データセットを組み合わせ、R²スコア 0.84〜0.86 の精度でマルチターゲット予測モデルを構築。数百種の材料候補の中からパレートフロント上の有望材料を絞り込むことに成功しています。
ただし、サロゲートモデルには明確な限界があります。学習データの範囲を大きく超えた条件(外挿域)では予測精度が急激に落ちます。金属加工で言えば、「これまで試したことがない高速・高送り領域」に飛び出した条件は、モデルが自信を持って予測できない領域になります。
モデルを過信せず、パレート解の候補を必ず少数の実際の加工実験で検証することが原則です。サロゲートモデルとベイズ最適化を組み合わせた手法では、通常100回以上かかる試行を10〜20回程度に削減した事例も報告されています。時間節約は大きいですね。
参考:Optunaとベイズ最適化による多目的最適化の実装(製造業出身DSによる解説)
optunaを使って多目的最適化問題を解いてみた - Qiita
参考:マルチターゲット回帰とパレートフロント可視化の詳細実装(実データ使用)
マテリアルズインフォマティクス入門⑦【多目的最適化とパレートフロント】- LabCode

自転車 空気入れ 電動 電動空気入れ バイク 車 用 コードレス 6000mAh 大容量バッテリー 仏/英/米式バルブ対応 自動停止 低騒音 エアポンプ