[PYTHON] Baies non paramétriques avec Pyro

Les baies non paramétriques sont appelées modèles de baies de dimensions infinies. Le processus gaussien réalisé dans Article précédent est également des baies non paramétriques, mais un autre processus célèbre est le ** processus Diricre **. Pour une explication théorique, reportez-vous à "Baies non paramétriques (série professionnelle d'apprentissage automatique)" et à article Qiita ici.

En premier lieu, l'inférence bayésienne est effectuée dans les trois étapes suivantes. (1) Définir la distribution a priori des paramètres et le modèle de probabilité de l'événement (2) Calculer la vraisemblance à partir des données obtenues et du modèle de probabilité, et calculer la distribution a posteriori des paramètres en la multipliant par le paramètre distribution a priori (théorème de Bayes). (3) Générer une distribution de probabilité prédite des données à partir de la distribution postérieure des paramètres et du modèle de probabilité La distribution dans laquelle la distribution a priori et la distribution postérieure sont les mêmes en (2) est appelée distribution a priori conjuguée. Tout comme la distribution bêta est la distribution a priori conjuguée du modèle de distribution binomiale, la distribution de Diricre est la distribution a priori conjuguée du modèle de distribution polynomiale. En d'autres termes, la distribution de Diricre est une distribution multivariée de la distribution bêta.

Le processus Diricle est celui qui considère la distribution Diricle dans des dimensions infinies. On a l'impression que le processus gaussien est une distribution gaussienne multivariée infiniment dimensionnelle. Cependant, alors que le processus gaussien est continu, le processus de Diricre est discret. Puisqu'elle est discrète, c'est une image qui sert de modèle stochastique pour les clusters. Cela permet le clustering (Diliquere Process Mixing Model (DPMM)) qui détermine automatiquement le nombre de clusters. Cependant, le processus Diricle est difficile à implémenter en raison du nombre infini d'éléments. Il y a donc deux manières. (1) Une méthode d'approximation avec des dimensions finies au lieu de l'infini. Il utilise le processus de pliage de la barre de coupe (TSB) et la distribution de direction symétrique finie (FSD). Il est possible de résoudre avec la variante Bayes. (2) Une méthode utilisant le procédé restaurant chinois (CRP) et le procédé Pitman-Yo dans lequel un nombre infini d'éléments sont intégrés et éliminés. Cette méthode n'autorise pas les baies variables, uniquement MCMC.

Cette fois, nous allons implémenter par ① avec Pyro.

Modèle mixte de processus Diricle (TSB) avec Pyro

