* Optimizationクラス [#cbdc0631] ** 使い方 [#eefd6d1a] - 教師データ(物体の位置とキャラクタのポーズ)を与えると、パラメータを最適化してくれる。 - 1. __init__に書いてある変数(計算回数、教師データのファイル名など)をセット - 2. start()を呼ぶと計算開始 - 実際の計算(CMA)は別クラス(Cmaesクラス)が担当する。 ** 評価関数 [#b7dd2383] - Evalクラスによって与える - シミュレーションを行って、その結果にしたがって評価値を決める。 - ObjectFunction関数が目的関数 -- paramを受け取って、シミュレーションを回し、評価値をreturnする。 -- 1. 受け取ったパラメータをSpringhead SceneやScript paramsにセット -- 2. LoadState(spbのrestoreを使う)して状態を初期状態(Optimizationクラスが作られた時にSaveStateされてる)に初期化 -- 3. 教師データに示されたエリアごとにエリアのステップ数回シミュレーションしながら教師データとの比較を行って誤差値を作り、総和をとる。 --- 誤差値を作る作業は個別の関数が担当 StepErroDirectionTarget:オブジェクトが指定された時。頭の姿勢の差分を見る StepErrorBIas:視線方向が指定された時。全身の関節角の差分を見る StepErrorDirectionNone : 何も見てはいけない。視線に偏差があるとマイナス -- 4. 得られた総和を評価値として返す - 教師データ -- 物体の教師データ: オブジェクト名/座標 が並んでいる -- 興味の教師データ: Evalクラスのtestcode関数に直書き(何ステップから何ステップにどれを見ていた(または視線方向)) --- app0128_01.txt(ステップごとに注意対象の物体が書いてある)をもとに手書きした -- 視線の教師データ: train0128_01.txtなど 何ステップ目/視線方向を示すベクトル → self.DirectionAreaDataにロードされるので、それをtestcode内で使う - 最適化プロセス -- Optimizationクラスのstart()内で、barecmaes2ファイルのfmin関数を呼び出すことで開始。 -- fminは --- 1. 目的関数 --- 2. 探索出発点となる初期パラメータ --- 3. 個体をバラ撒く範囲を決めるパラメータ --- 4. 探索回数 --- 5. 評価値がいくつ以下になったら停止するかの閾値 --- 6. mode(0以下のパラメータを個体として生成しない、1以下を(以下同様)、など個体生成にまつわるモード) :本当は 次元数個のrangeのリストを渡すのがよいだろう -- を受取り、 --- 1. 最適パラメータ --- 2. 最適パラメータ時の評価値 --- 3. なぜ終了したか(計算回数が指定回数を超えた、評価値が指定値以下になった、平均値が全く動かなかった): 文字列=>対応する値(計算回数、評価値、など) のハッシュで返る。 -- などを(リストで)返す。 -- fmin関数の中身 --- Cmaesクラスを作って動かす。 ---- 終了条件(stop)になるまで 個体生成(ask) ・ 評価(目的関数をcall) ・ 共分散行列と平均値の更新(tell) を繰り返す 終了条件(stop)になるまで 個体生成(ask) ・ 評価(目的関数をcall) ・ 共分散行列と平均値の更新(tell) を繰り返す -- Cmaesクラスの中身は、基本的には文献通り。 --- 個体数は文字列で数式指定できる。Nは次元数。ただしあまり使ってない。 --- askの中で個体生成している。 個体をrangeで切るのに、range内に収まるまで繰り返し生成となっている。効率悪いのでなんとかしたい。 - 行列ライブラリは使っておらず、行列は二重配列で表現している。 -- 固有値分解を行う関数 eig だけは必要で、どこかから取ってきた。 - やってほしいと思ってること -- 評価関数の汎化 : Stepを回すのは共通化して、Errorの計算のみif分岐したほうがいいのではないか。 -- 教師データの与え方をもっと洗練する。Blenderのキーフレームとか使いたい -- creature ruleで使うパラメータ変数を spb.parameter というファイルに置かないといけない。creature handlerに持たせる(sprスレッドから見える必要あり)など検討すべき -- CMA計算中は完全に固まってしまう。途中の状況を確認したい。別スレッドを建てるか、Spr.pydに放り込んでしまう(C++化)のも手かも。 - 注意 -- IK enableとかをscript内に書いてはダメ。1~2ステップ目からenableされることになり結果が一致しなくなる