今回はいろいろな意見のあるモデルの使いまわしについて、この際はっきりさせておこうじゃないかということで詳しく解説していこうと思います。併せて事前学習についても、モデルの使いまわしと同じ意味で使っている方がよくいるのでそこも訂正しておこうと思います。
そもそも機械学習って何してるの?
与えられた課題に対して、一番損失(loss)が少なくなるようにパラメーター(重み)を何回も更新して調整しています。特にDFはディ-プラーニングなので調整するパラメーターがたくさんあってとても時間がかかります。最近では企業や研究機関が何個もGPUを使って数週間分散学習させるようなのが普通になってきていますが、個人で複数のGPUを回すには費用も馬鹿にならないですし、たった一つのDFを作るために数週間かけるわけにもいきません。そこである程度パラメーターを調整しておこうというのが事前学習です。
事前学習について
DFの事前学習では、大規模な学習セットを使って汎用的な学習をします。(自分が配布してるものはcolabが今より自由に使える時に複数アカウントを使ってバッチサイズ10~16で100万iter回したものです。3週間くらいかかりました。。。)
簡単にDFのモデルの説明
情報を圧縮する部分をエンコーダーといいます。そして圧縮した情報を潜在的な特徴ベクトルに変換する中間層が間にあります。さらに、特徴ベクトルから情報を復元する部分をデコーダーといいます。ちなみにこの特徴ベクトルの次元の数がDFLのオプションで入力するdimsの正体です。例えるなら、絵を見て、それを言語化し、その言葉を元に絵を再現することを想像するとわかりやすいかもしれません。
liaeアーキではこの中間層の割合を変えることで、dfアーキではデコーダーの重みを交換することで顔を変換しています。
モデルの使いまわしについて
事前学習では複数人のデータセットを使って汎用的な学習をしていますが、本番の学習では個人(dstとsrc)に絞ってより専用的な学習をすることになります。つまり、事前学習済のモデルは、パラメーターがある程度ばらけた状態ですが、モデルの使いまわしはパラメータが偏った状態です。違う学習データでそのままモデルを使いまわすと初期値が偏ってしまっているため、正しい学習ができなくなり、似なくなったりモンスターが発生したりということになってしまうわけです。そこで必要になるのが重みの初期化です。
重みの初期化
全て初期化してしまうと事前学習の前の最初の状態と変わらなくなってしまうので、学習に影響する部分だけ初期化します。
LIAEアーキの場合
具体的にLIAEの場合、interABとinterBを初期化します。Modelフォルダの対象のファイルを消すと初期化できます。(※同じ組み合わせの場合は使いまわしてもいいと思います。)また、srcが異なる場合、もしくは、srcが同じでも顔セットの環境が異なる場合には、discriminatorの重み(~GAN.npy)とdiscriminatorのオプティマイザーの重み(~GAN_opt.npy)も消した方がいいと思います。
DFアーキの場合
DFアーキの場合は、true face powerという例外があるので分けて考える必要があります。先ほど中間層のところで特徴ベクトルのお話をしましたが、この特徴ベクトルがsrcの特徴ベクトルに似るように強制するのがtrue faceです。そのためtrue faceを使う場合はモデルを使いまわしても大丈夫なんじゃないかなと思います。ただしsrcの要素が強くなる分、元の動画になじませるのが難しくなるというデメリットもあります。(ちなみにliaeの場合は中間層自体の重みを交換するため仕組み的にtrue faceオプションはありません。)
一方でtrue faceを使わない場合はencoderと中間層の重みは共通なので、decoderの重みを初期化(対象ファイルを削除)するといいと思います。GANの重みも消してください。
まとめ
一見すぐにくっきりするのでよさそうに見えるモデルの使いまわしはありか?なしか?ーーー答えは『場合による』です。いろいろな意見があるのは当然ですね。しかし、この『場合』がわかっていないとせっかくの学習が無駄になってしまうので正しく理解して正しい学習をしましょう。正しく学習すれば時間が節約でき、クオリティも上がります。
LIAEアーキ
- SRCとDSTが同じ場合
→使いまわしはあり - SRCとDSTが異なる場合
→使いまわしはなし
→事前学習からやるか中間層の重みを初期化する - SRCは同じだがDSTが異なる場合
→中間層の重みを初期化する
DFアーキ
- true faceを使う場合
→使いまわしはあり - SRCとDSTが同じ場合
→使いまわしはあり - SRCとDSTが異なる場合
→使いまわしはなし
→デコーダーの重みを初期化 - どちらかが同じ場合
→違う方のデコーダーの重みを初期化