---
title: Perceptual Path Length (PPL)
description: Computes the perceptual path length (PPL) of a generator model.
canonical: 'https://lightning.ai/docs/torchmetrics/stable/image/perceptual_path_length'
---
# Perceptual Path Length (PPL) {#perceptual-path-length-ppl}

## Module Interface {#module-interface}

### `class torchmetrics.image.perceptual_path_length.PerceptualPathLength(num_samples=10000, conditional=False, batch_size=128, interpolation_method='lerp', epsilon=0.0001, resize=64, lower_discard=0.01, upper_discard=0.99, sim_net='vgg', **kwargs)` {#torchmetrics.image.perceptual_path_length.PerceptualPathLength}

[\[source\]](https://github.com/Lightning-AI/torchmetrics/blob/v1.9.0/src/torchmetrics/image/perceptual_path_length.py#L32-L182)

Computes the perceptual path length ([PPL](https://arxiv.org/abs/1812.04948)) of a generator model.

The perceptual path length can be used to measure the consistency of interpolation in latent-space models. It is defined as

```math
PPL = \mathbb{E}\left[\frac{1}{\epsilon^2} D(G(I(z_1, z_2, t)), G(I(z_1, z_2, t+\epsilon)))\right]
```

where $`G`$ is the generator, $`I`$ is the interpolation function, $`D`$ is a similarity metric, $`z_1`$ and $`z_2`$ are two sets of latent points, and $`t`$ is a parameter between 0 and 1. The metric thus works by interpolating between two sets of latent points, and measuring the similarity between the generated images. The expectation is approximated by sampling $`z_1`$ and $`z_2`$ from the generator, and averaging the calculated distanced. The similarity metric $`D`$ is by default the [LPIPS](https://arxiv.org/abs/1801.03924) metric, but can be changed by setting the sim\_net argument.

The provided generator model must have a sample method with signature sample(num\_samples: int) -> Tensor where the returned tensor has shape (num\_samples, z\_size). If the generator is conditional, it must also have a num\_classes attribute. The forward method of the generator must have signature forward(z: Tensor) -> Tensor if conditional=False, and forward(z: Tensor, labels: Tensor) -> Tensor if conditional=True. The returned tensor should have shape (num\_samples, C, H, W) and be scaled to the range \[0, 255\].

Hint

Using this metric with the default feature extractor requires that `torchvision` is installed. Either install as `pip install torchmetrics[image]` or `pip install torchvision`

As input to `forward` and `update` the metric accepts the following input

*   `generator` ([`Module`](https://docs.pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module "(in PyTorch v2.15)")): Generator model, with specific requirements. See above.
    

As output of forward and compute the metric returns the following output

*   `ppl_mean` ([`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)")): float scalar tensor with mean PPL value over distances
    
*   `ppl_std` ([`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)")): float scalar tensor with std PPL value over distances
    
*   `ppl_raw` ([`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)")): float scalar tensor with raw PPL distances
    

Parameters:

*   **num\_samples** ([`int`](https://docs.python.org/3/builtins/functions.html#int "(in Python v3.15)")) – Number of samples to use for the PPL computation.
    
*   **conditional** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool "(in Python v3.15)")) – Whether the generator is conditional or not (i.e. whether it takes labels as input).
    
*   **batch\_size** ([`int`](https://docs.python.org/3/builtins/functions.html#int "(in Python v3.15)")) – Batch size to use for the PPL computation.
    
*   **interpolation\_method** ([`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal "(in Python v3.15)")\[`'lerp'`, `'slerp_any'`, `'slerp_unit'`\]) – Interpolation method to use. Choose from ‘lerp’, ‘slerp\_any’, ‘slerp\_unit’.
    
*   **epsilon** ([`float`](https://docs.python.org/3/builtins/functions.html#float "(in Python v3.15)")) – Spacing between the points on the path between latent points.
    
*   **resize** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional "(in Python v3.15)")\[[`int`](https://docs.python.org/3/builtins/functions.html#int "(in Python v3.15)")\]) – Resize images to this size before computing the similarity between generated images.
    
*   **lower\_discard** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional "(in Python v3.15)")\[[`float`](https://docs.python.org/3/builtins/functions.html#float "(in Python v3.15)")\]) – Lower quantile to discard from the distances, before computing the mean and standard deviation.
    
*   **upper\_discard** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional "(in Python v3.15)")\[[`float`](https://docs.python.org/3/builtins/functions.html#float "(in Python v3.15)")\]) – Upper quantile to discard from the distances, before computing the mean and standard deviation.
    
*   **sim\_net** (`Union`\[[`Module`](https://docs.pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module "(in PyTorch v2.15)"), [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal "(in Python v3.15)")\[`'alex'`, `'vgg'`, `'squeeze'`\]\]) – Similarity network to use. Can be a nn.Module or one of ‘alex’, ‘vgg’, ‘squeeze’, where the three latter options correspond to the pretrained networks from the [LPIPS](https://arxiv.org/abs/1801.03924) paper.
    
*   **kwargs** ([`Any`](https://docs.python.org/3/library/typing.html#typing.Any "(in Python v3.15)")) – Additional keyword arguments, see [Advanced metric settings](/docs/torchmetrics/1.9.0/user-guide/overview.md#metric-kwargs) for more info.
    

Raises:

*   [**ModuleNotFoundError**](https://docs.python.org/3/builtins/exceptions.html#ModuleNotFoundError "(in Python v3.15)") – If `torch-fidelity` is not installed.
    
*   [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError "(in Python v3.15)") – If `num_samples` is not a positive integer.
    
*   [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError "(in Python v3.15)") – If conditional is not a boolean.
    
*   [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError "(in Python v3.15)") – If `batch_size` is not a positive integer.
    
*   [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError "(in Python v3.15)") – If `interpolation_method` is not one of ‘lerp’, ‘slerp\_any’, ‘slerp\_unit’.
    
*   [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError "(in Python v3.15)") – If `epsilon` is not a positive float.
    
*   [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError "(in Python v3.15)") – If `resize` is not a positive integer.
    
*   [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError "(in Python v3.15)") – If `lower_discard` is not a float between 0 and 1 or None.
    
*   [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError "(in Python v3.15)") – If `upper_discard` is not a float between 0 and 1 or None.
    

Example::

```python
>>> import torch
>>> class DummyGenerator(torch.nn.Module):
...    def __init__(self, z_size) -> None:
...       super().__init__()
...       self.z_size = z_size
...       self.model = torch.nn.Sequential(torch.nn.Linear(z_size, 3*128*128), torch.nn.Sigmoid())
...    def forward(self, z):
...       return 255 * (self.model(z).reshape(-1, 3, 128, 128) + 1)
...    def sample(self, num_samples):
...      return torch.randn(num_samples, self.z_size)
>>> generator = DummyGenerator(2)
>>> ppl = PerceptualPathLength(num_samples=10)
>>> ppl(generator)
(tensor(...), tensor(...), tensor([...]))
```

### `class torchmetrics.image.perceptual_path_length.GeneratorType(*args, **kwargs)` {#torchmetrics.image.perceptual_path_length.GeneratorType}

[\[source\]](https://github.com/Lightning-AI/torchmetrics/blob/v1.9.0/src/torchmetrics/functional/image/perceptual_path_length.py#L27-L47)

Basic interface for a generator model.

Users can inherit from this class and implement their own generator model. The requirements are that the `sample` method is implemented and that the `num_classes` attribute is present when `conditional=True` metric.

#### `sample(num_samples)` {#torchmetrics.image.perceptual_path_length.GeneratorType.sample}

[\[source\]](https://github.com/Lightning-AI/torchmetrics/blob/v1.9.0/src/torchmetrics/functional/image/perceptual_path_length.py#L40-L47)

Sample from the generator.

Parameters:

**num\_samples** ([`int`](https://docs.python.org/3/builtins/functions.html#int "(in Python v3.15)")) – Number of samples to generate.

Return type:

[`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)")

#### `property num_classes: int` {#torchmetrics.image.perceptual_path_length.GeneratorType.num_classes}

[\[source\]](https://github.com/Lightning-AI/torchmetrics/blob/v1.9.0/src/torchmetrics/image/perceptual_path_length.py)

Return the number of classes for conditional generation.

## Functional Interface {#functional-interface}

### `torchmetrics.functional.image.perceptual_path_length.perceptual_path_length(generator, num_samples=10000, conditional=False, batch_size=64, interpolation_method='lerp', epsilon=0.0001, resize=64, lower_discard=0.01, upper_discard=0.99, sim_net='vgg', device='cpu')` {#torchmetrics.functional.image.perceptual_path_length.perceptual_path_length}

[\[source\]](https://github.com/Lightning-AI/torchmetrics/blob/v1.9.0/src/torchmetrics/functional/image/perceptual_path_length.py#L153-L283)

Computes the perceptual path length ([PPL](https://arxiv.org/abs/1812.04948)) of a generator model.

The perceptual path length can be used to measure the consistency of interpolation in latent-space models. It is defined as

```math
PPL = \mathbb{E}\left[\frac{1}{\epsilon^2} D(G(I(z_1, z_2, t)), G(I(z_1, z_2, t+\epsilon)))\right]
```

where $`G`$ is the generator, $`I`$ is the interpolation function, $`D`$ is a similarity metric, $`z_1`$ and $`z_2`$ are two sets of latent points, and $`t`$ is a parameter between 0 and 1. The metric thus works by interpolating between two sets of latent points, and measuring the similarity between the generated images. The expectation is approximated by sampling $`z_1`$ and $`z_2`$ from the generator, and averaging the calculated distanced. The similarity metric $`D`$ is by default the [LPIPS](https://arxiv.org/abs/1801.03924) metric, but can be changed by setting the sim\_net argument.

The provided generator model must have a sample method with signature sample(num\_samples: int) -> Tensor where the returned tensor has shape (num\_samples, z\_size). If the generator is conditional, it must also have a num\_classes attribute. The forward method of the generator must have signature forward(z: Tensor) -> Tensor if conditional=False, and forward(z: Tensor, labels: Tensor) -> Tensor if conditional=True. The returned tensor should have shape (num\_samples, C, H, W) and be scaled to the range \[0, 255\].

Parameters:

*   **generator** ([`GeneratorType`](#torchmetrics.image.perceptual_path_length.GeneratorType "torchmetrics.functional.image.perceptual_path_length.GeneratorType")) – Generator model, with specific requirements. See above.
    
*   **num\_samples** ([`int`](https://docs.python.org/3/builtins/functions.html#int "(in Python v3.15)")) – Number of samples to use for the PPL computation.
    
*   **conditional** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool "(in Python v3.15)")) – Whether the generator is conditional or not (i.e. whether it takes labels as input).
    
*   **batch\_size** ([`int`](https://docs.python.org/3/builtins/functions.html#int "(in Python v3.15)")) – Batch size to use for the PPL computation.
    
*   **interpolation\_method** ([`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal "(in Python v3.15)")\[`'lerp'`, `'slerp_any'`, `'slerp_unit'`\]) – Interpolation method to use. Choose from ‘lerp’, ‘slerp\_any’, ‘slerp\_unit’.
    
*   **epsilon** ([`float`](https://docs.python.org/3/builtins/functions.html#float "(in Python v3.15)")) – Spacing between the points on the path between latent points.
    
*   **resize** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional "(in Python v3.15)")\[[`int`](https://docs.python.org/3/builtins/functions.html#int "(in Python v3.15)")\]) – Resize images to this size before computing the similarity between generated images.
    
*   **lower\_discard** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional "(in Python v3.15)")\[[`float`](https://docs.python.org/3/builtins/functions.html#float "(in Python v3.15)")\]) – Lower quantile to discard from the distances, before computing the mean and standard deviation.
    
*   **upper\_discard** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional "(in Python v3.15)")\[[`float`](https://docs.python.org/3/builtins/functions.html#float "(in Python v3.15)")\]) – Upper quantile to discard from the distances, before computing the mean and standard deviation.
    
*   **sim\_net** (`Union`\[[`Module`](https://docs.pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module "(in PyTorch v2.15)"), [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal "(in Python v3.15)")\[`'alex'`, `'vgg'`, `'squeeze'`\]\]) – Similarity network to use. Can be a nn.Module or one of ‘alex’, ‘vgg’, ‘squeeze’, where the three latter options correspond to the pretrained networks from the [LPIPS](https://arxiv.org/abs/1801.03924) paper.
    
*   **device** (`Union`\[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str "(in Python v3.15)"), [`device`](https://docs.pytorch.org/docs/stable/tensor_attributes.html#torch.device "(in PyTorch v2.15)")\]) – Device to use for the computation.
    

Return type:

[`tuple`](https://docs.python.org/3/builtins/stdtypes.html#tuple "(in Python v3.15)")\[[`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)"), [`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)"), [`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)")\]

Returns:

A tuple containing the mean, standard deviation and all distances.

Example::

```python
>>> import torch
>>> from torchmetrics.functional.image import perceptual_path_length
>>> class DummyGenerator(torch.nn.Module):
...    def __init__(self, z_size) -> None:
...       super().__init__()
...       self.z_size = z_size
...       self.model = torch.nn.Sequential(torch.nn.Linear(z_size, 3*128*128), torch.nn.Sigmoid())
...    def forward(self, z):
...       return 255 * (self.model(z).reshape(-1, 3, 128, 128) + 1)
...    def sample(self, num_samples):
...      return torch.randn(num_samples, self.z_size)
>>> generator = DummyGenerator(2)
>>> perceptual_path_length(generator, num_samples=10)  
(tensor(0.1945),
tensor(0.1222),
tensor([0.0990, 0.4173, 0.1628, 0.3573, 0.1875, 0.0335, 0.1095, 0.1887, 0.1953]))
```

---

**Navigation**

- Parent: [Image](/docs/torchmetrics/1.9.0/image.md)
