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

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

Pytorchの勉強を続ける

Pytorchの勉強を続けています。前回、基本的なGANは動いたと書きましたがどうもうまく学習できていないみたい・・・

オートエンコーダ(AE)のほうが学習状況の確認がしやすい(損失関数が1つだけなのでこいつが単調に減少していってくれればいちおう学習が進んでいると判断できる)ので、基本のAEまで戻ってプログラムしています。

今作っているAEは入力(下図の左)の3Dデータ(32x32x32)をエンコーダネットワークで100次元のベクトルに変換し、このベクトルをデコーダネットワークで元のサイズ(32x32x32)の3Dデータ(下図の右)に変換しています。

f:id:ichidaya:20210830214808j:plain

エンコーダへの入力とデコーダの出力の例 (1)

単純なAEだと損失関数としてエンコーダの入力とデコーダの出力の差(Binary Cross Entropy)を使うのですが、今回は出力が値のばらつきが正規分布になっているかというKL-Divergence(カールバックライブラーダイバージェンス)の項を追加しています。変分オートエンコーダと呼ばれています。

f:id:ichidaya:20210830220947j:plain

                             エンコーダへの入力とデコーダの出力の例 (2)

KL項の重みをどのくらいにするかにもよるのですが、変分オートエンコーダでは角やアンテナなどの特徴が失われてしまうことが多いです。

f:id:ichidaya:20210830222727j:plain

エンコーダへの入力とデコーダの出力の例 (3)

比較的学習しやすい変分オートエンコーダとシャープな出力が得られるGANを組み合わせるという手法もあるようです。

 

ロボットの頭部をAIでデザインできないかと試してみたい ーフレームワークをPytorchに変更ー

これまで3Dモデル生成のネットワークを作るのにTensorflow/Kerasというフレームワークを使っていたのですが、しばらく前からPytorchというフレームワークを使ってプログラムを作っています。2つのフレームワークDeep Learningフレームワークの2大勢力です。tensorflowが機能的に何か足りないとかということはないのですが、tensorflowでGANのプログラムをいじっているとフレームワークの中で発生したエラーの原因を特定できず煮詰まってしまっていて、何か目先を変えて打開したいというのがPytorchに手をだした理由です。

試行錯誤を続けてVisual Source CodeのJupyterプラグイン使ってデバッグするやりかたがやっとわかってきました。基本的なGANで32x32x32の3Dモデル(numpy配列)を作れるようになったところです。

損失関数の値をグラフにするやりかたもやっとわかってきました(これはDeep Learning)関係なくて単にPythonプログラミングをわかってなかっただけなんですが)。生成器の損失関数の値が学習をかさねるにつれて(乱高下しながらも)下がっていることがわかります。

f:id:ichidaya:20210803182929j:plain

モデル生成と識別それぞれの損失関数の値の変化

実際、同じ初期値をネットワークに入力しても学習が進んだネットワークからの出力はなんとなくロボットの頭部っぽい形が出力されています。

f:id:ichidaya:20210803190432j:plain

学習回数と生成される3Dモデル

プログラムとしては動いてくれていると思うのですが、ネットワークの学習の状況としてはまだまだです。モード崩壊とよばれる現象がおこっているらしく生成される形にバリエーションがないんですよね。ランダムに発生させたいろんな初期値を与えても生成される形は2,3個のパターンのどれかに落ちてしまう...

対応するための手法はいくつかあるので今後試していく予定です。

ひさびさにロボット骨格の新バージョン

前回のBlogからちょっと期間があいてしまいましたが、実はDeep Learningのプログラムでハマっておりました。デバッグのためのルールや方法を確立できず、機械学習フレームワークを変えていちから試してみたりと、低レベルから試行錯誤をやりなおしているところです。

気分を変えるため、お休みしていたロボットデザインの作業を進めようかと思うのですがこっちはこっちで煮詰まっているんですよね。基本となるロボットの骨格(と関節)を何度も繰り返している状態で、なかなか外装や変形機構の設計にたどりつけない..

そうはいっても何かしら新しいやりかたを試してみようということで、今回は下に示すような限られた種類のパーツを多数3Dプリントしておいてそれらを組み上げてロボットの骨格を作るということを試してみました。

f:id:ichidaya:20210721140932j:plain

ロボット骨格パーツの例(一部)

それぞれのパーツはFusion 360で設計していますが全体としてどんな形の骨格になるかはでたとこ勝負です。

f:id:ichidaya:20210721141648j:plain

骨格の仮組イメージ

パーツをAdventurer3で出力したら並べてみてこんなかたちにしようかと考えて後はネジを締めて組み立てました。

f:id:ichidaya:20210721142313j:plain

パーツを組み上げた骨格

モデリングにかかった時間は今までの中では一番短かったです。

ただ、関節の自由度は前のバージョンより少ないしポーズの保持力もいまいち。

ネジの数がやたらと多くなってしまったのはご愛敬。

このアプローチももう少し試してみようかなと思っています。

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を試そうと思っています。

新しいパソコンでDeep Dreamを試してみた

今回購入したパソコンの筐体はいわゆるフルタワー、このサイズのパソコンを買ったのは30年ぶりぐらいかな。中を開けるとこんな感じです。

f:id:ichidaya:20210430131605j:plain

本体の側面カバーを開けたところ

