Gromov-Wasserstein Distance
An overview of the Gromov-Wasserstein distance and its applications in my ML project
I’ve been working on a machine learning project involving the comparison of motion patterns extracted from dance videos. Our initial pipeline relied on DTW and several time-based distance metrics, but the results were not as robust as we expected. There was a suggestion to explore the Gromov–Wasserstein (GW) distance, and it turned out to be a very interesting idea! Let's start with..
Wasserstein Distance
Intuitively, it quantifies the minimum "cost" of transforming one probability distribution into another, where the cost is defined in terms of the distance between points in the space. Let's look at the example below.

from this lecture.
The cost at i,j is defined as the amount of mass moved () times the distance between the points (). The total cost is the sum of all individual costs.
For general probability measures with continuous support, the Wasserstein distance is defined as:


from this lecture.
Gromov-Wasserstein Distance
What if two distributions we want to compare do not live in the same space? For example, we have two graphs with different numbers of nodes, and we want to compare their structures. This is where the Gromov-Wasserstein distance comes into play.
Now we can't use distance between points directly, since they are in different spaces. Instead, we look at the internal structure.

Shape is... the relational structure formed by the distances between points. Even if two objects exist in entirely different coordinate systems, they can still have identical internal structures and thus represent the same shape.
Look at the cost function, we are minimizing the difference in pairwise distances within each space, weighted by the transport plan .
GW Distance in Python
All good! But how to compute coupling π(i,j)? In principle, computing the exact GW coupling requires solving a non convex quadratic optimization problem, which is computationally challenging. In practice, we instead use an entropic regularized version
In Python, we can use the POT (Python Optimal Transport) library to compute the GW distance. Here's a simple example:
import numpy as np
import scipy as sp
import ot
def _flatten_poses(poses):
n_frames = len(poses)
n_landmarks = poses[0].shape[0]
# Mediapipe pose landmarks are 3D so each frame is flattened into xyz coordinates.
return poses[:, :, :3].reshape(n_frames, n_landmarks * 3)
def compute_distance_matrices(poses1, poses2):
X1 = _flatten_poses(poses1)
X2 = _flatten_poses(poses2)
D1 = sp.spatial.distance.cdist(X1, X1)
D2 = sp.spatial.distance.cdist(X2, X2)
D1 /= D1.max()
D2 /= D2.max()
return D1, D2
def compute_gromov_wasserstein(poses1, poses2, verbose=False, log=False):
X1 = _flatten_poses(poses1)
X2 = _flatten_poses(poses2)
D1 = sp.spatial.distance.cdist(X1, X1)
D2 = sp.spatial.distance.cdist(X2, X2)
D1 /= D1.max()
D2 /= D2.max()
p = ot.unif(len(X1))
q = ot.unif(len(X2))
gw_distance, log_dict = ot.gromov.gromov_wasserstein2(
D1, D2, p, q,
loss_fun='square_loss',
verbose=verbose,
log=True
)
transport_plan = ot.gromov.gromov_wasserstein(
D1, D2, p, q,
loss_fun='square_loss',
verbose=verbose
)
if log:
return gw_distance, transport_plan, log_dict
return gw_distance, transport_plan
def compute_gw_from_distance_matrices(D1, D2, p=None, q=None, loss_fun='square_loss', verbose=False, log=False):
if p is None:
p = ot.unif(D1.shape[0])
if q is None:
q = ot.unif(D2.shape[0])
gw_distance, log_dict = ot.gromov.gromov_wasserstein2(
D1, D2, p, q,
loss_fun=loss_fun,
verbose=verbose,
log=True
)
transport_plan = ot.gromov.gromov_wasserstein(
D1, D2, p, q,
loss_fun=loss_fun,
verbose=verbose
)
if log:
return gw_distance, transport_plan, log_dict
return gw_distance, transport_plan
Note
More general case with GW distance can be found in the official doc.
I loaded a pair of dance videos from the same dance (Video 1, Video 2), another video from a completely different dance (Video 3), and extracted pose keypoints using MediaPipe. Each pose is represented as a set of 3D coordinates for various landmarks on the body.

Interesting! Distance matrices of Video 1 and Video 2 look quite similar, while that of Video 3 shows more variation. What do you think? The computed GW distances are:
Video 1 and Video 2: 0.008441
Video 1 and Video 3: 0.008753
In absolute terms the values are close, but if you experiment with other video pairs, you'll notice a clear pattern: GW distances between similar dance styles consistently remain smaller than those between different styles.

Summary
- GW distance provides a flexible way to compare sequences with different lengths or coordinate systems.
- For motion analysis in particular, it captures structural similarity beyond simple time alignment and serves as a strong complement to DTW based methods.