Implementation:Kornia Kornia Mutual Information Loss
| Knowledge Sources | |
|---|---|
| Domains | Vision, Loss_Functions |
| Last Updated | 2026-02-09 15:00 GMT |
Overview
Mutual Information Loss computes differentiable mutual information and normalized mutual information between signals using kernel density estimation, suitable for image registration and similarity measurement tasks.
Description
This module provides entropy-based loss functions that estimate probability distributions via kernel density estimation (KDE). It computes joint histograms between signals and derives entropy measures including mutual information (MI) and normalized mutual information (NMI).
The mutual information is computed as:
The normalized mutual information is:
Both are returned negated so they can serve as loss functions to be minimized.
The module provides three kernel functions for KDE:
- xu: 2nd-order polynomial kernel (Xu et al., 2008)
- rectangular: Uniform rectangular kernel
- truncated_gaussian: Truncated Gaussian kernel
Variants are provided for flat (1D), 2D image, and 3D volume data, as both functional APIs and nn.Module classes.
Usage
Import this loss when performing image registration tasks where you need to maximize the statistical dependence between two images. Mutual information is particularly effective for multi-modal image registration (e.g., aligning CT and MRI scans) since it does not assume a linear relationship between image intensities.
Code Reference
Source Location
- Repository: Kornia
- File: kornia/losses/mutual_information.py
- Lines: 1-674
Signature
# Base class
class EntropyBasedLossBase(torch.nn.Module):
def __init__(
self,
reference_signal: torch.Tensor,
kernel_function: MIKernel = MIKernel.xu,
num_bins: int = 64,
window_radius: float = 1.0,
) -> None: ...
def entropies(self, other_signal: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]: ...
# MI Loss modules
class MILossFromRef(EntropyBasedLossBase):
def forward(self, other_signal: torch.Tensor) -> torch.Tensor: ...
class NMILossFromRef(EntropyBasedLossBase):
def forward(self, other_signal: torch.Tensor) -> torch.Tensor: ...
class MILossFromRef2D(MILossFromRef):
def __init__(self, reference_signal: torch.Tensor, kernel_function: MIKernel = MIKernel.xu,
num_bins: int = 64, window_radius: float = 1) -> None: ...
def forward(self, other_signal: torch.Tensor) -> torch.Tensor: ...
class MILossFromRef3D(MILossFromRef):
def __init__(self, reference_signal: torch.Tensor, kernel_function: MIKernel = MIKernel.xu,
num_bins: int = 64, window_radius: float = 1) -> None: ...
def forward(self, other_signal: torch.Tensor) -> torch.Tensor: ...
class NMILossFromRef2D(NMILossFromRef):
def __init__(self, reference_signal: torch.Tensor, kernel_function: MIKernel = MIKernel.xu,
num_bins: int = 64, window_radius: float = 1) -> None: ...
def forward(self, other_signal: torch.Tensor) -> torch.Tensor: ...
class NMILossFromRef3D(NMILossFromRef):
def __init__(self, reference_signal: torch.Tensor, kernel_function: MIKernel = MIKernel.xu,
num_bins: int = 64, window_radius: float = 1) -> None: ...
def forward(self, other_signal: torch.Tensor) -> torch.Tensor: ...
# Functional APIs
def mutual_information_loss(input: torch.Tensor, target: torch.Tensor, ...) -> torch.Tensor: ...
def mutual_information_loss_2d(input: torch.Tensor, target: torch.Tensor, ...) -> torch.Tensor: ...
def mutual_information_loss_3d(input: torch.Tensor, target: torch.Tensor, ...) -> torch.Tensor: ...
def normalized_mutual_information_loss(input: torch.Tensor, target: torch.Tensor, ...) -> torch.Tensor: ...
def normalized_mutual_information_loss_2d(input: torch.Tensor, target: torch.Tensor, ...) -> torch.Tensor: ...
def normalized_mutual_information_loss_3d(input: torch.Tensor, target: torch.Tensor, ...) -> torch.Tensor: ...
Import
from kornia.losses import MILossFromRef, MILossFromRef2D, MILossFromRef3D
from kornia.losses import NMILossFromRef, NMILossFromRef2D, NMILossFromRef3D
from kornia.losses import mutual_information_loss, normalized_mutual_information_loss
I/O Contract
Inputs (Module classes)
| Name | Type | Required | Description |
|---|---|---|---|
| reference_signal | torch.Tensor | Yes | Reference signal to compare against; shape (B, N) for flat, (B, H, W) for 2D, (B, D, H, W) for 3D |
| kernel_function | MIKernel | No | Kernel for KDE: MIKernel.xu (default), MIKernel.rectangular, or MIKernel.truncated_gaussian |
| num_bins | int | No | Number of signal value bins in KDE (default: 64) |
| window_radius | float | No | Radius of the kernel support interval (default: 1.0) |
| other_signal | torch.Tensor | Yes | Signal to compare with reference; must have same shape as reference_signal |
Inputs (Functional APIs)
| Name | Type | Required | Description |
|---|---|---|---|
| input | torch.Tensor | Yes | Input signal tensor |
| target | torch.Tensor | Yes | Target signal tensor, same shape as input |
| kernel_function | MIKernel | No | Kernel function for KDE (default: MIKernel.xu) |
| num_bins | int | No | Number of bins for KDE (default: 64) |
| window_radius | float | No | Smoothing window radius (default: 1.0) |
Outputs
| Name | Type | Description |
|---|---|---|
| loss | torch.Tensor | Negated mutual information (or NMI) scalar or batch of scalars with shape B (batch dimensions) |
Usage Examples
import torch
from kornia.losses import MILossFromRef2D, mutual_information_loss
# Using the module API for 2D images
reference = torch.rand(2, 64, 64)
criterion = MILossFromRef2D(reference_signal=reference, num_bins=64)
other = torch.rand(2, 64, 64)
loss = criterion(other)
# Using the functional API for flat signals
input_signal = torch.rand(4, 1000)
target_signal = torch.rand(4, 1000)
loss = mutual_information_loss(input_signal, target_signal, num_bins=64)