電子部品としてはマザーボードとグラフィックボード(GEFORCE RTX 3090)だけである意味スカスカですが、熱対策が重要なんでしょうね。昔では考えられなかったようなでっかいファンがいくつもついています。

f:id:ichidaya:20210430132215j:plain

グラフィックボードRTX3090

このスペックならいろんなDeep Learningニューラルネットワークを動かすことができそうです。そこで(3Dモデリングとは直接関係ないのですが)、Deep Dreamというおもしろそうなアプリケーションがあったので試してみました。雲の流れとは天井板の木目模様とかをじっと眺めていると、人の顔とか動物に見えてくることがありますよね。Deep Dreamはこういった錯覚(幻覚?)をニューラルネットでエミュレート(今回は下記のURLのコードを利用)することでいわゆる「悪夢」のような画像を作り出してくれます。

https://www.tensorflow.org/tutorials/generative/deepdrea

左端はオリジナル画像、中と右端が徐々にDeep Dreamの効果を強めて処理していった結果です。

f:id:ichidaya:20210430140622j:plain

Deep Dream実行例

このDeep Dreamの実装ではInceptionV3という定義済のニューラルネットワークを使い、ImageNetという画像データベースを使って学習した状態で提供されています。画像の処理に要する時間は1枚当たり数秒程度でした(処理の瞬間のCUDAs使用率は100%近くに達しています)。

 

GPUでDeep Learningの学習がどれだけ速くなるか

先週、オーダーしていた新しいPCが届きました。グラフィックカードGEFORCE RTX 3090を搭載、メモリ64Gバイト、CPUは8コア2.5GHzという自分史上最高スペックのマシンです。週末にTensorflow等のDeep Learning用ソフトウェアのセットアップを行い、GPUによる高速化効果を確認しました。

比較に用いたGPU無しの環境はふだん使っているノートパソコンですが、AMD RYZEN(8コア、1.7GHz)、メモリ32Gバイトとそれなりに強力な(と思う)マシンです。

下の表に時間計測の結果をまとめましたが、当然ながらGPUの効果(どれだけ速くなるか)はタスクの内容(ネットワークの層の数、ニューロンの数)によってだいぶ異なっていました。

学習タスク GPU無し GPUあり GPUの効果 CUDA使用率
A.画像分類               59秒             32秒    1.8倍     63%
B.3DデータのVAE 4時間17分36秒        1分11秒    217.7倍     100%

 

Aの画像分類のタスクは教科書に載っているもので写真に写っている鳥や馬、自動車など10種類の動物や乗り物を識別するというものです。

f:id:ichidaya:20210415225248j:plain

画像分類の結果

隠れ層の数は2、学習するパラメータ数は646,260、32x32 のRGB画像5万枚を学習に使っていて機械学習のタスクとしては軽いほうだと思います。GPU有りと無しの環境とで処理時間は1.8倍程度にしか上がっていません。CPUのクロック差で速くなっている分もあると考えるとGPUの効果はかなり限定的といえます。

一方のBはロボットの3Dモデル生成のために私が作成中の変分オートエンコーダー(VAE)と呼ばれるタイプのネットワークの学習です。隠れ層、畳込み層の数は9、学習するパラメータ数は7,395,841、64x64x64の3Dモデル1280個を学習に使っています。こちらはGPU有無の差が200倍以上になっています。タスクの規模が比較的大きくて、かつ計算処理の中で並列に実行できる割合が高ければCUDAコア数の分だけ並列に(つまり高速に)実行できるということなんでしょう。ちなみにRTX 3090は10496個のCUDAコアを持っていますが、学習タスクを走らせているあいだはほぼ100%使われていました。

 

 

 

 

やっぱり速いPCが欲しい、という話

 GAN(敵対的生成ネットワーク)で生成する3Dモデルの精度やバリエーションをもっと改善したいと学習するモデル解像度を32x32x32から64x64x64にスケールアップしたのですが、結果は惨憺たるものでした。得られた生成モデルに何を入力しても、どれも同じような丸っこい形しか出力されません。学習データの数が足りないのか、ネットワークモデルの構成に問題があるのか、分析したいのですがそこでボトルネックになるのがネットワーク学習の処理時間です。

手持ちのPCでの処理は遅くて論外です。1バッチ分の学習に5分から10分かかるので、仮に3000回学習したらまる10日以上かかってしまう。いくつかDeep Learning用にPCインスタンスを提供してくれるクラウドサービスを試してみて、AWSのEC2サービス(GPU1個のインスタンス)を使ったのですがそれでも1回の学習に数時間かかってしまいました。このインスタンスの使用料は1時間当り$4.19です。インスタンスを起動する度に時計がリセットされて課金が始まるので、起動・10分使用・停止を3回繰り返すと3時間分の課金になります。

本番の学習処理に数千円かかるのはしょうがないにしても、プログラムやデータのロードなど環境の変更などのちょっとしたお試しで短時間インスタンスを立ち上げるたびに400円強ずつの出費が積み重なっていくというのはがまんできない..

以上、物欲に負けた言い訳をつらつらと書きましたが自分でそこそこの実験ができる環境を確保しようとポチッとしてしまったのがこのグラフィックカードを採用したBTOパソコン。

AWSで動かした経験だとGPUのメモリが16GBだと大きなテンソルデータを処理するのに容量的にギリギリだったのでRTX3090で24GBメモリがあればとりあえず十分かなと思っています。納期は4~5週間ということで、到着を楽しみにしています。