[PYTHON] Apprentissage profond du noyau avec Pyro

Le Deep Kernel Learning est une combinaison d'apprentissage profond et de processus gaussiens, et fait partie de l'apprentissage profond bayésien. En tant que méthode, un noyau profond est créé en utilisant les fonctionnalités produites par le réseau neuronal profond (DNN) comme entrée du noyau dans le processus gaussien. La formule est la suivante.

k_{deep}(x,x') = k(f(x),f(x'))

Puisque le processus gaussien équivaut à un réseau de neurones avec des unités infinies, il semble qu'il a été ajouté à la fin de DNN. Comme je l'ai essayé dans l'article précédent (https://qiita.com/takeajioka/items/f24d58d2b13017ab2b18), il est important d'optimiser les hyperparamètres du noyau lors du processus gaussien. L'apprentissage profond du noyau semble optimiser et apprendre les paramètres DNN et les hyper paramètres du noyau en même temps.

Veuillez vous référer au document suivant pour plus de détails. [1] Deep Kernel Learning, 2015, Andrew G. Wilson et al.,https://arxiv.org/abs/1511.02222 [2] Stochastic Variational Deep Kernel Learning, 2016, Andrew G. Wilson et al., https://arxiv.org/abs/1611.00336

Essayez d'apprendre MNIST avec Deep Kernel Learning

Dans Pyro, vous pouvez facilement créer un noyau profond en utilisant la classe gp.kernels.Warping. Il existe un code pour l'apprentissage profond du noyau dans le tutoriel officiel de Pyro, apprenons donc en y faisant référence.

import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision
from torchvision import transforms
import pyro
import pyro.contrib.gp as gp
import pyro.infer as infer

Puisque MNIST a une grande quantité de données, nous l'apprendrons dans un mini-lot. Définissez le jeu de données.

batch_size = 100
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5, ), (0.5, ))])
trainset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=True)
testset = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=False)

Tout d'abord, préparez un modèle DNN normal.

class CNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
        self.fc1 = nn.Linear(320, 50)
        self.fc2 = nn.Linear(50, 10)
    def forward(self, x):
        x = F.relu(F.max_pool2d(self.conv1(x), 2))
        x = F.relu(F.max_pool2d(self.conv2(x), 2))
        x = x.view(-1, 320)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

Enveloppez le noyau dans ceci pour créer un noyau profond.

rbf = gp.kernels.RBF(input_dim=10, lengthscale=torch.ones(10))
deep_kernel = gp.kernels.Warping(rbf, iwarping_fn=CNN())

Une approximation parcimonieuse est utilisée pour réduire le coût de calcul du processus gaussien. Dans l'approximation clairsemée, le point d'induction est utilisé, mais cette fois, nous utiliserons les données d'apprentissage pour une taille de lot.

Xu, _ = next(iter(trainloader))
likelihood = gp.likelihoods.MultiClass(num_classes=10)
gpmodule = gp.models.VariationalSparseGP(X=None, y=None, kernel=deep_kernel, Xu=Xu, likelihood=likelihood, latent_shape=torch.Size([10]), num_data=60000)
optimizer = torch.optim.Adam(gpmodule.parameters(), lr=0.01)
elbo = infer.TraceMeanField_ELBO()
loss_fn = elbo.differentiable_loss

Définit une fonction pour l'apprentissage par mini-lots.

def train(train_loader, gpmodule, optimizer, loss_fn, epoch):
    total_loss = 0
    for data, target in train_loader:
        gpmodule.set_data(data, target)
        optimizer.zero_grad()
        loss = loss_fn(gpmodule.model, gpmodule.guide)
        loss.backward()
        optimizer.step()
        total_loss += loss
    return total_loss / len(train_loader)

def test(test_loader, gpmodule):
    correct = 0
    for data, target in test_loader:
        f_loc, f_var = gpmodule(data)
        pred = gpmodule.likelihood(f_loc, f_var)
        correct += pred.eq(target).long().sum().item()
    return 100. * correct / len(test_loader.dataset)

Apprenez.

import time
losses = []
accuracy = []
epochs = 10
for epoch in range(epochs):
    start_time = time.time()
    loss = train(trainloader, gpmodule, optimizer, loss_fn, epoch)
    losses.append(loss)
    with torch.no_grad():
        acc = test(testloader, gpmodule)
    accuracy.append(acc)
    print("Amount of time spent for epoch {}: {}s\n".format(epoch+1, int(time.time() - start_time)))
print("loss:{:.2f}, accuracy:{}".format(losses[-1],accuracy[-1]))

J'ai pu apprendre une époque en 30 secondes environ. La précision finale était de 96,23%. (Il semble que cela puisse atteindre 99,41% dans le tutoriel officiel.) Affichez la courbe d'apprentissage.

