3Dモデルをいろいろ作ってみたい

3Dモデルをいろいろ作ろうとがんばっています。苦労した点、役に立ちそうな情報を発信していきます。

Deep Learningで3Dデータ生成 -高解像度の3Dモデルを目指して-

RTX3090 GPUボードのおかげでDeep Learningの学習のスピードは相当(200倍程度)速くなることは確認できたのですが、3次元データの解像度を単純に上げていくとGPUメモリ容量の制約でGPU並列処理ができなくなる、すなわち事実上実行不能になるという制約に変わりはありません。24GBの容量があっても3次元の畳込み層を使うと処理できるテンソルのサイズは32x32x32まででした。モデルの解像度を128x128x128ぐらいに上げてかつGPUでそこそこの速度をだしたいということで、学習のためのネットワーク構成を再検討することにしました。

基本的な考え方は128x128x128の3Dのテンソルではなく128x128の断面画像に相当するテンソル128枚分を入力として用いるということです。128x128の2次元データを畳込み層に適用してそれぞれのサイズを小さくしてからConcatenate層(Tensorflow/Kerasにはちゃんとマージのための層が用意されている)で1枚の2次元画像にマージし、全結合層(Dense層)につなぐことにしました。これだと(縦横サイズの大きい)入力に近い側では2次元データを処理すればよいのでGPUメモリの範囲内に収めることができます。高さ方向では層間の畳込みを行っていない点でちょっと学習能力は落ちる気はしますが、とりあえずはこの方針で試すことにしました。

生成用Deep Learningアーキテクチャは前回のGAN(敵対的生成ネットワーク)ではなく、Auto Encoderです。前回は本に載っていたGANのプログラムコードを少し変更することで実現したのですが、今回は入出力の構造が大きく変わっているため自分でいちからコーディングしました。そのぶん、Kerasの勉強をしながらになるのでGANに比べて構造が単純なAuto Encoder に則してネットワークを作ることにしました。

Auto Encoderは入力の3Dデータに対して畳込み層、全結合層を適用してベクトルデータを出力するエンコーダとベクトルデータを入力として3Dデータを出力するデコーダから成ります。エンコーダへの入力とデコーダの出力の差を最小化するように学習を行います。学習後のエンコーダー->ベクトルデータ->デコーダの処理はデータの圧縮と復元を表し、乱数で生成したベクトルデータ->デコーダの処理が新たな3Dデータ(ロボットの顔)の生成になります。(ただし、文献でAuto Encoderは汎化能力に乏しいことがわかっているため本格的3Dデータ生成には向かないだろうとは予想しています。)

以下、800個の3Dデータで1000エポック学習(GPUを使用して半日ぐらい)させたのち、そのうちの1個のデータをエンコーダに入力、デコーダから出力させた各断面の画像です。

f:id:ichidaya:20210526223050j:plain

入力とAuto Encoder出力の各断面図

3次元データとして表示するとこんな感じ。128x128x128の3Dデータをいちど128次元のエンコーダでベクトルデータにおとし、デコーダで復元しています。

f:id:ichidaya:20210526223641j:plain

3Dデータの復元結果

Auto Encoderは汎化能力に乏しいためランダムデータから新しいロボットの頭部を作れるかというと残念ながらうまくいきません。

f:id:ichidaya:20210526224806j:plain

ランダムデータをもとに生成した3Dデータ

次は断面図リストを入出力とするアプローチでGANを試そうと思っています。