## HumanMAC: Masked Motion Completion for Human Motion Prediction [github](https://github.com/LinghaoChan/HumanMAC/tree/main) ### 前言 **擴散模型(Diffusion Model)** ![image](https://hackmd.io/_uploads/BJguZR1axe.png) 將原始圖片逐漸加入雜訊(Noise),讓原本的圖片逐漸變成完全的雜訊狀態。然後再透過反轉這個過程,也就是Denoise去除雜訊來恢復圖片。讓它學習了雜訊圖和真實圖片之間的變換關係,最後使其能夠從雜訊中生成出像樣的圖片。 1. 正向過程(Forward Process/Diffusion Process):對圖片逐步增加雜訊。 2. 反向過程(Reverse Process):從雜訊中逐步恢復圖片。 --- ### 概述 ![image](https://hackmd.io/_uploads/Syrwz_A3eg.png =50%x) 以往的人體動作預測方法多採用 **encoder - decoder** 框架,雖然有不錯表現,但存在幾個問題: - 多數先進方法需要多種損失函數才能獲得高品質的預測結果,例如APD、FDE,以及對抗損失,需要精心設計超參數來平衡不同損失,導致應用上相當繁瑣。 - encoder/decoder 和 latent sampling 是在不同階段完成的,流程複雜。 - 受限於已觀測的動作序列,難以實現切換動作類別(如從走路到坐下),導致多樣性不足。 --- ### 內容 **Masked motion Completion, HumanMAC** 跳脫出 encoder/decoder 的方式來處理 HMP 問題。 - 訓練階段:將已觀測與預測的動作結合,學習一個從隨機噪聲生成動作的 **motion diffusion model**,從雜訊生成動作序列,只用單一 loss(噪聲預測 MSE loss)。 - 推論階段:提出 **DCT-Completion**,將觀測到的動作加雜訊,再透過 masking 機制與去噪過程結合,讓預測動作 **可控且連續**。 **架構特色** - 僅需單一 loss,端到端訓練。 - 可自然完成動作轉換(motion switch),如坐下→站立。 - 支援部位可控預測 (part-body controllable prediction)。 --- ### 流程 - 訓練階段 #### 1. 輸入完整的動作序列 $\mathbf{x} \in \mathbb{R}^{(H+F)\times 3J}$ (包含過去 $H$ 幀 + 未來 $F$ 幀),來預測接下來長度 $F$ 的未來序列 $$ \mathbf{x}^{(1:H)} = \big[ \mathbf{x}^{(1)} ; \mathbf{x}^{(2)} ; \ldots ; \mathbf{x}^{(H)} \big] \in \mathbb{R}^{H \times 3J} $$ $$ \mathbf{x}^{(H+1:H+F)} = \big[ \mathbf{x}^{(H+1)} ; \mathbf{x}^{(H+2)} ; \ldots ; \mathbf{x}^{(H+F)} \big] \in \mathbb{R}^{F \times 3J} $$ * $𝐻$:觀測到的歷史幀數 * $J$:關節數量 * $\mathbf{x}^{(h)} \in \mathbb{R}^{3J}$ :第 $h$ 個影格中所有關節的三維座標 #### 2. 將動作序列透過 DCT 轉換投影到頻域 $$ \mathbf{y} = \mathrm{DCT}(\mathbf{x}) = \mathbf{D}\mathbf{x} $$ * $\mathbf{y} \in \mathbb{R}^{(H+F)\times 3J}$:經過 DCT 轉換的已觀測到動作序列 * $\mathbf{D} \in \mathbb{R}^{(H+F)\times(H+F)}$:預先定義的 DCT 基底矩陣 * $\mathbf{x} \in \mathbb{R}^{(H+F)\times 3J}$:完整序列(過去 $H$ 幀 + 未來 $F$ 幀真值),時間長度 $(H+F)$ 幀 $$ \mathbf{x} = \big[ \mathbf{x}^{(1:H)} ; \underbrace{\mathbf{x}^{(H+1:H+F)}}_{\text{未來真值}} \big] \; (\text{完整真值序列}) $$ >鑑於人體動作在**時間上平滑**的特性,採用**截斷版 DCT/iDCT**:只取 $\mathbf{D}$ 與 $\mathbf{D}^\top$ 的前 $L$ 列 ( 分別記為 $\mathbf{D}_L$ 、 $\mathbf{D}_L^\top$ ) $$ \mathbf{c} \approx \mathbf{D}_L \mathbf{x}, \qquad \mathbf{x} \approx \mathbf{D}_L^\top \mathbf{c} $$ 取前 $L$ 個頻率分量(低頻)能捕捉**長期趨勢與平滑性**,對於保證預測的**連續 / 不抖動**尤為關鍵,同時節省運算量。在不致混淆的情況下,後文以 $\mathbf{D}_L$ 取代 $\mathbf{D}$ 記號。 $$ \mathbf{c} \equiv \mathbf{y}_0 = \mathbf{D}_L \mathbf{x} $$ >* $\mathbf{y}_0 \in \mathbb{R}^{L \times 3J}$:取前 $L$ 個頻率之後的頻譜 >* $\mathbf{D}_L \in \mathbb{R}^{L \times (H+F)}$:只取 $\mathbf{D}$ 的前 $L$ 個低頻的 DCT 基底矩陣 >* $\mathbf{x} \in \mathbb{R}^{(H+F)\times 3J}$:完整序列(過去 $H$ 幀 + 未來 $F$ 幀真值),時間長度 $(H+F)$ 幀 >**為什麼不直接在時間域做擴散?** DCT 能同時保留當前與週期性的時間性質,且低頻對連續動作更關鍵,所以在頻域學去噪更穩、更省算。 #### 3. 前向加噪 (Forward noising) 將乾淨的動作頻譜逐步轉化為高斯噪聲,建立一條從「真實序列」到「純噪聲」的馬可夫鏈,讓模型在訓練時學會如何反向去噪。 對於低頻的 DCT 特徵 $\mathbf{y}_0 \in \mathbb{R}^{L \times 3J}$ ,在第 $t$ 步的帶噪表達式為: $$ \mathbf{y}_t=\sqrt{\overline{\alpha}_t}\,\mathbf{y}_0+\sqrt{1-\overline{\alpha}_t}\,\epsilon,\quad \epsilon\sim\mathcal{N}(0,\mathbf{I}) $$ * $t$:前向加噪過程的總長度 * $\mathbf{y}_t \in \mathbb{R}^{L \times 3J}$:在時間步 $t$ 的帶噪特徵,隨著 $t$ 增加會越來越接近純噪聲 * $\mathbf{y}_0 \in \mathbb{R}^{L \times 3J}$:乾淨的低頻特徵 * $\bar{\alpha}_t=\displaystyle\prod_{i=1}^{t}\alpha_i \in \mathbb{R}$:為**累積訊號保留率** (cumulative product),表示從第 1 步到第 $t$ 步過程中訊號還剩下多少比例 >當 $t$ 小:$\bar{\alpha}_t \approx 1$,訊號幾乎沒破壞 >當 $t$ 大:$\bar{\alpha}_t \approx 0$,訊號幾乎消失,只剩噪聲 * $\epsilon\sim\mathcal{N}(0,\mathbf{I}),\ \epsilon\in\mathbb{R}^{L\times 3J}$:與 $\mathbf{y}_0$ 同形狀的高斯白噪聲 * $\sqrt{\overline{\alpha}_t}\,\mathbf{y}_0$:保留訊號的一部分,隨 $t$ 增加會縮小 * $\sqrt{1-\overline{\alpha}_t}\,\epsilon$:逐步加入的隨機噪聲,隨 $t$ 增加會變大 #### 4. 噪聲預測 (Noise Prediction) 在第 $t$ 步,模型輸入帶噪的 DCT 特徵 $\mathbf{y}_t$,並輸出對應的噪聲預測。 $$ \epsilon_{\theta}(\mathbf{y}_t,t) $$ - $\theta$:可學習參數的神經網路(HumanMAC 採用 TransLinear 結構) - $\mathbf{y}_t$:在時間步 $t$ 的帶噪特徵 - $t$:噪聲步數,用來告知網路目前的加噪強度 >目的:網路學習去預測真實加入的噪聲 $\epsilon$,也就是 diffusion model 的標準訓練方式 #### 5. 損失函數 (Loss Function) 採用單一的 MSE 損失,用來度量模型預測噪聲與真實噪聲之間的誤差。 讓模型學會在任意時間步 $t$,輸入帶噪樣本 $\mathbf{y}_t$ 後,正確地預測出當時加進去的真實噪聲 $\epsilon$。 $$ \mathcal{L} =\mathbb{E}_{\epsilon,t}\!\left[\left\|\,\epsilon-\epsilon_{\theta}(\mathbf{y}_t,t)\,\right\|_2^{2}\right] $$ - $\epsilon\sim\mathcal{N}(0,\mathbf{I})$:真實加入的高斯白噪聲 - $\epsilon_{\theta}(\mathbf{y}_t,t)$:模型的噪聲預測 - $\mathbb{E}_{\epsilon,t}[\cdot]$:表示對「不同的噪聲樣本 $\epsilon$」與「不同的步數 $t$」做期望(取平均) **總結** ![image](https://hackmd.io/_uploads/B12Tix1Tlg.png =70%x) --- ### 流程 - 推理階段 #### 1. 輸入僅有觀測到的過去序列$\mathbf{x}^{(1:H)}$ (不是完整序列),目的是讓模型生成接下來的 $F$ 幀。 $$ \mathbf{x}^{(1:H)} = \big[ \mathbf{x}^{(1)} ; \mathbf{x}^{(2)} ; \ldots ; \mathbf{x}^{(H)} \big] \in \mathbb{R}^{H \times 3J} $$ * $𝐻$:觀測到的歷史幀數 * $\mathbf{x}^{(h)} \in \mathbb{R}^{3J}$ :第 $h$ 個影格中所有關節的三維座標 #### 2. 序列補長 + DCT 轉換 模型只有過去序列 $\mathbf{x}^{(1:H)}$,但要生成長度 $H+F$ 的完整序列,因此要先把序列補長。 將最後一幀 $\mathbf{x}^{(H)}$ 重複 $F$ 幀,把序列補到長度 $H+F$ 後做 DCT 轉換。 $$ \mathbf{x}=\left[\mathbf{x}^{(1:H)},\ \underbrace{\mathbf{x}^{(H)},\ldots,\mathbf{x}^{(H)}}_{\text{ }F\text{ 幀}}\right]\in\mathbb{R}^{(H+F)\times 3J} $$ $$ \mathbf{c} \equiv \mathbf{y}_0 = \mathbf{D}_L \mathbf{x} $$ * $\mathbf{y}_0 \in \mathbb{R}^{L \times 3J}$:取前 $L$ 個頻率之後的頻譜 * $\mathbf{D}_L \in \mathbb{R}^{L \times (H+F)}$:只取$\mathbf{D}$ 的前 $L$ 個低頻的 DCT 基底矩陣 * $\mathbf{x} \in \mathbb{R}^{(H+F)\times 3J}$:完整序列(過去 $H$ 幀 + 未來 $F$ 幀真值),時間長度 $(H+F)$ 幀 #### 3. 初始化生成噪聲 (Initialization) 模型要從「純噪聲」開始逐步去噪,所以初始化時會直接生成一個與輸入形狀相同的隨機噪聲。 $$\mathbf{y}_T \sim \mathcal{N}(0, I)$$ * $\mathbf{y}_T \in \mathbb{R}^{L \times 3J}$:diffusion 過程的最後一步 (最強噪聲狀態),是演算法的起點,跟 DCT 特徵 $\mathbf{y}_0$ 相同。 >為什麼要初始化成純噪聲? 在 diffusion 生成模型裡,推理必須從高斯白噪聲開始,透過反向過程一步步還原訊號。 這樣才能保證生成過程具有「隨機性 → 多樣性」。 #### 4. DCT-Completion - 反向迭代,從純噪聲 $\mathbf{y}_T$ 開始,逐步還原訊號 傳統的擴散式方法:完成訓練後透過 $T$ 次去噪步驟來生成序列,但此流程無法利用觀測幀,因此生成結果不可控。 → 不需重新訓練的演算法 DCT-Completion:能在推論時以觀測動作為條件來補齊未來動作。 * 每個時間步範圍: $$t=T,T-1,\ldots,1$$ >DDIM steps:推論時實際使用的步數 **(a) 對觀測序列加噪 (保持過去 $H$ 幀條件)** 左支 在反向過程中「鎖住」過去 $H$ 幀不讓它們被改變,確保模型生成的序列會「連續且符合觀測」。 把觀測序列用最後一幀補到長度 $H+F$,再投影到 DCT 域得到 $y$。接著在時間步 $t−1$ 對 $y$ 加噪以取得「觀測端的帶噪頻譜」: $$\mathbf{y}^{n}_{t-1}=\sqrt{\overline{\alpha}_{t-1}}\,\mathbf{y}+\sqrt{1-\overline{\alpha}_{t-1}}\,\mathbf{z},\ \ \mathbf{z}\sim\mathcal{N}(0,\mathbf{I})$$ $$\mathbf{y}^{n}_{t-1}\sim q(\mathbf{y}_{t-1}\mid \mathbf{y})$$ * $\mathbf{y}^{n}_{t-1} \in \mathbb{R}^{L \times 3J}$:在 第 $t−1$ 步的觀測端帶噪聲頻譜,「訊號 + 噪聲」的混合體 * $\bar{\alpha}_{t-1} \in[0,1]$:是純量,代表累積訊號保留率,表示訊號在第 $t−1$ 步還剩多少比例 * $\mathbf{y} \in \mathbb{R}^{L \times 3J}$:補齊序列 (長度 $H+F$) 之後投影到 DCT 領域的頻譜表示 * $\mathbf{z} \in \mathbb{R}^{L \times 3J}$:高斯白噪聲 * $\sqrt{\overline{\alpha}_{t-1}}\,\mathbf{y} \in \mathbb{R}^{L \times 3J}$:保留訊號的一部分,隨 $t$ 增加會縮小 * $\sqrt{1-\overline{\alpha}_{t-1}}\,\mathbf{z} \in \mathbb{R}^{L \times 3J}$:逐步加入的隨機噪聲,隨 $t$ 增加會變大 **(b) 生成端去噪** 右支 [.](https://hackmd.io/@q_bRZRi5Q2iTv2zdBQYQHg/SkEF3wWTxg) 利用網路去掉噪聲,還原訊號。 由 $\mathbf{y}_t$ 得到「預測端的去噪頻譜」 $\mathbf{y}^{d}_{t-1}$ $$\mathbf{y}^{d}_{t-1}=\dfrac{1}{\sqrt{\alpha_t}}\!\left(\mathbf{y}_t-\dfrac{1-\alpha_t}{\sqrt{1-\overline{\alpha}_t}}\;\epsilon_{\theta}(\mathbf{y}_t,t)\right)+\sigma_t\mathbf{z}$$ $\text{其中 } t=1:\ \mathbf{z}\sim\mathcal{N}(0,\mathbf{I});\ \text{否則 } \mathbf{z}=\mathbf{0}$ $$ \mathbf{y}^{d}_{t-1}\sim p_{\theta}(\mathbf{y}_{t-1}\mid \mathbf{y}_t) $$ * $\mathbf{y}^{d}_{t-1} \in \mathbb{R}^{L \times 3J}$:第 $t−1$ 步生成端的去噪後頻譜 * $\mathbf{y}_t \in \mathbb{R}^{L \times 3J}$:在第 $t$ 步的帶噪聲頻譜 * $\alpha_t$:變異數排程參數 (variance schedule),是純量,決定該步保留多少訊號 * $\epsilon_{\theta}(\mathbf{y}_t,t) \in \mathbb{R}^{L \times 3J}$:噪聲預測網路的輸出 * $\sigma_t$:決定隨機性,若取 0 則生成是確定性的 (DDIM),若取非 0 則生成有隨機性 (DDPM) * $\mathbf{z} \in \mathbb{R}^{L \times 3J}$:高斯白噪聲 **( c ) 用 iDCT 把頻域的結果轉回時間域然後輸出動作序列** 每一步迭代裡的 iDCT $$ \mathrm{iDCT}(\mathbf{y}^{n}_{t-1}), \quad \mathrm{iDCT}(\mathbf{y}^{d}_{t-1}) $$ 最後一步的 iDCT $$ \hat{\mathbf{x}} = \mathrm{iDCT}(\mathbf{y}_0) = \mathbf{D}^\top \mathbf{y}_0, \quad \hat{\mathbf{x}} \in \mathbb{R}^{(H+F)\times 3J} $$ * $\mathbf{y}_0\in\mathbb{R}^{L\times 3J}$:diffusion 完成後得到的乾淨頻譜 * $\mathbf{D}_L^\top \in \mathbb{R}^{(H+F) \times L}$:只取 $\mathbf{D}$ 的前 $L$ 個低頻的 IDCT 基底矩陣 * $\hat{\mathbf{x}}$:長度 $H+F$ 的輸出結果 **(d)遮罩式補全 (Mask Completion)** 在已訓練好的擴散模型中,$\mathbf{y}^{n}_{t-1}$ (觀測端)與 $\mathbf{y}^{d}_{t-1}$ (生成端)在分佈上近似一致;因此把兩者投回時間域(iDCT)後,用遮罩 $M$ 逐幀組合,再送回 DCT 域,確保輸出既符合條件又能生成合理的未來。 $$ \mathbf{y}_{t-1} =\mathrm{DCT}\!\Big( \mathbf{M}\odot \mathrm{iDCT}(\mathbf{y}^{n}_{t-1}) +\big(\mathbf{1}-\mathbf{M}\big)\odot \mathrm{iDCT}(\mathbf{y}^{d}_{t-1}) \Big) $$ * $\mathbf{y}_{t-1} \in \mathbb{R}^{L \times 3J}$:在 $t−1$ 步的最終更新頻譜 * $\mathbf{y}^{n}_{t-1} \in \mathbb{R}^{L \times 3J}$:用「觀測(加噪後)回到時域」的訊號 * $\mathbf{y}^{d}_{t-1} \in \mathbb{R}^{L \times 3J}$:用「模型去噪預測」的訊號 * $⊙$:元素對應相乘 * $\mathbf{M} =\big[\underbrace{1,\ldots,1}_{H},\underbrace{0,\ldots,0}_{F}\big]^{\top} \in\mathbb{R}^{H+F}$:遮罩向量 * 前 $H$ 幀(已觀測的過去動作):$M=1$,保留觀測(加噪後)的訊號 * 後 $F$ 幀(未來要預測的動作):$M=0$,因此在這段區域不採用觀測,而是由模型去噪預測提供訊號。 ![image](https://hackmd.io/_uploads/BkgJOdW6xg.png) **總結** ![image](https://hackmd.io/_uploads/ByC2-Nlalg.png =70%x) --- ### 附加流程 - Motion Switch 讓生成的序列不只延續觀測幀,還能在推理過程中 插入一段「目標動作」(target motion),實現動作類別的切換。 公式裡的遮罩向量 $M$: $$\mathbf{M}=[\underbrace{1,1,\ldots,1}_{H},\ \underbrace{0,0,\ldots,0}_{F-M},\ \underbrace{1,1,\ldots,1}_{M}]^{\top}$$ * 預測長度:$F$ 幀 * 前 $H$ 幀:保持觀測幀 → $M=1$ * 中間 $F−M$ 幀:讓模型自由生成,平滑過渡到新動作 → $M=0$ * 後 $M$ 幀:強制套用「目標動作 (target motion)」 → $M=1$ --- ### TransLinear HumanMAC 裡的核心噪聲預測網路,在每一步迭代裡幫忙把目前的帶噪頻譜 $y_t$ 去噪。 輸入是 $(\mathbf{y}_t,\,t)$,輸出是 $\epsilon_{\theta}(\mathbf{y}_t,\,t)$。 Human3.6M 用 8 層 TransLinear block,HumanEva-I 用 4 層 TransLinear block。 :::spoiler HumanMAC/models/transformer.py ```javascript=198 class TemporalDiffusionTransformerDecoderLayer(nn.Module): def __init__(self, latent_dim=32, time_embed_dim=128, ffn_dim=256, num_head=4, dropout=0.5, ): super().__init__() self.sa_block = TemporalSelfAttention( latent_dim, num_head, dropout, time_embed_dim) self.ffn = FFN(latent_dim, ffn_dim, dropout, time_embed_dim) def forward(self, x, emb): x = self.sa_block(x, emb) x = self.ffn(x, emb) return x ``` ::: 每層都包含兩個模塊且按順序執行: 1. TemporalSelfAttention:先處理輸入,建立時序依賴關係 :::spoiler HumanMAC/models/transformer.py **TemporalSelfAttention** ```javascript=129 class TemporalSelfAttention(nn.Module): def __init__(self, latent_dim, num_head, dropout, time_embed_dim): super().__init__() self.num_head = num_head self.norm = nn.LayerNorm(latent_dim) self.query = nn.Linear(latent_dim, latent_dim, bias=False) self.key = nn.Linear(latent_dim, latent_dim, bias=False) self.value = nn.Linear(latent_dim, latent_dim, bias=False) self.dropout = nn.Dropout(dropout) self.proj_out = StylizationBlock(latent_dim, time_embed_dim, dropout) def forward(self, x, emb): """ x: B, T, D """ B, T, D = x.shape H = self.num_head # B, T, 1, D query = self.query(self.norm(x)).unsqueeze(2) # B, 1, T, D key = self.key(self.norm(x)).unsqueeze(1) query = query.view(B, T, H, -1) key = key.view(B, T, H, -1) # B, T, T, H attention = torch.einsum('bnhd,bmhd->bnmh', query, key) / math.sqrt(D // H) weight = self.dropout(F.softmax(attention, dim=2)) value = self.value(self.norm(x)).view(B, T, H, -1) y = torch.einsum('bnmh,bmhd->bnhd', weight, value).reshape(B, T, D) y = x + self.proj_out(y, emb) return y ``` ![image](https://hackmd.io/_uploads/r1Q06Lball.png =50%x) ::: 2. FFN:接著對注意力輸出進行特徵變換 :::spoiler HumanMAC/models/transformer.py **FFN** ```javascript=113 class FFN(nn.Module): def __init__(self, latent_dim, ffn_dim, dropout, time_embed_dim): super().__init__() self.linear1 = nn.Linear(latent_dim, ffn_dim) self.linear2 = zero_module(nn.Linear(ffn_dim, latent_dim)) self.activation = nn.GELU() self.dropout = nn.Dropout(dropout) self.proj_out = StylizationBlock(latent_dim, time_embed_dim, dropout) def forward(self, x, emb): y = self.linear2(self.dropout(self.activation(self.linear1(x)))) y = x + self.proj_out(y, emb) return y ``` ![image](https://hackmd.io/_uploads/HyiZ0LZTex.png =50%x) ::: --- ### 資料集 - 主要資料集 | 名稱 | 主體/頻率 | 關節數(V) | 任務 | |:----------:|:-------------------------------:|:------:|:-------------------------------------------:| | Human3.6M | 11 位受試者,約 360 萬幀,50 Hz/s | 17 | 給定過去 25 幀(0.5秒),預測未來 100 幀(2秒) | | HumanEva-I | 3 位受試者,60 Hz/s | 15 | 給定過去 15 幀(0.25秒),預測未來 60 幀(1秒) | | 參數 | 設定 | |:-------------------------:|:-----------------------------------------:| | epoch | Human3.6M:1001,HumanEva-I:501 | | batch size | 64 | | 每個 epoch 處理的訓練樣本 | 50000 | | DCT 係數(M) | Human3.6M:前 20 個,HumanEva-I:前 10 個 | - 額外驗證:CMU-MoCap、AMASS(含 zero-shot 評估) --- ### 實驗結果 [github](https://github.com/LinghaoChan/HumanMAC/tree/main) **(a) 與 SOTA 比較** - HumanMAC 在 **ADE、FDE**(準確性)達到 SOTA,且動作更合理。 - 在 **APD(多樣性)** 指標略低,但避免了 baseline 常見的「失敗案例造成假多樣性」。 ![image](https://hackmd.io/_uploads/BkTOMDWple.png) **(b) 可視化結果** - HumanMAC 較少出現物理不合理的預測(如浮空、突然彎曲)。 **( c ) 動作切換 Motion Switch** - 能順暢轉換稀有或未見過的動作(如坐下 → 站立、轉身)。 **(d) 部分身體可控預測 Part-body Controllable Prediction** - 可固定下半身,生成合理的上半身動作。 - 基線方法 GSPS 和 DLow 僅能實現上下半身的控制,因為它們需要顯式地解耦上下半身的動作。而且在解耦後,這些方法還需要重新訓練模型,才能實現部分身體可控能力。相比之下,我們的方法不依賴於模型的重新訓練,即可對身體的任意部分進行可控預測。 **(e) 消融實驗 (Ablation Studies)** 1. DCT/iDCT 中 L 的取值 ![image](https://hackmd.io/_uploads/r1sV8v-plg.png) 2. 噪聲預測網路層層數的設計 ![image](https://hackmd.io/_uploads/HJ4c8PZ6ge.png) 3. 擴散模型的設定 探討去噪步數長度,以及不同的擴散方差排程方式(如 Linear、Cosine 和 Sqrt)對實驗結果的影響 [擴散方差排程方式](https://hackmd.io/@q_bRZRi5Q2iTv2zdBQYQHg/SkEF3wWTxg) ![image](https://hackmd.io/_uploads/Hy8QwP-Txl.png) 預設加噪與採樣的步數分別設為 1000 與 100,如果將加噪與採樣的步數同時縮減 10 倍,生成動作的真實性會明顯下降。此外步數的減少會導致視覺化結果中出現「抖動」的動作。 ![image](https://hackmd.io/_uploads/BkPHDvZagl.png) **(f) 零樣本動作預測 Zero-shot Evaluation** 在 Human3.6M 數據集上訓練 HumanMAC 模型,並利用給定的 AMASS 數據集中的觀測動作進行動作預測。結果表現合理且多樣,生成未見過的動作(如 kneeling),展現了 HumanMAC 框架良好的泛化能力。 **(g) 在其他資料集上的評估** 將 HumanMAC 與以 VAE 與以擴散模型為基礎的方法,在 CMU-MoCap 與 AMASS 兩個資料集上進行比較。 HumanMAC 在兩個資料集上都展現出更優越的表現,顯示其遮罩補全機制(mask-completion)具有強大的預測能力。 ![image](https://hackmd.io/_uploads/ByHrJub6xx.png) **(h) DCT 設計的消融實驗** 未使用 DCT 的模型會出現嚴重抖動,使用DCT 能讓預測更為準確。 ![image](https://hackmd.io/_uploads/BkdJWdbaxl.png =50%x)![image](https://hackmd.io/_uploads/ryYe-O-axg.png =50%x) **(i) 長序列預測** 將最後 $H$ 幀的預測視為觀測,並不斷遞迴地預測後續動作。基線方法傾向於預測過度平滑、幾乎靜止的動作,HumanMAC 生成的動作比 baseline 多樣且不會過度平滑。 ![image](https://hackmd.io/_uploads/r1ob-_-agl.png) --- ### 缺點 - **效率限制**:需要約 100 步 DDIM 取樣,速度不足以應用於即時系統。 - **多樣性指標問題**:作者指出現有的 APD 衡量方式可能誤導(高分可能來自錯誤樣本),仍需更合理的多樣性評估指標。 - **未測試大規模資料集**:目前僅在中型數據集評估,未在大規模全身動作庫進行完整驗證。 - **網路結構仍偏複雜**:未來計劃簡化模型與演算法。