PCA Probabilistik

Lihat di TensorFlow.org Jalankan di Google Colab Lihat sumber di GitHub Unduh buku catatan

Probabilistik analisis komponen utama (PCA) adalah teknik pengurangan dimensi yang menganalisis data melalui ruang laten dimensi yang lebih rendah ( Tipping dan Uskup 1999 ). Ini sering digunakan ketika ada nilai yang hilang dalam data atau untuk penskalaan multidimensi.

Impor

import functools
import warnings

import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns

import tensorflow.compat.v2 as tf
import tensorflow_probability as tfp

from tensorflow_probability import bijectors as tfb
from tensorflow_probability import distributions as tfd

tf.enable_v2_behavior()

plt.style.use("ggplot")
warnings.filterwarnings('ignore')

Model

Pertimbangkan data set \(\mathbf{X} = \{\mathbf{x}_n\}\) dari \(N\) titik data, dimana setiap titik data adalah \(D\)berdimensi, $ \ mathbf {x} _n \ di \ mathbb {R} ^ D\(. We aim to represent each \)\ mathbf {x} _n $ bawah variabel laten \(\mathbf{z}_n \in \mathbb{R}^K\) dengan dimensi yang lebih rendah, $ K <D\(. The set of principal axes \)\ mathbf {W} $ berkaitan variabel laten untuk data.

Secara khusus, kami mengasumsikan bahwa setiap variabel laten terdistribusi normal,

\[ \begin{equation*} \mathbf{z}_n \sim N(\mathbf{0}, \mathbf{I}). \end{equation*} \]

Titik data yang sesuai dihasilkan melalui proyeksi,

\[ \begin{equation*} \mathbf{x}_n \mid \mathbf{z}_n \sim N(\mathbf{W}\mathbf{z}_n, \sigma^2\mathbf{I}), \end{equation*} \]

di mana matriks \(\mathbf{W}\in\mathbb{R}^{D\times K}\) dikenal sebagai sumbu utama. Dalam PCA probabilistik, kita biasanya tertarik dalam memperkirakan sumbu utama \(\mathbf{W}\) dan istilah noise\(\sigma^2\).

PCA probabilistik menggeneralisasi PCA klasik. Meminggirkan variabel laten, distribusi setiap titik data adalah

\[ \begin{equation*} \mathbf{x}_n \sim N(\mathbf{0}, \mathbf{W}\mathbf{W}^\top + \sigma^2\mathbf{I}). \end{equation*} \]

PCA klasik adalah kasus khusus dari PCA probabilistik ketika kovarians dari kebisingan menjadi sangat kecil, \(\sigma^2 \to 0\).

Kami mengatur model kami di bawah ini. Dalam analisis kami, kami menganggap \(\sigma\) diketahui, dan bukan titik memperkirakan \(\mathbf{W}\) sebagai parameter model kita menempatkan sebelum di atasnya dalam rangka untuk menyimpulkan distribusi lebih sumbu utama. Kami akan mengungkapkan model sebagai TFP JointDistribution, khusus, kita akan menggunakan JointDistributionCoroutineAutoBatched .

def probabilistic_pca(data_dim, latent_dim, num_datapoints, stddv_datapoints):
  w = yield tfd.Normal(loc=tf.zeros([data_dim, latent_dim]),
                 scale=2.0 * tf.ones([data_dim, latent_dim]),
                 name="w")
  z = yield tfd.Normal(loc=tf.zeros([latent_dim, num_datapoints]),
                 scale=tf.ones([latent_dim, num_datapoints]),
                 name="z")
  x = yield tfd.Normal(loc=tf.matmul(w, z),
                       scale=stddv_datapoints,
                       name="x")
num_datapoints = 5000
data_dim = 2
latent_dim = 1
stddv_datapoints = 0.5

concrete_ppca_model = functools.partial(probabilistic_pca,
    data_dim=data_dim,
    latent_dim=latent_dim,
    num_datapoints=num_datapoints,
    stddv_datapoints=stddv_datapoints)

model = tfd.JointDistributionCoroutineAutoBatched(concrete_ppca_model)

Data

Kita dapat menggunakan model untuk menghasilkan data dengan mengambil sampel dari distribusi prior bersama.

actual_w, actual_z, x_train = model.sample()

print("Principal axes:")
print(actual_w)
Principal axes:
tf.Tensor(
[[ 2.2801023]
 [-1.1619819]], shape=(2, 1), dtype=float32)

Kami memvisualisasikan kumpulan data.

plt.scatter(x_train[0, :], x_train[1, :], color='blue', alpha=0.1)
plt.axis([-20, 20, -20, 20])
plt.title("Data set")
plt.show()

png

Maksimum Inferensi Posterior

Kami pertama mencari estimasi titik variabel laten yang memaksimalkan kepadatan probabilitas posterior. Hal ini dikenal sebagai maksimum posteriori (MAP) inferensi, dan dilakukan dengan menghitung nilai-nilai \(\mathbf{W}\) dan \(\mathbf{Z}\) yang memaksimalkan posterior density \(p(\mathbf{W}, \mathbf{Z} \mid \mathbf{X}) \propto p(\mathbf{W}, \mathbf{Z}, \mathbf{X})\).

