# 🤖 AI Motion 模型開發與訓練全指南 (完整版) 本文件整合了從數據預處理、序列預測(Predictor)到隨機生成(VAE)的完整實作路徑。 --- ## 📂 第一部分:動作序列預測模型 (Motion Predictor) **目標**:輸入前 60 幀,預測下一幀(第 61 幀)。適用於動作補完或即時互動。 ### 1. 模型架構 ```python import torch import torch.nn as nn class MotionPredictor(nn.Module): def __init__(self, input_dim=120, model_dim=256, nhead=8, num_layers=3): super().__init__() # 位置編碼與投影 self.pos_encoder = nn.Parameter(torch.zeros(1, 60, model_dim)) self.input_projection = nn.Linear(input_dim, model_dim) # Transformer Encoder enc_layer = nn.TransformerEncoderLayer(d_model=model_dim, nhead=nhead, batch_first=True) self.transformer_encoder = nn.TransformerEncoder(enc_layer, num_layers=num_layers) # 輸出層:將特徵轉回原始維度 self.decoder = nn.Linear(model_dim, input_dim) def forward(self, src): # src: (Batch, 60, 120) x = self.input_projection(src) + self.pos_encoder x = self.transformer_encoder(x) # 【預測邏輯】:取最後一幀的特徵來預測未來 out = self.decoder(x[:, -1, :]) return out # 返回 (Batch, 120) ``` ### 2. 預測模型訓練代碼 ```python def train_predictor(model, dataloader, epochs=50): optimizer = torch.optim.Adam(model.parameters(), lr=1e-4) criterion = nn.MSELoss() # 預測任務通常使用均方誤差 model.train() for epoch in range(epochs): for batch_x, batch_y in dataloader: # batch_x: (Batch, 60, 120) # batch_y: (Batch, 120) -> 真實的第 61 幀 optimizer.zero_grad() output = model(batch_x) loss = criterion(output, batch_y) loss.backward() optimizer.step() print(f"Epoch {epoch+1}, Loss: {loss.item():.6f}") ``` --- ## 🎨 第二部分:隨機動作生成模型 (Motion VAE) **目標**:學習動作的「隱藏空間」,並從中隨機抽樣產生全新的動畫變體。 ### 1. 模型架構 (含 Encoder 與 Decoder) ```python class MotionVAE(nn.Module): def __init__(self, input_dim=120, model_dim=256, latent_dim=64, seq_len=60): super().__init__() self.latent_dim = latent_dim self.seq_len = seq_len self.pos_encoder = nn.Parameter(torch.zeros(1, seq_len, model_dim)) # Encoder 支柱 self.enc_embed = nn.Linear(input_dim, model_dim) self.encoder = nn.TransformerEncoder( nn.TransformerEncoderLayer(d_model=model_dim, nhead=8, batch_first=True), num_layers=3) self.fc_mu = nn.Linear(model_dim, latent_dim) self.fc_logvar = nn.Linear(model_dim, latent_dim) # Decoder 支柱 self.latent_to_model = nn.Linear(latent_dim, model_dim) self.dec_transformer = nn.TransformerEncoder( nn.TransformerEncoderLayer(d_model=model_dim, nhead=8, batch_first=True), num_layers=3) self.final_out = nn.Linear(model_dim, input_dim) def reparameterize(self, mu, logvar): std = torch.exp(0.5 * logvar) eps = torch.randn_like(std) return mu + eps * std # 此處梯度會回傳至 mu 與 logvar def forward(self, x): # 壓縮過程 x_enc = self.encoder(self.enc_embed(x) + self.pos_encoder) z_feat = x_enc[:, -1, :] # 取序列精華 mu, logvar = self.fc_mu(z_feat), self.fc_logvar(z_feat) # 抽樣與還原 z = self.reparameterize(mu, logvar) recon_x = self.decode(z) return recon_x, mu, logvar def decode(self, z): """隨機抽樣後調用此函數""" z_emb = self.latent_to_model(z).unsqueeze(1).expand(-1, self.seq_len, -1) z_emb = z_emb + self.pos_encoder return self.final_out(self.dec_transformer(z_emb)) ``` ### 2. VAE 訓練代碼 (含雙重 Loss) ```python def train_vae(model, dataloader, epochs=100): optimizer = torch.optim.Adam(model.parameters(), lr=1e-4) for epoch in range(epochs): for data in dataloader: # data: (Batch, 60, 120) optimizer.zero_grad() recon_x, mu, logvar = model(data) # 1. 重建誤差:確保動作正確 recon_loss = F.mse_loss(recon_x, data, reduction='sum') # 2. KL 散度:確保隱藏空間整齊(梯度會校正 mu 和 logvar) kl_loss = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp()) loss = recon_loss + kl_loss loss.backward() optimizer.step() print(f"Epoch {epoch+1}, Loss: {loss.item():.4f}") ``` --- ## 🛠️ 第三部分:Houdini 與推理應用 (Inference) ### 1. 預測未來模式 * **用法**:將當前 60 幀餵入 Predictor,得到第 61 幀。 * **特性**:適合做物理連動或即時反應。 ### 2. 隨機生成模式 (VAE Decode) * **用法**: ```python z = torch.randn(1, 64) # 從常態分佈抽樣(數值多在 -2 到 2) new_motion = model.decode(z) ``` * **特性**:每次點擊按鈕,都會產生一段全新的類似動作。 * **Houdini 整合**:利用 **Slider** 控制 `latent_dim` 中的數值,你可以像調色盤一樣「滑動」出不同的動作風格。 --- ## 💡 總結檢查清單 (Development Checklist) 1. **維度一致性**:`latent_dim` 是隱藏空間的維度,數值範圍在訓練後應趨向 。 2. **位置編碼**:在 Predictor 的 Encoder 以及 VAE 的 Decoder 中都是必須的。 3. **梯度傳導**:均值與對數方差透過 `reparameterize` 參與梯度更新,從而定義了有意義的隱藏空間。