Par exemple, dans la méthode k-means et le clustering dans le modèle mixte gaussien, il est nécessaire de spécifier le nombre de clusters comme paramètre. (Calculez et ajustez l'AIC, etc.) D'autre part, dans le clustering avec ce processus mixte de processus Diricle, le nombre de clusters peut être déterminé automatiquement, ce qui permet un clustering flexible.

En pyro, le processus Diricle n'a pas de classe dédiée comme le processus Gaussien, il sera donc implémenté à partir du modèle. Cette fois, nous allons implémenter TSB (processus de pliage de la barre de coupe) en se référant à Exemple de tutoriel officiel.

import torch
import pyro
import pyro.distributions as dist
import matplotlib.pyplot as plt
pyro.set_rng_seed(101)

Commencez par créer les données. Échantillonnez 200 morceaux de données de chacune des quatre distributions gaussiennes bidimensionnelles.

num = 200
data = torch.cat((dist.MultivariateNormal(-8 * torch.ones(2), torch.eye(2)).sample([num]),
                  dist.MultivariateNormal(8 * torch.ones(2), torch.eye(2)).sample([num]),
                  dist.MultivariateNormal(torch.tensor([-5., 5.]), torch.eye(2)).sample([num]),
                  dist.MultivariateNormal(torch.tensor([6., -5.]), torch.eye(2)).sample([num])
                 ))
plt.scatter(data[:, 0], data[:, 1])
plt.show()

image.png

Regroupez ces 800 données sans spécifier le nombre de clusters.

Définissez une fonction pour plier une barre.

import torch.nn.functional as F
def mix_weights(beta):
    beta1m_cumprod = (1 - beta).cumprod(-1)
    return F.pad(beta, (0, 1), value=1) * F.pad(beta1m_cumprod, (1, 0), value=1)

Définit un modèle probabiliste pour TSB. alpha est un paramètre de concentration qui représente le degré de variation de classe. T est la limite supérieure du nombre de clusters. Cette fois, je l'ai mis à 10.

N = data.shape[0]
T = 10
alpha = 0.1
def model(data):
    with pyro.plate("beta_plate", T-1):
        beta = pyro.sample("beta", dist.Beta(1, alpha))
    with pyro.plate("mu_plate", T):
        mu = pyro.sample("mu", dist.MultivariateNormal(torch.zeros(2), 5 * torch.eye(2)))
    with pyro.plate("data", N):
        z = pyro.sample("z", dist.Categorical(mix_weights(beta)))
        pyro.sample("obs", dist.MultivariateNormal(mu[z], torch.eye(2)), obs=data)

Vous ne pouvez pas utiliser l'autoguide, définissez donc votre propre fonction de guidage.

from torch.distributions import constraints
def guide(data):
    kappa = pyro.param('kappa', lambda: dist.Uniform(0, 2).sample([T-1]), constraint=constraints.positive)
    tau = pyro.param('tau', lambda: dist.MultivariateNormal(torch.zeros(2), 3 * torch.eye(2)).sample([T]))
    phi = pyro.param('phi', lambda: dist.Dirichlet(1/T * torch.ones(T)).sample([N]), constraint=constraints.simplex)
    with pyro.plate("beta_plate", T-1):
        q_beta = pyro.sample("beta", dist.Beta(torch.ones(T-1), kappa))
    with pyro.plate("mu_plate", T):
        q_mu = pyro.sample("mu", dist.MultivariateNormal(tau, torch.eye(2)))
    with pyro.plate("data", N):
        z = pyro.sample("z", dist.Categorical(phi))

Exécutez la variante Bayes.

from pyro.optim import Adam
from pyro.infer import SVI, Trace_ELBO
from tqdm import tqdm
optim = Adam({"lr": 0.05})
svi = SVI(model, guide, optim, loss=Trace_ELBO())
losses = []
num_step = 1000
pyro.clear_param_store()
for j in tqdm(range(num_step)):
    loss = svi.step(data)
    losses.append(loss)
plt.plot(losses)
plt.xlabel("step")
plt.ylabel("loss")

image.png

Définissez une fonction pour éliminer (interrompre) une classe à faible probabilité postérieure.

def truncate(alpha, centers, weights):
    threshold = alpha**-1 / 100.
    print(threshold)
    true_centers = centers[weights > threshold]
    true_weights = weights[weights > threshold] / torch.sum(weights[weights > threshold])
    return true_centers, true_weights

Éliminez la classe la moins probable et affichez le résultat de la prédiction.

Bayes_Centers, Bayes_Weights = truncate(alpha, pyro.param("tau").detach(), torch.mean(pyro.param("phi").detach(), dim=0))
plt.scatter(data[:, 0], data[:, 1], color="blue")
plt.scatter(Bayes_Centers[:, 0], Bayes_Centers[:, 1], color="red")

image.png Quatre classes ont été reconnues. Je pense que le centre est également capturé assez précisément. C'est un bon exemple, mais cela n'a pas fonctionné selon les valeurs d'alpha et de T.

Autres applications

Estimation des changements structurels

Lors de l'application d'un modèle de régression linéaire à des données de séries chronologiques, nous considérons un modèle linéaire infini par le processus Diricle. En regroupant chaque modèle, les données de séries chronologiques peuvent être segmentées. Référence: https://www.slideshare.net/shotarosano5/in-62843951

HDP-LDA LDA (Potential Diricle Allocation Method) est un apprentissage non supervisé et est utilisé dans les modèles de sujets. (Exemple d'implémentation LDA Pyro) HDP-LDA utilisant HDP (Hierarchical Diricle Process) peut déterminer automatiquement le nombre approprié de sujets. Cela semble facile à faire avec une bibliothèque Python appelée Gensim. Le processus de diricre hiérarchique est calqué sur le CRF (Chinese Restaurant Franchise), qui est une étape plus compliquée que le CRP (Chinese Restaurant Process).

la fin

Je pensais que les baies non paramétriques ne sont pas sans paramètres, mais qu'elles pensent à un nombre infini ou grand de paramètres (il n'y a aucune restriction sur le nombre de paramètres). Cependant, notez que la mise en œuvre du TSB nécessite cette fois une limite supérieure du nombre de grappes. Je voudrais également essayer Implémentation de CRP, qui ne nécessite pas de limite supérieure.

Recommended Posts

Baies non paramétriques avec Pyro
Introduction aux baies non paramétriques
Apprentissage profond du noyau avec Pyro
[Python] Estimation bayésienne avec Pyro
[Python] Modèle gaussien mixte avec Pyro
Filtrage de texte avec des baies naïves de sklearn