lybxin's picture
Upload folder using huggingface_hub
66b7c56 verified
"""
Copyright (c) Meta Platforms, Inc. and affiliates.
All rights reserved.
This source code is licensed under the license found in the
LICENSE file in the root directory of this source tree.
"""
import argparse
import numpy as np
from scipy import linalg
def calculate_diversity(activation: np.ndarray, diversity_times: int = 10_000) -> float:
assert len(activation.shape) == 2
assert activation.shape[0] > diversity_times
num_samples = activation.shape[0]
first_indices = np.random.choice(num_samples, diversity_times, replace=False)
second_indices = np.random.choice(num_samples, diversity_times, replace=False)
dist = linalg.norm(activation[first_indices] - activation[second_indices], axis=1)
return dist
def calculate_activation_statistics(
activations: np.ndarray,
) -> (np.ndarray, np.ndarray):
mu = np.mean(activations, axis=0)
cov = np.cov(activations, rowvar=False)
return mu, cov
def calculate_frechet_distance(
mu1: np.ndarray,
sigma1: np.ndarray,
mu2: np.ndarray,
sigma2: np.ndarray,
eps: float = 1e-6,
) -> float:
mu1 = np.atleast_1d(mu1)
mu2 = np.atleast_1d(mu2)
sigma1 = np.atleast_2d(sigma1)
sigma2 = np.atleast_2d(sigma2)
assert (
mu1.shape == mu2.shape
), "Training and test mean vectors have different lengths"
assert (
sigma1.shape == sigma2.shape
), "Training and test covariances have different dimensions"
diff = mu1 - mu2
# Product might be almost singular
covmean, _ = linalg.sqrtm(sigma1.dot(sigma2), disp=False)
if not np.isfinite(covmean).all():
msg = (
"fid calculation produces singular product; "
"adding %s to diagonal of cov estimates"
) % eps
print(msg)
offset = np.eye(sigma1.shape[0]) * eps
covmean = linalg.sqrtm((sigma1 + offset).dot(sigma2 + offset))
# Numerical error might give slight imaginary component
if np.iscomplexobj(covmean):
if not np.allclose(np.diagonal(covmean).imag, 0, atol=1e-3):
m = np.max(np.abs(covmean.imag))
raise ValueError("Imaginary component {}".format(m))
covmean = covmean.real
tr_covmean = np.trace(covmean)
return diff.dot(diff) + np.trace(sigma1) + np.trace(sigma2) - 2 * tr_covmean
def main(args):
num_samples = 5
results = np.load(args.results, allow_pickle=True).item()
pred_reshaped = results["motion"].squeeze().reshape((num_samples, -1, 104, 600))
gt_reshaped = results["gt"].squeeze().reshape((num_samples, -1, 104, 600))
# calulate variance across the different samples generated
cross_sample_var = np.var(pred_reshaped.reshape((num_samples, -1)), axis=0)
print("cross var", cross_sample_var.mean())
pred_pose_last = pred_reshaped.transpose((0, 1, 3, 2)).reshape(-1, 104)
gt_pose_last = gt_reshaped.transpose((0, 1, 3, 2)).reshape(-1, 104)
# calculate the static and kinematic diversity
var_g = calculate_diversity(pred_pose_last)
print("var_g", var_g.mean())
var_k = np.var(pred_reshaped, axis=-1)
print("var_k", var_k.mean())
# calculate the static and kinematic fid
pred_mu_g, pred_cov_g = calculate_activation_statistics(pred_pose_last)
gt_mu_g, gt_cov_g = calculate_activation_statistics(gt_pose_last)
fid_g = calculate_frechet_distance(gt_mu_g, gt_cov_g, pred_mu_g, pred_cov_g)
print("fid_g", fid_g)
# reshape for kinematic fid
pred_motion = pred_reshaped[..., 1:] - pred_reshaped[..., :-1]
gt_motion = gt_reshaped[..., 1:] - gt_reshaped[..., :-1]
pred_motion_last = pred_motion.transpose((0, 1, 3, 2)).reshape(-1, 104)
gt_motion_last = gt_motion.transpose((0, 1, 3, 2)).reshape(-1, 104)
pred_mu_k, pred_cov_k = calculate_activation_statistics(pred_motion_last)
gt_mu_k, gt_cov_k = calculate_activation_statistics(gt_motion_last)
fid_k = calculate_frechet_distance(gt_mu_k, gt_cov_k, pred_mu_k, pred_cov_k)
print("fid_k", fid_k)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--results", type=str, required=True)
args = parser.parse_args()
main(args)