Pytorch Torch Slogdet
## PyTorch `torch.slogdet`
The `torch.slogdet` function in PyTorch computes the sign and natural logarithm of the absolute value of the determinant of a square matrix (or a batch of square matrices).
Compared to directly calculating the determinant using `torch.det`, `torch.slogdet` is significantly more numerically stable. It prevents underflow or overflow issues when dealing with matrices that have extremely large or extremely small determinants.
---
### Mathematical Background
For a square matrix $A$, the determinant $\det(A)$ can be represented in terms of its sign and the natural logarithm of its absolute value:
$$\det(A) = \text{sign} \times e^{\text{logdet}}$$
Where:
* $\text{sign} \in \{-1, 0, 1\}$ (for real matrices)
* $\text{logdet} = \ln(|\det(A)|)$
If the determinant is zero, $\text{sign}$ will be $0$ and $\text{logdet}$ will be $-\infty$.
---
### Function Definition
```python
torch.slogdet(input, *, out=None) -> (Tensor, Tensor)
```
#### Parameters:
* **`input`** *(Tensor)*: A tensor of shape `(*, N, N)` where `*` represents zero or more batch dimensions, and the inner-most dimensions form square matrices of size `N x N`.
* **`out`** *(tuple, optional)*: A tuple of two tensors to write the output to.
#### Returns:
* **`tuple` (sign, logdet)**:
* **`sign`** *(Tensor)*: The sign of the determinant.
* **`logdet`** *(Tensor)*: The natural logarithm of the absolute value of the determinant.
---
### Code Examples
#### Example 1: Basic Usage with a Single Matrix
This example demonstrates how to compute the sign and log-determinant of a $3 \times 3$ upper triangular matrix.
```python
import torch
# Create a 3x3 upper triangular matrix
A = torch.tensor([[1.0, 2.0, 3.0],
[0.0, 4.0, 5.0],
[0.0, 0.0, 6.0]])
# Compute the sign and log-determinant
sign, logdet = torch.slogdet(A)
print("Matrix A:")
print(A)
print("\nDeterminant Sign:", sign)
print("Log-Determinant (ln|det|):", logdet)
# Reconstruct the original determinant: sign * exp(logdet)
det = sign * torch.exp(logdet)
print("Reconstructed Determinant:", det)
```
**Output:**
```text
Matrix A:
tensor([[1., 2., 3.],
[0., 4., 5.],
[0., 0., 6.]])
Determinant Sign: tensor(1.)
Log-Determinant (ln|det|): tensor(3.5835)
Reconstructed Determinant: tensor(24.0000)
```
---
#### Example 2: Batch Processing
`torch.slogdet` natively supports batch operations. If you pass a 3D tensor of shape `(B, N, N)`, it returns a batch of signs and log-determinants of shape `(B,)`.
```python
import torch
# Create a batch of two 2x2 matrices
# Batch shape: (2, 2, 2)
B = torch.tensor([[[1.0, 2.0],
[3.0, 4.0]],
[[1.0, 3.0],
[3.0, 1.0]]])
signs, logdets = torch.slogdet(B)
for i in range(B.size(0)):
print(f"--- Matrix {i} ---")
print(B)
print(f"Sign: {signs.item()}")
print(f"Log-det: {logdets.item():.4f}")
print(f"Reconstructed Det: {(signs * torch.exp(logdets)).item():.4f}\n")
```
**Output:**
```text
--- Matrix 0 ---
tensor([[1., 2.],
[3., 4.]])
Sign: -1.0
Log-det: 0.6931
Reconstructed Det: -2.0000
--- Matrix 1 ---
tensor([[1., 3.],
[3., 1.]])
Sign: -1.0
Log-det: 2.0794
Reconstructed Det: -8.0000
```
---
### Important Considerations
1. **Numerical Stability**: When working with high-dimensional matrices, the determinant can easily overflow to $\infty$ or underflow to $0$. Using `torch.slogdet` keeps calculations in the logarithmic domain, which prevents these numerical issues. This is particularly crucial when calculating the loss of Normalizing Flows or Multivariate Gaussian distributions.
2. **Singular Matrices**: If the input matrix is singular (i.e., its determinant is $0$), `sign` will be $0$ and `logdet` will be $-\infty$.
3. **Backpropagation**: PyTorch supports autograd through `torch.slogdet`. However, backward passes can become numerically unstable if the input matrix is close to singular (non-invertible).
YouTip