pinn / Utils.py
SeongvinJu's picture
Upload folder using huggingface_hub
5cb4913 verified
Raw
History Blame Contribute Delete
2.89 kB
import torch
import torch.nn.functional as F
from typing import Optional
# H36M17 skeleton edges
H36M17_EDGES = [
(0, 1), (1, 2), (2, 3), # left leg
(0, 4), (4, 5), (5, 6), # right leg
(0, 7), (7, 8), (8, 9), (9, 10), # pelvis to head
(8, 11), (11, 12), (12, 13), # right arm
(8, 14), (14, 15), (15, 16), # left arm
]
# Left-right pairs.
H36M17_LR_PAIRS = [
(1, 4), (2, 5), (3, 6),
(14, 11), (15, 12), (16, 13)
]
def return_edges():
return H36M17_EDGES
def return_lr_edges():
return H36M17_LR_PAIRS
def split_state(s_hat: torch.Tensor):
"""
s_hat: (B, T, J, 12) = concat(p, v, a, j), each 3D
returns
p: (B, T, J, 3)
v: (B, T, J, 3)
a: (B, T, J, 3)
j: (B, T, J, 3)
"""
p, v, a, j = torch.split(s_hat, 3, dim=-1)
return p, v, a, j
# Central difference.
def central_diff(x: torch.Tensor,
dt: float):
"""
Central difference along time axis.
x: (B, T, J, 3) -> dx/dt: (B, T, J, 3)
Endpoints use forward/backward difference.
"""
B, T, J, C = x.shape
if T < 2:
return torch.zeros_like(x)
dx = torch.zeros_like(x)
dx[:, 0] = (x[:, 1] - x[:, 0]) / dt
dx[:, -1] = (x[:, -1] - x[:, -2]) / dt
if T > 2:
dx[:, 1:-1] = (x[:, 2:] - x[:, :-2]) / (2.0 * dt)
return dx
def masked_mean(x: torch.Tensor,
mask: Optional[torch.Tensor] = None,
eps: float = 1e-8):
"""
Inputs:
x: (...,) any shape
Description:
mask: same broadcastable shape as x without last dims, or exact shape of x expects float/bool with 1 for valid
"""
if mask is None:
return x.mean()
m = mask
if m.dtype != x.dtype:
m = m.to(dtype=x.dtype)
# broadcast
while m.ndim < x.ndim:
m = m.unsqueeze(-1)
num = (x * m).sum()
den = m.sum().clamp_min(eps)
return num / den
def build_adj(J: int,
edges):
A = torch.zeros(J, J)
for i, j in edges:
A[i, j] = 1.0
A[j, i] = 1.0
A.fill_diagonal_(1.0)
return A # (J,J)
# Loss util
def variance_regularization(z: torch.Tensor, eps: float = 1e-4, target_std: float = 1.0):
"""
z shape:
(B,T,J,D) or (B,N,D) or (B,D)
Treat the last dimension D as the feature dimension.
Flatten all leading dimensions into samples before computing std.
"""
if z.ndim < 2:
raise ValueError(f"z.ndim must be >= 2, got {z.ndim}")
z = z.reshape(-1, z.shape[-1]) # (N_all, D)
std = torch.sqrt(z.var(dim=0, unbiased=False) + eps) # (D,)
loss_var = torch.mean(F.relu(target_std - std))
return loss_var