solverを使って複雑な最適化を解いてみた。MyEnigmaスマートフォン用の表示で見るMyEnigmaとあるエンジニアのブログです。solverを使って複雑な最適化を解いてみた。solverを使って複雑な最適化を解いてみた。Supportersはじめに先日、上げた記事の続きです。複雑な最適化を実際に実装してみたいと思います。Ceresの基本的な部分は先程の記事を参照下さい。評価関数の各変数における導関数を使って、最適化を実施します。導関数を与えることが重要になります。大きく分けて2つの方法でCeresに導関数を与えることができます。二つ目は解析的に導関数を与える方法です。先日の記事で紹介したようなテンプレートを使ったコスト関数を設定できないことがあります。外部のライブラリを使っている時などです。そんな時のために、数値演算的に導関数を与える方法があります。初めに下記のように、数値導関数を与える構造体を作ります。}};先日の記事との違いは、テンプレートを使わなくしたことです。続いて、上記の構造体をNumericDiffCostFunctionというCeresのAPIを使うことにより、Problemクラスに与えます。導関数を数値的にどうのように計算するかを指定している所が違います。(ceres::CENTRALの部分)この導関数の計算の方法に関しては下記のAPIドキュメントが参考になります。differentiation)の方法を使うことを推奨しています。計算が遅く、精度も悪くなり、収束も遅いことが原理的に示されているからです。導関数を解析的に計算出来る場合は、そちらを使った方が効率的になることがあります。残差項とヤコビ行列の両方をコードに記述する必要があります。コードとして与える場合は、CostFunctionクラスか、SizedCostFunctionクラスを継承したクラスを設定する必要があります。残差項とヤコビ行列を設定します。解析的に導関数を計算出来る時であっても、AutoDiffCostFunctionを使うことを推奨しているようです。導関数の求め方は、現在でも様々な方法が提案されており、それらの幾つかの手法はceresにも実装されています。DynamicAutoDiffCostFunctionCostFunctionToFunctorNumericDiffFunctorConditionedCostFunction詳しい方法はAPIのリファレンスを確認下さい。複雑な最適化をCeresソルバで解いてみたいと思います。今回は、パウエル関数の最適化を考えます。下記の式で4次元のベクトルが計算される関数です。ここでこのパウエル関数の二乗ノルムを最小化するxをCeresで計算するコードを作ってみたいと思います。ちなみに、パウエル関数はx=[0,0,0,0]でF(x)=0が極小値になることがわかっています。Functionまず初めに、それぞれのベクトルの要素を計算する評価関数のコードを作成します。入力の変数は配列のポインタの形なので0番目の要素を指定することを忘れないようにしましょう。続いて、最適化を実施する関数を書きます。options.minimizer_progress_to_stdout=true;//最適化の結果を標準出力に表示する。0;}コスト関数が複数の場合は、AddResidualBlockを複数回呼んで、それぞれ追加すればOKです。ちなみにAutoDiffCostFunction<F1,1,1,1>のそれぞれの入力は、1つめ:評価関数の構造体2つめ:residualの次元数(F1のresidualは次元が1)3つめ:1つめの次元数(F1のx1は次元が1)4つめ:1つめの次元数(F1のx2は次元が1)です。詳しくは下記を参照下さい。Solverすると下記のような結果が得られます。x=[0,0,0,0]でF(x)=0の極小値が探索できていることがわかります。こちらのコードは下記のGithubリポジトリでも公開しています。github.comより深く最適化を学びたい人は下記の資料が体系的に学べるのでおすすめです。Supportersもしこの記事が参考になり、ブログをサポートしたいと思われた方は、こちらからよろしくお願いします。solverを使って複雑な最適化を解いてみた。はてなブログProとあるエンジニアのブログです。Page月別アーカイブスポンサーリンクスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。