Upgrade to Pro — share decks privately, control downloads, hide ads and more …

【KMC春合宿2024】実装視点で見るNeural Radiance Fields

【KMC春合宿2024】実装視点で見るNeural Radiance Fields

KMC 春合宿2024の講座として発表したスライド資料です.内容はNeural Radiance FieldsをCUDA C++でフルスクラッチ実装してみたので,そのうえで実装に近い視点でNeural Radiance Fieldsを説明していくものとなります.実装に完全に特化した説明を読みたい場合は私が先日書いた記事を参考にしていただけると嬉しいです.CUDAによる実装(ソースコード)の一部とそれに対する説明,そしてそのプログラムを動かした結果などが記述されています.
[URL]
Part1: MLP編: https://tetrisyoshi.hatenablog.com/entry/2024/01/21/213713
Part2: エンコーダー編: https://tetrisyoshi.hatenablog.com/entry/2024/02/13/141046
Part3: NeRF編: https://tetrisyoshi.hatenablog.com/entry/2024/02/24/155515

Yoshi's Dream

March 11, 2024
Tweet

More Decks by Yoshi's Dream

Other Decks in Programming

Transcript

  1. 自己紹介 本名: (deleted) / HN: Yoshi’s Dream / KMCID: tetrisyoshi

    電気電子工学科 B2 / KMC47th 普段: 主に3DCGのレンダリング処理を書いてます. 興味: 物理現象のシミュレーション,画像処理,計算機のハードウェア最適化など けものフレンズはいいぞ 2
  2. 主なメモリの種類 (CUDA) ホスト(CPU)から転送する先のデバイス(GPU)メモリはglobal memoryという領域 global memory いわゆるGPUメモリ 大容量!RTX3080は10GBあります.A100なら80GBあります. 遅い!!! shared

    memory Blockごとに共有されているメモリ領域 On-Chipメモリであり,読み書きが非常に高速 容量が小さい!RTX3080だと48KB. __shared__ 修飾子で確保する 22
  3. 準備: パラメーターの探索 xの初期値を2とする.ηを0.1とする 𝑑𝐿 𝑑𝑥 = 𝑑𝐿 𝑑(𝑓−𝑔) 𝑑 𝑓−𝑔

    𝑑𝑥 = 𝑓 − 𝑔 2𝑥 + 2 x0 = 2.0 x1 = -3.4 x2 = -0.6352 x3 = -0.644909 x4 = -0.653864 … x1e3 = -0.950463 x1e5 = -0.994703 (1) xを𝑥0 で初期化する. (2) 収束するまで次を行う 2.1 𝑑𝐿 𝑑𝑥 を計算する (2.2) 𝑥 = 𝑥 − 𝜂 𝑑𝐿 𝑑𝑥 𝑓(𝑥) = 𝑥2 + 2𝑥 + 2 g(𝑥) = 1 L 𝑥 = 1 2 𝑓 𝑥 − 𝑔 𝑥 2 0 3 6 9 12 15 -4 -3 -2 -1 0 1 2 3 26
  4. 先ほど示した放射輝度の変化を計算したい t_nearからt_farまでに充満するボリュームの放射輝度への関与を考える C: 「色」 / σ: 「密度」 / r(t): カメラから距離tの座標

    / dir: カメラの視線ベクトル ボリュームにおける放射輝度の計算 𝑡𝑛𝑒𝑎𝑟 𝑡𝑓𝑎𝑟 レイ ボリューム 𝑅𝑎𝑑𝑖𝑎𝑛𝑐𝑒 𝑟𝑎𝑦 = න 𝑡𝑛𝑒𝑎𝑟 𝑡𝑓𝑎𝑟 𝑇 𝑡 𝜎 𝑟 𝑡 𝐶 𝑟 𝑡 , 𝑑𝑖𝑟 𝑑𝑡 𝑇 𝑡 = exp − න 𝑡𝑛𝑒𝑎𝑟 𝑡 𝜎 𝑟 𝑠 𝑑𝑠 33
  5. ボリュームにおける放射輝度の計算 計算機上で積分を行うのは厳しい レイ上にサンプル点を取り,離散的に計算する 細かい話は置いといて,下に示す式となる [“Optical Models for Direct Volume Rendering",

    Nelson Max, 1995] 𝑅𝑎𝑑𝑖𝑎𝑛𝑐𝑒 𝑟𝑎𝑦 = න 𝑡𝑛𝑒𝑎𝑟 𝑡𝑓𝑎𝑟 𝑇 𝑡 𝜎 𝑟 𝑡 𝐶 𝑟 𝑡 , 𝑑𝑖𝑟 𝑑𝑡 𝑇 𝑡 = exp − න 𝑡𝑛𝑒𝑎𝑟 𝑡 𝜎 𝑟 𝑠 𝑑𝑠 Camera ボリューム C1, σ1 C2, σ2 C3, σ3 C4, σ4 C5, σ5 δ1 δ2 δ3 δ4 Radiance 𝑟𝑎𝑦 = σ𝑖=1 𝑁 𝑇𝑖 (1 − exp −𝜎𝑖 𝛿𝑖 )𝐶𝑖 , where 𝑇𝑖 = exp(− σ 𝑗=1 𝑖−1 𝜎𝑗 𝛿𝑗 ) 34
  6. ボリュームレンダリング 誤差逆伝播 順方向は以下の式で計算できた やはり細かい計算はおいといて,次の式で微分が求まる. Radiance_k: カメラに入射するレイの放射輝度の内,k番目のサンプル点による放射輝度 つまりS_iはi+1番目以降のサンプル点による寄与の量を表す Radiance 𝑟𝑎𝑦 =

    σ𝑖=1 𝑁 𝑇𝑖 (1 − exp −𝜎𝑖 𝛿𝑖 )𝐶𝑖 , where 𝑇𝑖 = exp(− σ 𝑗=1 𝑖−1 𝜎𝑗 𝛿𝑗 ) 𝜕𝑅𝑎𝑑𝑖𝑎𝑛𝑐𝑒 𝜕𝐶𝑖 = 𝑇𝑖 (1 − exp(−𝜎𝑖 𝛿𝑖 )) 𝜕𝑅𝑎𝑑𝑖𝑎𝑛𝑐𝑒 𝜕𝜎𝑖 = 𝜎𝑖 (𝑇𝑖+1 𝐶𝑖 − 𝑆𝑖 ) 𝑆𝑖 = 𝑅𝑎𝑑𝑖𝑎𝑛𝑐𝑒 − ෍ 𝑘=1 𝑖 𝑅𝑎𝑑𝑖𝑎𝑛𝑐𝑒𝑘 1 2 3 4 5 38
  7. 概念としてのNeRF: まとめ (1): カメラから画像のピクセルに対応する方向にレイ(光線)を飛ばす (2): レイの経路上の点をサンプリング (3): サンプル点の座標,そしてレイの向きをニューラルネットワーク(NN)に入力 (4): NNを実行し,サンプル点における「色」と「密度」を計算

    (5): 得られたサンプル点の情報からボリュームレンダリング方程式を計算 (6): 計算結果と対応するピクセルの色を比較し,誤差を計算 (7): ボリュームレンダリングの処理を逆方向に行う (8): NNを誤差逆伝播 (9): NN最適化 (10): Occupancy Gridの最適化(16イテレーションごと) 40
  8. Occupancy Gridの構築 空間を一辺128マスのブロックに分割する (Morton Codeで陰に行う) 2種類のOccupancy Gridを構築する (1): Bit Occupancy

    Grid: 「物体」の有無を管理 (2): Float Occupancy Grid: 「密度」の程度を管理 NNの最適化時に(2)を更新し,その結果得られた(2)に基づいて(1)を更新する 手続き: (i): (2)の全てのブロックの値を0.95倍 (ii): (2)からM個のブロックを選択し,中身を現在の値,ブロック内のある一点における「密度」 の大 きい方で更新する (iii): (2)がある閾値を超えていれば(1)の対応するブロックをtrueに,そうでなければfalseにする. 43
  9. Occupancy Gridの実装に関する処理 Morton Codeとは? 空間充填曲線の一種 3次元で表現される座標を再帰構造で1次元で表現する 空間的に近い→メモリ上で近い メモリアクセスの局所性向上 例えば解像度を1辺4bitで表現するとすると(表現法の一例) x:

    𝑥1 𝑥2 𝑥3 𝑥4 y: 𝑦1 𝑦2 𝑦3 𝑦4 z: 𝑧1 𝑧2 𝑧3 𝑧4 Morton Code: 𝑥1 𝑦1 𝑧1 𝑥2 𝑦2 𝑧2 𝑥3 𝑦3 𝑧3 𝑥4 𝑦4 𝑧4 Morton Codeでソートすると右図のZみたいなカーブに沿ってindexが振られる 44 Z階数曲線 Wikipedia
  10. OccupancyGridを考慮したサンプリング処理 48 Radiance 𝑟𝑎𝑦 = σ𝑖=1 𝑁 𝑇𝑖 (1 −

    exp −𝜎𝑖 𝛿𝑖 )𝐶𝑖 , where 𝑇𝑖 = exp(− σ 𝑗=1 𝑖−1 𝜎𝑗 𝛿𝑗 )
  11. 50

  12. 51

  13. 52

  14. NeRF: まとめ (1): カメラから画像のピクセルに対応する方向にレイ(光線)を飛ばす (2): レイの経路上の点をOccupancy Gridを参照しつつサンプリング (3): サンプル点の座標,そしてレイの向きをニューラルネットワーク(NN)に入力 (4):

    NNを実行し,サンプル点における「色」と「密度」を計算 (5): 得られたサンプル点の情報からボリュームレンダリング方程式を計算 (6): 計算結果と対応するピクセルの色を比較し,誤差を計算 (7): ボリュームレンダリングの処理を逆方向に行う (8): NNを誤差逆伝播 (9): NN最適化 (10): Occupancy Gridの最適化(16イテレーションごと) 54
  15. 線形層(全結合層) 入力ベクトルの基底の線形結合を出力する W: パラメーター行列 / b: バイアス項 / x: 入力ベクトル

    / y: 出力ベクトル 特に,今回はバイアス項を使用しないので 𝒚 = 𝑊𝒙 + 𝒃 𝒚 = 𝑊𝒙 x1 x2 W11 W12 W21 W22 W31 W32 y1 y2 y3 W11*x1 + W12*x2 W21*x1 + W22*x2 W31*x1 + W32*x2 = = 56
  16. 逆伝播 計算で簡単に示せる 線形層(全結合層) Sigmoid (Logistic) ReLU 𝜕𝐿 𝜕𝒙𝑇 = 𝜕𝐿

    𝜕𝒚𝑇 𝑊 𝜕𝐿 𝜕𝑊 = 𝜕𝐿 𝜕𝒚 𝒙𝑇 𝑑𝐿 𝑑𝑥 = 𝑑𝐿 𝑑𝑦 𝑦(1 − 𝑦) 𝑑𝐿 𝑑𝑥 = ൞ 𝑑𝐿 𝑑𝑦 (𝑥 > 0) 0 (𝑒𝑙𝑠𝑒) 𝒚 = 𝑊𝒙 𝑦 = 1 1 + 𝑒−𝑥 𝑦 = max(0, 𝑥) 58
  17. 最適化処理 基本は勾配降下法 Adam: 勾配降下法の発展形の最適化関数(かなり強力) 59 𝑤 = 𝑤 − 𝜂

    𝜕𝐿 𝜕𝑤 𝑚 = 𝛽1 𝑚 + 1 − 𝛽1 𝜕𝐿 𝜕𝑤 𝑣 = 𝛽2 𝑣 + 1 − 𝛽2 𝜕𝐿 𝜕𝑤 2 ෝ 𝑚 = 𝑚 (1 − 𝛽1 𝑡) ො 𝑣 = 𝑣 (1 − 𝛽2 𝑡) 𝑤 = 𝑤 − 𝜂 ෝ 𝑚 ො 𝑣 + 𝜖
  18. バッチ処理: 線形層(全結合層) 実は,ベクトルが行列となるだけ 逆伝播も同じくして WX = 𝑊 𝒙𝟏 𝒙𝟐 𝒙𝟑

    … = 𝑊𝒙1 𝑊𝒙2 𝑊𝒙𝟑 … = 𝒚𝟏 𝒚𝟐 𝒚𝟑 … = 𝑌 𝜕𝐿 𝜕𝑋𝑇 = 𝜕𝐿 𝜕𝑌𝑇 𝑊 𝜕𝐿 𝜕𝑊 = 𝜕𝐿 𝜕𝑌 𝑋𝑇 y y x x y w w w w w w = y y x x y w w w w w w = y y y y y y y y y y y y x x x x x x x x 61
  19. Fully Fused MLP [NVIDIA 2021] NVIDIA GPUに最適化されたMLPの実装 shared memoryを最大活用し,global memoryとのやり取りを最小限に抑える

    各Blockが128バッチを処理する設計とする 入力層~出力層の次元は大きくても128次元とする 入力層から流れていくベクトルをshared memoryに載せたまま処理できる! bank conflictという現象を避けるためにゼロパディングすることもある 線形層(全結合層)の処理にTensorコアを使用する 行列演算にハードウェア最適化の恩恵を受けられる 63
  20. 原著NeRF - Network Green: Input Red: Output Blue: Fully-Connected Layer

    (Number is the dimension) Array: Black = ReLU / Orange = None/ Dashed = Sigmoid NeRF paper – Fig. 7 73
  21. The Network (𝑥, 𝑦, 𝑧) (𝐷𝑖𝑟𝑋, 𝐷𝑖𝑟𝑌, 𝐷𝑖𝑟𝑍) Density Color

    MHE FC ReLU FC ReLU FC ReLU FC ReLU FC SH Projection Input Exp Sigmoid V[0] [15:0] [31:16] 3 32 64 16 16 3 64 64 3 83
  22. 最後にもういちど整理 (1): カメラから画像のピクセルに対応する方向にレイ(光線)を飛ばす (2): レイの経路上の点をOccupancy Gridを参照しつつサンプリング (3): サンプル点の座標,そしてレイの向きをニューラルネットワーク(NN)に入力 (4): NNを実行し,サンプル点における「色」と「密度」を計算

    (5): 得られたサンプル点の情報からボリュームレンダリング方程式を計算 (6): 計算結果と対応するピクセルの色を比較し,誤差を計算 (7): ボリュームレンダリングの処理を逆方向に行う (8): NNを誤差逆伝播 (9): NN最適化 (10): Occupancy Gridの最適化(16イテレーションごと) 84
  23. 参考文献 NeRF: Representing Scenes as Neural Radiance Fields for View

    Synthesis [Ben Mildenhall et al. ECCV2020] Instant Neural Graphics Primitives with a Multiresolution Hash Encoding [Thomas Müller et al. SIGGRAPH2022] Optical Models for Direct Volume Rendering [Nelson Max. 1995] memoRANDOM ボリュームレンダリング方程式 (Volume Rendering Equation) 1 URL: https://rayspace.xyz/CG/contents/VLTE1/ NVIDIA Developer Blog, Thinking Parallel, Part III: Tree Construction on the GPU https://developer.nvidia.com/blog/thinking-parallel-part-iii-tree-construction-gpu/ Ushioさんのredpillの実装と解説スライド https://github.com/Ushio/redpill Optim Tech Blog. Instant NeRF の心臓、Multiresolution Hash Encoding をシンプルに実装しつつ2次元画像で試してみる https://tech-blog.optim.co.jp/entry/2022/04/22/100000 Real-time Neural Radiance Caching for Path Tracing tiny-cuda-nnのgitリポジトリ https://github.com/NVlabs/tiny-cuda-nn Tensorコアを使ってみた https://proc-cpuinfo.fixstars.com/2018/10/tensorcore/ 85