最適化問題のスケーリング

最適化問題をモデルで実行する前に、そのモデルをスケーリングすることをお勧めします。

その理由を理解するために、大幅に異なる複数のスケールが混在する粒子物理学の問題を考えてみます。

スケーリングが重要な理由

最適化を使用して、タウ粒子などの素粒子の質量と速度を決定することにします。質量はKg、速度はm/sで測定します。質量は10-30 Kg程度、速度は107 m/s程度になります。スケーリングを適用せずにこの問題を解析すると、以下の問題が発生します:
  • 四捨五入の誤差により計算が不正確になったり、無意味な数字が算出される可能性がある。
    • 倍精度では、マシンの精度は10-16程度です。このため、粒子質量に関係する計算では、かなりの誤差が累積される可能性があります(または、数値が小さすぎることからゼロに設定されることもあります)。
    • 粒子の質量および速度を扱うマトリックスでは、スケーリングが適切に適用されません。10-30程度になる値もあれば、10+7程度になる値もあります。1つのマトリックスに存在する数値の範囲がこれほど広いと、ほとんどの数値的な手法は適切に機能しません。
  • 最適化の合理的な停止基準を最適化エンジンで設定できない。
    • SLSQPでは、サイズに関係なく、すべての変数が同じ方法で処理されます。
    • 速度の1%の誤差は、106 m/s程度に相当します。
    • 質量の1000%の誤差は、10-28 Kg程度に相当します。
    • したがって、速度の1%の誤差の方が質量の1000%の誤差よりも重みを持つことになります。
    • 選択した値が、ある変数では厳格すぎ、別の変数では緩すぎることになります。
  • 妥当なステップを最適化エンジンで選択できない。
    • 最適化エンジンで一般的に定義される設計ステップである1.0は、質量軸には大きすぎ、速度軸には小さすぎます。
    • 停止基準と同様に、選択した値が、ある変数には厳格すぎ、別の変数には緩すぎることになります。

モデルのスケーリングで、これらの問題をすべて解決できます。最適化エンジンに、質量に対するスケールは10-27、速度に対するスケールは107とすることを指示できます。変数ごとのスケーリングファクターを使用することで、前述の問題に対処できます。

スケーリングのガイドライン

モデルのスケーリング方法は問題ごとに異なります。従うべき一般的規則はありません。ただし、以下の規則を試してみることをお勧めします。

Dvのスケーリング
  • 対象とする領域でDvがすべて同じような大きさであることを確認します。
  • 感度もほぼ同程度の大きさであることを確認します。Dvの単位を変更すると、目的関数の単位も変更されることが理想的です。
  • Responseの評価でキャンセレーションエラーの発生を防止できるようにDvを変換します。
制約のスケーリング
  • Dvの摂動を基準として制約を適切に調整する必要があります。
  • 複数の制約は、互いを基準として適切なバランスを維持する必要があります。あるDvに発生した1単位の変更によって、他のすべての制約にも1単位の変更が発生することが理想的です。
目標のスケーリング
  • 対象とする領域の中で、目標は1前後の値であることが必要です。
  • 目標には制約を適用しないようにします。
    • x2 + y2 は、目的関数として最適化エンジンにはx2 + y2 +1よりも優れています。

自動スケーリング

DvおよびResponseのそれぞれに適切なスケーリングファクターが見つからない場合は、最適化エンジンを定義する際にautoScale = Trueと設定することで、MotionSolveの自動スケーリングを試してみます。最適化を実行する前に、最適化エンジンによる試験実行でスケールファクターが計算されます。問題に対して合理的なスケーリングが適切に適用されるように、すべてのDvおよびResponseがスケーリングされます。

   
   >>> # Turn automatic scaling on in optimizer
   >>> opt = Optimizer (
              objective = [a2x, a2y, a2psi],
              weight    = [1.0, 1.0, 1.0],
              type      = 'KINEMATICS',
              end       = 2.0,
              dtout     = 0.01,
              plot      = True,
              dsa       = 'AUTO',
              autoScale = True
              )
   >>> opt.optimize()