import matplotlib.pyplot as plt
plt.subplot(2,1,1)
plt.plot(losses)
plt.xlabel("epoch")
plt.ylabel("loss")
plt.subplot(2,1,2)
plt.plot(accuracy)
plt.xlabel("epoch")
plt.ylabel("accuracy")

image.png

Regardons l'image de test et la sortie prévue côte à côte.

data, target = next(iter(testloader))
f_loc, f_var = gpmodule(data)
pred = gpmodule.likelihood(f_loc, f_var)
for i in range(len(data)):
    plt.subplot(1,2,1)
    plt.imshow(data[i].reshape(28, 28))
    plt.subplot(1,2,2)
    plt.bar(range(10), f_loc[:,i].detach(), yerr= f_var[:,i].detach())
    ax = plt.gca()
    ax.set_xticks(range(10))
    plt.xlabel("class")
    plt.savefig('image/figure'+ str(i) +'.png')
    plt.clf()

figure0.png figure12.png figure15.png

La barre bleue est la valeur moyenne et la barre d'erreur est la distribution. On a constaté que chacune des 10 classes avait une sortie et que la classe correcte avait une valeur élevée.

Regardons également des images difficiles à distinguer. figure36.png figure43.png figure92.png La sortie est élevée dans plusieurs classes. Compte tenu de la barre d'erreur, il semble qu'il n'y ait pas de différence significative.

À la fin

J'ai pu apprendre comme un Deep Learning normal. Je pense que c'est un avantage que Deep Learnig normal n'a pas de pouvoir afficher la valeur moyenne et la variance en sortie. Il existe également un processus gaussien profond (DGP), qui est une pile de processus gaussiens, alors j'aimerais également étudier cela.

Recommended Posts

Apprentissage profond du noyau avec Pyro
Essayez l'apprentissage en profondeur avec TensorFlow
Essayez le Deep Learning avec FPGA
Générez des Pokémon avec Deep Learning
L'apprentissage en profondeur
Essayez le Deep Learning avec les concombres FPGA-Select
Identification de la race de chat avec Deep Learning
Faites de l'art ASCII avec l'apprentissage en profondeur
Essayez l'apprentissage en profondeur avec TensorFlow Partie 2
Vérifiez la forme de squat avec l'apprentissage en profondeur
Catégoriser les articles de presse grâce au Deep Learning
Prévisions des ventes de collations avec apprentissage en profondeur
Faites sourire les gens avec le Deep Learning
Classez les visages d'anime avec l'apprentissage en profondeur avec Chainer
Mémorandum d'apprentissage profond
Essayez les prévisions de prix Bitcoin avec Deep Learning
Essayez avec Chainer Deep Q Learning - Lancement
Commencer l'apprentissage en profondeur
Essayez l'apprentissage profond de la génomique avec Kipoi
Analyse émotionnelle des tweets avec apprentissage en profondeur
Apprentissage en profondeur Python
Apprentissage profond × Python
L'histoire de l'apprentissage profond avec TPU
99,78% de précision avec apprentissage en profondeur en reconnaissant les hiragana manuscrits
Premier apprentissage profond ~ Lutte ~
Apprendre Python avec ChemTHEATER 03
"Orienté objet" appris avec python
Apprendre Python avec ChemTHEATER 05-1
Baies non paramétriques avec Pyro
Apprentissage profond à partir de zéro
Méthode Kernel avec Python
Deep learning 1 Pratique du deep learning
Apprentissage profond / entropie croisée
Premier apprentissage profond ~ Préparation ~
Première solution d'apprentissage en profondeur ~
[AI] Apprentissage métrique profond
Apprendre Python avec ChemTHEATER 02
J'ai essayé le deep learning
Apprendre Python avec ChemTHEATER 01
Python: réglage du Deep Learning
Technologie d'apprentissage en profondeur à grande échelle
Fonction d'apprentissage profond / softmax
Une histoire de prédiction du taux de change avec Deep Learning
Analyse d'images par apprentissage profond à partir de Kaggle et Keras
Prédire les tags en extrayant des fonctionnalités musicales avec Deep Learning
Classer les visages d'anime par suite / apprentissage profond avec Keras
Régression du noyau avec Numpy uniquement
Apprentissage profond à partir de zéro 1 à 3 chapitres
Essayez de créer un réseau de neurones / d'apprentissage en profondeur avec scratch
[Evangelion] Essayez de générer automatiquement des lignes de type Asuka avec Deep Learning
<Cours> Apprentissage en profondeur: Day2 CNN
Noyau Linux auto-construit avec clang
Reconnaissance d'image par apprentissage profond 1 théorie
Deep running 2 Réglage de l'apprentissage profond
Créez un environnement pour "Deep Learning from scratch" avec Docker
Apprentissage amélioré à partir de Python
À propos de l'apprentissage avec Google Colab
Apprentissage profond / code de travail LSTM
Apprentissage automatique avec Python! Préparation