機械学習の精度向上に貢献!PyTorch `log_prob()` 関数で低ランク多変量正規分布を自在に扱う


この関数は、以下の引数を取ります。

  • cov_diag: 低ランク共分散行列の対角線要素ベクトル。形状は (dim,) である必要があります。
  • cov_factor: 低ランク共分散行列の因子行列。形状は (dim, rank) である必要があります。
  • value: 入力ベクトル。形状は (batch_shape, dim) である必要があります。ここで、batch_shape はバッチ次元を表し、dim は分布の次元を表します。

この関数は、以下の値を返します。

  • log_prob: 確率密度関数の対数値。形状は (batch_shape,) です。

計算の詳細

log_prob() 関数の内部では、以下の手順で計算が行われます。

  1. 事前計算
    • capacitance_tril: W @ W.T + D のCholesky分解を計算します。
    • lowrank_logdet: W @ W.T + D の行列式を計算します。
  2. Mahalanobis距離の計算
    • mahalanobis_term1: x.T @ Dinv @ x を計算します。
    • mahalanobis_term2: x.T @ inv(capacitance_tril) @ x を計算します。
    • mahalanobis: mahalanobis_term1 - mahalanobis_term2 を計算します。
  3. 対数確率密度の計算
    • log_prob: -0.5 * mahalanobis - 0.5 * dim * math.log(2 * math.pi) - lowrank_logdet を計算します。
import torch
from torch.distributions import LowRankMultivariateNormal

# パラメータの設定
cov_factor = torch.randn(5, 2)
cov_diag = torch.rand(5)
mean = torch.zeros(5)
value = torch.randn(10, 5)

# 低ランク多変量正規分布の生成
distribution = LowRankMultivariateNormal(mean, cov_factor, cov_diag)

# 対数確率密度の計算
log_prob = distribution.log_prob(value)

# 結果の表示
print(log_prob)

このコード例では、5次元低ランク多変量正規分布を生成し、value がその分布に従う確率の対数値を計算しています。



低ランク多変量正規分布からのサンプリング

import torch
from torch.distributions import LowRankMultivariateNormal

# パラメータの設定
cov_factor = torch.randn(5, 2)
cov_diag = torch.rand(5)
mean = torch.zeros(5)
num_samples = 10

# 低ランク多変量正規分布の生成
distribution = LowRankMultivariateNormal(mean, cov_factor, cov_diag)

# サンプリング
samples = distribution.rsample(num_samples)

# 結果の表示
print(samples)

このコード例では、5次元低ランク多変量正規分布を生成し、その分布から10個のサンプリングを行います。

以下のコードは、混合低ランク多変量正規分布をデータにフィッティングする例です。

import torch
from torch.distributions import LowRankMultivariateNormal
from torch.distributions.mixture import MixtureMultivariateNormal

# データの生成
data = torch.randn(100, 5)

# 混合低ランク多変量正規分布のモデル
components = [
    LowRankMultivariateNormal(mean1, cov_factor1, cov_diag1),
    LowRankMultivariateNormal(mean2, cov_factor2, cov_diag2),
]
mixing_probs = torch.tensor([0.7, 0.3])
model = MixtureMultivariateNormal(components, mixing_probs)

# モデルのフィッティング
optimizer = torch.optim.Adam(model.parameters())
for i in range(100):
    optimizer.zero_grad()
    loss = -model.log_prob(data).mean()
    loss.backward()
    optimizer.step()

# フィッティング結果の表示
print(model.components)
print(model.mixing_probs)

このコード例では、100個の5次元データポイントを生成し、2つの低ランク多変量正規分布で構成される混合低ランク多変量正規分布をフィッティングします。

これらのコード例は、torch.distributions.lowrank_multivariate_normal.LowRankMultivariateNormal.log_prob() 関数の様々な用途を示しています。

  • torch.distributions モジュールには、様々な確率分布が実装されていますので、用途に合わせて利用することができます。
  • 低ランク多変量正規分布は、高次元データのモデリングに有効な手法です。
  • 上記のコード例はあくまでも例であり、具体的な用途に合わせて変更する必要があります。


そこで、以下の代替方法を検討することができます。

ランダムサンプリングによる近似

torch.distributions.lowrank_multivariate_normal.LowRankMultivariateNormal.log_prob() の代替方法として、ランダムサンプリングによる近似方法があります。この方法は、以下の手順で行います。

  1. 低ランク多変量正規分布からランダムサンプリングを複数回行う。
  2. 各サンプリングに対して、value との距離を計算する。
  3. 距離が近いサンプリングの個数をカウントする。
  4. カウントされた個数を、サンプリング回数で割る。
  5. 結果を log(確率) として返す。

この方法は、計算コストが低く、大規模なデータセットや高次元の分布にも適用することができます。

import torch
import numpy as np

def log_prob_approx(value, mean, cov_factor, cov_diag, num_samples):
    samples = torch.randn(num_samples, value.shape[1])
    samples = mean + cov_factor @ samples @ cov_factor.T + cov_diag.unsqueeze(0)
    distances = torch.norm(samples - value, dim=1)
    nearest_count = (distances < distances.min(dim=1)[0]).sum(dim=0)
    log_prob = torch.log(nearest_count.float() / num_samples)
    return log_prob

# パラメータの設定
cov_factor = torch.randn(5, 2)
cov_diag = torch.rand(5)
mean = torch.zeros(5)
value = torch.randn(10, 5)
num_samples = 1000

# 対数確率密度の近似計算
log_prob_approx = log_prob_approx(value, mean, cov_factor, cov_diag, num_samples)

# 結果の表示
print(log_prob_approx)

このコード例では、5次元低ランク多変量正規分布を生成し、value がその分布に従う確率をランダムサンプリングによって近似しています。

  1. 低ランク多変量正規分布の確率密度関数 p(x) を定義する。
  2. valuex の積分を計算する。
  3. 積分値を log(確率) として返す。

この方法は、理論的には正確な結果を得ることができますが、計算コストが高く、大規模なデータセットや高次元の分布には適用できない場合があります。

import torch
import scipy.integrate

def log_prob_integrate(value, mean, cov_factor, cov_diag):
    def pdf(x):
        return torch.distributions.MultivariateNormal(mean, cov_factor @ cov_factor.T + cov_diag).log_prob(x)

    log_prob = scipy.integrate.quad(pdf, -np.inf, np.inf)[0]
    return log_prob

# パラメータの設定
cov_factor = torch.randn(5, 2)
cov_diag = torch.rand(5)
mean = torch.zeros(5)
value = torch.randn(10, 5)

# 対数確率密度の積分計算
log_prob_integrate = log_prob_integrate(value, mean, cov_factor, cov_diag)

# 結果の表示
print(log_prob_integrate)

このコード例では、5次元低ランク多変量正規分布を生成し、value がその分布に従う確率を積分によって計算しています。