w = tf.Variable(tf.random.normal([data_dim, latent_dim]))
z = tf.Variable(tf.random.normal([latent_dim, num_datapoints]))

target_log_prob_fn = lambda w, z: model.log_prob((w, z, x_train))
losses = tfp.math.minimize(
    lambda: -target_log_prob_fn(w, z),
    optimizer=tf.optimizers.Adam(learning_rate=0.05),
    num_steps=200)
plt.plot(losses)
[<matplotlib.lines.Line2D at 0x7f19897a42e8>]

png

Kita dapat menggunakan model untuk data sampel untuk nilai disimpulkan untuk \(\mathbf{W}\) dan \(\mathbf{Z}\), dan dibandingkan dengan dataset yang sebenarnya kita dikondisikan pada.

print("MAP-estimated axes:")
print(w)

_, _, x_generated = model.sample(value=(w, z, None))

plt.scatter(x_train[0, :], x_train[1, :], color='blue', alpha=0.1, label='Actual data')
plt.scatter(x_generated[0, :], x_generated[1, :], color='red', alpha=0.1, label='Simulated data (MAP)')
plt.legend()
plt.axis([-20, 20, -20, 20])
plt.show()
MAP-estimated axes:
<tf.Variable 'Variable:0' shape=(2, 1) dtype=float32, numpy=
array([[ 2.9135954],
       [-1.4826864]], dtype=float32)>

png

Inferensi Variasi

MAP dapat digunakan untuk menemukan mode (atau salah satu mode) dari distribusi posterior, tetapi tidak memberikan wawasan lain tentangnya. Kami berikutnya menggunakan inferensi variasional, di mana posterior distribtion \(p(\mathbf{W}, \mathbf{Z} \mid \mathbf{X})\) didekati menggunakan distribusi variational \(q(\mathbf{W}, \mathbf{Z})\) parametrised oleh \(\boldsymbol{\lambda}\). Tujuannya adalah untuk menemukan parameter variational \(\boldsymbol{\lambda}\) yang meminimalkan perbedaan KL antara q dan posterior, \(\mathrm{KL}(q(\mathbf{W}, \mathbf{Z}) \mid\mid p(\mathbf{W}, \mathbf{Z} \mid \mathbf{X}))\), atau ekuivalen, yang memaksimalkan bukti batas bawah, \(\mathbb{E}_{q(\mathbf{W},\mathbf{Z};\boldsymbol{\lambda})}\left[ \log p(\mathbf{W},\mathbf{Z},\mathbf{X}) - \log q(\mathbf{W},\mathbf{Z}; \boldsymbol{\lambda}) \right]\).

qw_mean = tf.Variable(tf.random.normal([data_dim, latent_dim]))
qz_mean = tf.Variable(tf.random.normal([latent_dim, num_datapoints]))
qw_stddv = tfp.util.TransformedVariable(1e-4 * tf.ones([data_dim, latent_dim]),
                                        bijector=tfb.Softplus())
qz_stddv = tfp.util.TransformedVariable(
    1e-4 * tf.ones([latent_dim, num_datapoints]),
    bijector=tfb.Softplus())
def factored_normal_variational_model():
  qw = yield tfd.Normal(loc=qw_mean, scale=qw_stddv, name="qw")
  qz = yield tfd.Normal(loc=qz_mean, scale=qz_stddv, name="qz")

surrogate_posterior = tfd.JointDistributionCoroutineAutoBatched(
    factored_normal_variational_model)

losses = tfp.vi.fit_surrogate_posterior(
    target_log_prob_fn,
    surrogate_posterior=surrogate_posterior,
    optimizer=tf.optimizers.Adam(learning_rate=0.05),
    num_steps=200)
print("Inferred axes:")
print(qw_mean)
print("Standard Deviation:")
print(qw_stddv)

plt.plot(losses)
plt.show()
Inferred axes:
<tf.Variable 'Variable:0' shape=(2, 1) dtype=float32, numpy=
array([[ 2.4168603],
       [-1.2236133]], dtype=float32)>
Standard Deviation:
<TransformedVariable: dtype=float32, shape=[2, 1], fn="softplus", numpy=
array([[0.0042499 ],
       [0.00598824]], dtype=float32)>

png

posterior_samples = surrogate_posterior.sample(50)
_, _, x_generated = model.sample(value=(posterior_samples))

# It's a pain to plot all 5000 points for each of our 50 posterior samples, so
# let's subsample to get the gist of the distribution.
x_generated = tf.reshape(tf.transpose(x_generated, [1, 0, 2]), (2, -1))[:, ::47]

plt.scatter(x_train[0, :], x_train[1, :], color='blue', alpha=0.1, label='Actual data')
plt.scatter(x_generated[0, :], x_generated[1, :], color='red', alpha=0.1, label='Simulated data (VI)')
plt.legend()
plt.axis([-20, 20, -20, 20])
plt.show()

png

ucapan terima kasih

Tutorial ini awalnya ditulis dalam Edward 1.0 ( sumber ). Kami berterima kasih kepada semua kontributor untuk menulis dan merevisi versi itu.

Referensi

[1]: Michael E. Tipping dan Christopher M. Bishop. Analisis komponen utama probabilistik. Jurnal Royal Society Statistik: Seri B (Metodologi statistik), 61 (3): 611-622, 1999.