[PYTHON] La relation entre la science du cerveau et l'apprentissage non supervisé. Maximisez la quantité d'informations MNIST: Google Colabratory (PyTorch)

Dans cet article, j'expliquerai la mise en œuvre d'IIC qui offre des performances élevées avec MNIST dans l'apprentissage non supervisé, la science du cerveau et l'apprentissage non supervisé.

Les articles abordés dans cet article sont Invariant Information Clustering for Unsupervised Image Classification and Segmentation est.

Dans cet article, nous utilisons un index appelé ** Mutual Information Amount ** pour classer les images numériques manuscrites en regroupant l'apprentissage non supervisé.

Il s'appelle IIC (Invariant Information Clustering).

Dans cet article, j'expliquerai la science du cerveau et l'apprentissage non supervisé, les points IIC et des exemples de mise en œuvre dans MNIST.

La table des matières est la suivante.

  1. Science du cerveau et apprentissage non supervisé
  2. Focus sur l'apprentissage non supervisé dans le domaine de l'intelligence artificielle
  3. Points de la méthode proposée IIC
  4. Mise en œuvre d'IIC avec MNIST (Google Colabratory et PyTorch)

Le code d'implémentation "MNIST_IIC.ipynb" se trouve ici. Référentiel de code d'implémentation

1. Science du cerveau et apprentissage non supervisé

Le récent boom de l'IA et de l'intelligence artificielle est alimenté par la technologie d'apprentissage en profondeur.

Cependant, la plupart de l'apprentissage en profondeur est un apprentissage supervisé ou un apprentissage amélioré (comme Alpha Go).

Il n'est pas courant d'utiliser le deep learning pour un apprentissage non supervisé (Je vois la compression de dimension représentée par AutoEncoder, mais il y a peu de clustering).

En regardant le domaine de la science du cerveau, OIST (Okinawa Science and Technology Graduate University) Livre du professeur Doya "Invitation à la neuroscience computationnelle" visant à comprendre le mécanisme d'apprentissage du cerveau " Comme le montre la figure ci-dessous, la relation entre les trois types d'apprentissage de l'intelligence artificielle et le cerveau est suggérée.

l_bit201806011320437219.jpg

Citation de l'image: Pourquoi les modules de circuits cérébraux peuvent-ils bien se connecter - Professeur Kenji Doya, Université de technologie d'Okinawa

C'est le développement du cortex cérébral (en particulier le lobe frontal) qui distingue les humains des autres organismes en matière d'intelligence. ** Dans son cortex cérébral, l'importance de l'apprentissage non supervisé est suggérée. ** **

Le travail de Huber et Weasel, qui a remporté le prix Nobel de physiologie et de médecine en 1981, est bien connu des chercheurs en sciences du cerveau.

Ils transpercent les cellules nerveuses du cerveau du chat avec des électrodes En mesurant l'activité des cellules nerveuses lors de l'affichage de divers symboles et tiges mobiles, Dans le champ visuel du cortex cérébral, chaque cellule nerveuse a une position de présentation de symbole et la direction dans laquelle la tige s'étend (verticale, horizontale, diagonale), etc. ** Il a été révélé que les cellules nerveuses agissent de manière sélective en fonction de l'objet présenté **.

Dans la figure ci-dessous, cette cellule nerveuse est un neurone qui répond fortement à la barre verticale.

1024px-Orientation_V1.svg.png Orientation selectivity

En d'autres termes, il existe des cellules nerveuses correspondant à la barre horizontale, des cellules nerveuses correspondant à la barre verticale, etc., et le traitement de ces neurones est traité de manière complexe pour reconnaître l'objet.

Puis, au 21ème siècle, ** Une partie du cerveau qui s'enflamme en réponse à une image faciale et une partie du cerveau qui s'enflamme en réponse à une célébrité spécifique ont été découvertes. ** ** Mécanisme de reconnaissance faciale - extrait du numéro d'octobre 2017 de Nikkei Science

Parce qu'il y avait une telle prémisse (l'existence de neurones qui réagissent spécifiquement aux objets du cortex cérébral), Au tout début de l'apprentissage profond, Google ** Annonce que les neurones correspondant au visage du chat sont nés dans la couche intermédiaire de l'apprentissage profond ** C'était une grande nouvelle. Using large-scale brain simulations for machine learning and A.I.

En effet, l'apprentissage profond a acquis des caractéristiques similaires à celles d'un véritable cerveau vivant.

Et il y a une autre expérience bien connue sur le cerveau, en particulier sur l'apprentissage non supervisé.

Expérience Blackmore et Cooper. Elles sont, ** Si vous élevez un chaton dans un environnement où vous ne pouvez voir que temporairement les lignes verticales, vous ne pourrez pas reconnaître les lignes horizontales pour le moment ** Je l'ai précisé.

C'est un environnement comme l'image ci-dessous.

catexperiment.gif

Cats and Vision: is vision acquired or innate?

En d'autres termes, Hubel et Weasel ont révélé l'existence de neurones qui répondent sélectivement aux barres verticales et horizontales. Blackmore et Cooper ont montré que de tels neurones sont nés dans le cortex cérébral pendant le développement du chaton, avec de tels paysages apportés aux yeux.

C'est une découverte de la science du cerveau que ** l'apprentissage non supervisé jouera un rôle important dans la reconnaissance d'objets en raison du développement du champ visuel des chatons **.

2. Focus sur l'apprentissage non supervisé dans le domaine de l'intelligence artificielle

Même dans le domaine des chercheurs en IA, il y a des remarques remarquables mettant l'accent sur l'importance des efforts pour l'apprentissage non supervisé plutôt que sur l'apprentissage profond conventionnel de l'apprentissage supervisé.

Hinton a été présenté dans le blog de PFN Okanohara en 2017,

Professeur Geoffrey Hinton aussi [lien] "Il y a 10 ^ 14 synapses cérébrales, mais les humains ne peuvent vivre que 10 ^ 9 secondes. Il y a beaucoup plus de paramètres que d'échantillons (de ces synapses). Nous avons besoin de 10 ^ 5 contraintes par seconde (pour déterminer les poids), et nous arrivons à l'idée que nous faisons beaucoup d'apprentissage non supervisé. "

5 ans après la contre-attaque du réseau neuronal

Il est dit.

Nous menons actuellement des recherches et avons annoncé SimCLR (A Simple Framework for Contrastive Learning of Visual Representations) en février 2020.

Geoffrey Hinton & Google Brain Unsupervised Learning Algorithm Improves SOTA Accuracy on ImageNet by 7%

illustration-of-the-proposed-SimCLR-framework.gif

Citation de l'image et explication de SimCLR: SimCLR: Améliorer les performances de l'apprentissage autonome par l'apprentissage par contraste

Dans SimCLR, ** saisissez différentes paires converties dans la même image et apprenez qu'elles sont identiques, tout en apprenant que différentes images sont différentes d'elles par un apprentissage non supervisé et la quantité de fonctionnalités de l'image Obtenez d'abord la technique pour extraire. ** **

De plus, Jan Lucan était à l'AAAI en février 2020.

M. Lucan a déclaré que la prochaine innovation de l'apprentissage en profondeur n'est pas l'apprentissage supervisé, mais «l'apprentissage non supervisé» qui extrait les fonctionnalités des données sans balises de réponse correctes, et «l'apprentissage auto-supervisé (auto-) qui crée des réponses correctes à partir des données d'apprentissage. Enseignement supervisé) ". «Ce sont les mêmes tâches que les nouveau-nés font dans le monde», explique Lucan. Les bébés peuvent apprendre par eux-mêmes sans donner la «bonne réponse».

Il est dit. Quelles sont les lacunes actuelles de l'IA signalées par les trois «pères divins» de l'apprentissage en profondeur

Si nous continuons à parler de science du cerveau et d'intelligence artificielle, nous ne pourrons pas atteindre l'implémentation d'origine, alors allez ici.

En outre, l'article de Hinton d'avril 2020 sur Nature Reviews Neuroscience "Back propagation and the brain" Backpropagation and the brain

Loi NGRAD dans ([Représentation du gradient neuronal par différences d'activité](https://syncedreview.com/2020/04/23/new-hinton-nature-paper-revisits-backpropagation-offers-insights-for-understanding-learning- dans-le-cortex /)))

image-78.png

Est introduit.

Autre, ● Conversation entre un scientifique du cerveau et un ingénieur informatique sur la DL et l'intelligence artificielle à usage généralApplication commerciale d'apprentissage par renforcement profond et comment faire comprendre à l'IA le langage naturel

Est également un article précédent recommandé sur la science du cerveau et l'IA.

3. Points de la méthode proposée IIC

Eh bien, ce papier, Invariant Information Clustering for Unsupervised Image Classification and Segmentation

Je vais expliquer les points de IIC (Invariant Information Clustering) dans.

De plus, l'article de l'IIC lui-même n'a pas de description telle que "Comment fonctionne le cerveau ...", c'est un article avec une méthode de calcul pure.

Il y a deux points dans IIC.

** Le premier point est entré **. Pour entrée ・ Données (cette fois-ci, image numérique manuscrite) ・ Données converties de manière appropriée Utilisez-en deux. Entrez chacun dans le réseau et obtenez la sortie de chacun.

Le réseau d'apprentissage en profondeur d'IIC est similaire à l'apprentissage supervisé. Le nombre de neurones dans la couche de sortie est de 10 (correspondant aux nombres de 0 à 9). Multipliez la sortie par la fonction softmax pour afficher la valeur de probabilité que l'image d'entrée soit de 0 à 9.

Le deuxième point est la ** fonction de perte **. Puisqu'il s'agit d'un apprentissage non supervisé, nous n'utilisons pas d'étiquettes d'enseignant. Au lieu, ・ Sortie de vecteur (10 éléments) en entrant une image numérique manuscrite dans le réseau neuronal Quand, -Vecteur de sortie (10 éléments) qui sort en saisissant une image un peu convertie au hasard à partir d'une image numérique manuscrite Calculez la ** quantité d'informations mutuelles ** et entraînez-la pour la maximiser.

Par conséquent, vous devez être ami avec des informations mutuelles pour comprendre IIC.

Vous trouverez ci-dessous une diapositive qui explique la quantité d'informations mutuelles.

図1.png

Certaines formules difficiles sont alignées, mais ** après tout, les informations partagées par les deux données sont appelées le montant d'informations mutuelles **.

La clé est ** distribution simultanée et distribution de probabilité périphérique ** dans le journal.

Dans l'image ci-dessus, l'exemple 1 montre un exemple de lancement de deux pièces indépendantes, et l'exemple 2 montre un exemple de lancement de deux pièces non indépendantes. (Autrement dit, dans l'exemple 2, la deuxième pièce a le même résultat que la première)

L'image ci-dessus est un exemple de pièce de monnaie, qui en produit deux, recto et verso.

Dans le cas du réseau neuronal MNIST, 10 éléments de 0 à 9 sont émis.

Pensez aux deux versions de sortie du réseau neuronal de MNIST comme le jette la pièce ci-dessus.

Si les deux de l'exemple 1 sont indépendants, la probabilité d'être (arrière, arrière) est de 0,25. Et la probabilité que la première feuille soit au verso après la marginalisation est de 0,5 pour (verso, verso) + (verso, recto). De même, la probabilité que la deuxième feuille soit au verso est de 0,5 pour (recto, verso) + (verso, verso). Si vous les incluez dans le calcul du journal, le résultat du journal sera 0.

Si vous calculez non seulement (arrière, arrière) mais aussi (arrière, avant), (avant, arrière), (avant, avant), tous sont 0 et le total est 0.

Par conséquent, si vous lancez deux pièces indépendantes, la quantité d'informations mutuelles entre le premier résultat et le deuxième résultat est de 0.

Étant donné que les essais de lancer de pièces sont indépendants et que les premier et deuxième résultats ne sont pas pertinents, il n'y a aucune information à partager, et je pense que vous pouvez être convaincu que ce sera 0.

Considérez la quantité d'informations mutuelles lorsque la deuxième pièce, qui n'est pas indépendante dans l'exemple 2, donne le même résultat que la première pièce.

La probabilité de devenir (retour, retour) est de 0,5. Et la probabilité que la première feuille soit au verso après la marginalisation est de 0,5 pour (verso, verso) + (verso, recto). De même, la deuxième pièce est de 0,5. Ensuite, le calcul en log devient (1 / 0,5) et log2 = 0,69. Multipliez cela par la probabilité de (retour, retour) 0,5 pour obtenir environ 0,35. (Arrière, avant) est 0, (avant, avant) est d'environ 0,35 comme (arrière, arrière) et (avant, arrière) est 0, donc le total est de 0,69.

Par conséquent, dans le cas d'un lancer de pièces non indépendant, la quantité d'informations mutuelles sera supérieure à 0.

En d'autres termes, le résultat du premier jet de pièce et le résultat du deuxième jet de pièce ont des informations. Cette fois, le résultat de la deuxième feuille est le même que celui de la première feuille, donc je pense que vous pouvez le comprendre.

Dans IIC, considérez cela comme un lanceur de pièces dans 10 versions différentes de la sortie d'image MNIST 0-9.

Et la deuxième pièce est l'image MNIST avec une conversion appropriée.

En tant que conversion appropriée, la conversion affine tourne et étire l'image, et le bruit est décevant.

** Je souhaite entraîner le réseau pour que le résultat de sortie de la probabilité que cette image légèrement convertie et l'image originale soient de 0 à 9 soit le même **

C'est le sentiment d'IIC.

Une image qui a subi une certaine conversion simule, après tout, une image de la même classe.

Il y a deux points ici.

Premièrement, la sortie réseau ne correspond pas aux nombres 0 à 9 dans l'ordre, ni ne correspond aux nombres. ** Séparez simplement les images similaires dans la même classe. ** **

Le deuxième point est que je crains qu'ils ne soient tous dans la même classe, mais rappelez-vous la quantité d'informations mutuelles dans le lancer de pièces. La deuxième pièce de l'exemple 2 a le même résultat que la première pièce.

La quantité d'informations mutuelles est plus importante pour les pièces qui ont le même recto et verso que pour les pièces qui ont tous les versos.

Avec des pièces qui ont toutes une face arrière, la probabilité de devenir (face arrière, face arrière) est de 1,0. Et la probabilité que la première feuille soit au verso après la marginalisation est de 1,0 pour (verso, verso) + (verso, recto). De même, le deuxième morceau est 1.0. Ensuite, le calcul en log devient (1/1) et log1 = 0,0.

** Afin de maximiser la quantité d'informations mutuelles, la quantité d'informations mutuelles sera maximisée si les probabilités sont uniformément réparties entre 2 types s'il y a 2 types et 10 types uniformément s'il y a 10 types. ** **

Par conséquent, si vous calculez le montant du mini-lot, 10 classes naturellement séparées existeront de manière uniforme.

Ce qui précède est l'explication ponctuelle d'IIC.

Ensuite, nous commencerons l'implémentation.

4. Mise en œuvre d'IIC avec MNIST (Google Colabratory et PyTorch)

L'environnement utilise Google Colaboratory et le framework utilise PyTorch.

Implémentez IIC pour MNIST.

Le code d'implémentation "MNIST_IIC.ipynb" se trouve ici. Référentiel de code d'implémentation

https://github.com/RuABraun/phone-clustering Je vais le mettre en œuvre en référence à, mais j'ai fait beaucoup de changements.

Tout d'abord, réparez la graine

#Graine aléatoire fixe
import os
import random
import numpy as np
import torch

SEED_VALUE = 1234  #Cela peut être n'importe quoi
os.environ['PYTHONHASHSEED'] = str(SEED_VALUE)
random.seed(SEED_VALUE)
np.random.seed(SEED_VALUE)
torch.manual_seed(SEED_VALUE)  #Lors de l'utilisation de PyTorch

Ensuite, vérifiez l'utilisation du GPU. Pour Google Colaboratory, depuis "Runtime" dans le menu supérieur Sélectionnez «Modifier le type d'exécution» et basculez Aucun sur GPU.

#Lorsque le GPU est disponible, sélectionnez GPU (dans le cas de Google Colaboratory, spécifiez le GPU à partir de l'exécution)
device = 'cuda' if torch.cuda.is_available() else 'cpu'
print(device)  

#Utilise le GPU. Confirmez que cuda est sorti.

Téléchargez l'image MNIST et utilisez-la comme chargeur de données PyTorch. Préparez-vous à la formation et aux tests.

#Téléchargez l'image MNIST et faites-en un DataLoader (Train and Test)
from torchvision import datasets, transforms

batch_size_train = 512

train_loader = torch.utils.data.DataLoader(
    datasets.MNIST('.', train=True, download=True,
                   transform=transforms.Compose([
                       transforms.ToTensor(),
                   ])),
    batch_size=batch_size_train, shuffle=True, drop_last=True)
# drop_last n'est pas utilisé si le dernier mini-lot est plus petit que la taille spécifiée


test_loader = torch.utils.data.DataLoader(
    datasets.MNIST('.', train=False, transform=transforms.Compose([
        transforms.ToTensor(),
    ])),
    batch_size=1024, shuffle=False)

Vient ensuite le modèle d'apprentissage en profondeur IIC. C'est la même chose que l'apprentissage supervisé normal, mais il est plus lourd qu'un simple apprentissage supervisé afin d'acquérir un pouvoir expressif plus riche dans le réseau.

Et la couche de sortie finale est constituée de 10 types de classes que vous voulez espérer correspondre à 0-9, et séparément, une technologie appelée overclustring est également utilisée.

Cela le rend encore plus catégorisé que les 10 types attendus.

La couche de sortie finale sera la version de type 10 et la version de surclassement, et la fonction de perte calculera également la sortie des deux et utilisera la somme.

On s'attend à ce que les performances des 10 types de classification habituels soient améliorées si des changements infimes peuvent être capturés par le réseau surchargé.

Dans l'article IIC, cette couche de sortie est en outre multiplexée en tant que multi-tête. Cela permet d'éviter les pannes en fonction de la valeur initiale de la couche de sortie, mais Je l'ai omis car cela n'a pas beaucoup de sens pour moi et c'est difficile à mettre en œuvre.

#Modèle d'apprentissage profond
import torch.nn as nn
import torch.nn.functional as F

OVER_CLUSTRING_Rate = 10  #Préparez également l'overclsutering pour classer davantage


class NetIIC(nn.Module):
    def __init__(self):
        super(NetIIC, self).__init__()

        self.conv1 = nn.Conv2d(1, 128, 5, 2, bias=False)
        self.bn1 = nn.BatchNorm2d(128)
        self.conv2 = nn.Conv2d(128, 128, 5, 1, bias=False)
        self.bn2 = nn.BatchNorm2d(128)
        self.conv3 = nn.Conv2d(128, 128, 5, 1, bias=False)
        self.bn3 = nn.BatchNorm2d(128)
        self.conv4 = nn.Conv2d(128, 256, 4, 1, bias=False)
        self.bn4 = nn.BatchNorm2d(256)
        
        # 0-10 types de classes que vous souhaitez prendre en charge
        self.fc = nn.Linear(256, 10)

        # overclustering
        #En regroupant plus que l'hypothèse réelle, il sera possible de capturer des changements infimes dans le réseau.
        self.fc_overclustering = nn.Linear(256, 10*OVER_CLUSTRING_Rate)

    def forward(self, x):
        x = F.relu(self.bn1(self.conv1(x)))
        x = F.relu(self.bn2(self.conv2(x)))
        x = F.relu(self.bn3(self.conv3(x)))
        x = F.relu(self.bn4(self.conv4(x)))
        x_prefinal = x.view(x.size(0), -1)
        y = F.softmax(self.fc(x_prefinal), dim=1)

        y_overclustering = F.softmax(self.fc_overclustering(
            x_prefinal), dim=1)  # overclustering

        return y, y_overclustering

Définissez la fonction d'initialisation du poids du modèle.

import torch.nn.init as init


def weight_init(m):
    """Initialisation du poids"""
    if isinstance(m, nn.Conv2d):
        init.xavier_normal_(m.weight.data)
        if m.bias is not None:
            init.normal_(m.bias.data)
    elif isinstance(m, nn.BatchNorm2d):
        init.normal_(m.weight.data, mean=1, std=0.02)
        init.constant_(m.bias.data, 0)
    elif isinstance(m, nn.Linear):
        # Xavier
        #init.xavier_normal_(m.weight.data)

        # He 
        init.kaiming_normal_(m.weight.data)
        
        if m.bias is not None:
            init.normal_(m.bias.data)

Ensuite, définissez la transformation pour créer une image qui sera associée à l'image d'entrée. La transformation affine s'étire, puis ajoute du bruit à chaque pixel.

#Définition d'une fonction qui ajoute du bruit aux données
import torchvision as tv
import torchvision.transforms.functional as TF


def perturb_imagedata(x):
    y = x.clone()
    batch_size = x.size(0)

    #Effectuer une conversion affine aléatoire
    trans = tv.transforms.RandomAffine(15, (0.2, 0.2,), (0.2, 0.75,))
    for i in range(batch_size):
        y[i, 0] = TF.to_tensor(trans(TF.to_pil_image(y[i, 0])))

    #Ajoute du bruit
    noise = torch.randn(batch_size, 1, x.size(2), x.size(3))
    div = torch.randint(20, 30, (batch_size,),
                        dtype=torch.float32).view(batch_size, 1, 1, 1)
    y += noise / div

    return y

Et c'est le calcul de la quantité d'informations mutuelles, qui est la clé de l'IIC. Ce que nous faisons, c'est calculer la quantité d'informations mutuelles comme expliqué en 3.

Je veux maximiser la quantité d'informations mutuelles, mais pour en faire une perte, multipliez-la par moins et Je le remplace par un problème de minimisation.

Aussi, Méthode simple pour obtenir un taux de réponse correcte MNIST de 97% ou plus en apprenant sans enseignant (sans apprentissage par transfert) Un terme de coefficient est ajouté au calcul de la quantité d'informations mutuelles introduites dans, ce qui facilite la variation des classes.

L'article ci-dessus présente soigneusement l'implémentation dans TensorFlow2 et est fortement recommandé pour TensorFlow.

#Définition de la fonction de perte par IIS
#Référence: https://github.com/RuABraun/phone-clustering/blob/master/mnist_basic.py
import sys


def compute_joint(x_out, x_tf_out):

    # x_out、x_tf_c'est la torche.Size([512, 10]).. Multipliez ces deux pour trouver la distribution simultanée, torche.Size([2048, 10, 10])À.
    # torch.Size([512, 10, 1]) * torch.Size([512, 1, 10])
    p_i_j = x_out.unsqueeze(2) * x_tf_out.unsqueeze(1)
    # p_i_j est une torche.Size([512, 10, 10])

    #Ajouter tous les mini lots ⇒ torche.Size([10, 10])
    p_i_j = p_i_j.sum(dim=0)

    #Ajouter à la matrice transposée et diviser (symétrie) ⇒ torche.Size([10, 10])
    p_i_j = (p_i_j + p_i_j.t()) / 2.

    #Standardisation ⇒ torche.Size([10, 10])
    p_i_j = p_i_j / p_i_j.sum()

    return p_i_j
    #Après tout, p_i_j montre la table de distribution de probabilité de laquelle des 100 modèles tous les mini-lots étaient pour 100 modèles de 10 types de sortie de jugement d'image normale et 10 types de jugement d'image convertie.


def IID_loss(x_out, x_tf_out, EPS=sys.float_info.epsilon):
    # torch.Size([512, 10]), Les 10 derniers sont le nombre de classifications, donc 100 pour la suragrégation
    bs, k = x_out.size()
    p_i_j = compute_joint(x_out, x_tf_out)  # torch.Size([10, 10])

    #À partir de la table de distribution de probabilité simultanée, additionnez 10 modèles de l'image convertie et marginalisez-la pour créer une table de distribution de probabilité périphérique uniquement pour l'image d'origine
    p_i = p_i_j.sum(dim=1).view(k, 1).expand(k, k)
    #À partir de la table de distribution des probabilités simultanées, additionnez 10 motifs de l'image originale et marginalisez-les pour créer une table de distribution de probabilités périphériques uniquement pour l'image convertie.
    p_j = p_i_j.sum(dim=0).view(1, k).expand(k, k)

    #Évitez de saisir une valeur proche de 0 dans le journal car elle diverge.
    #p_i_j[(p_i_j < EPS).data] = EPS
    #p_j[(p_j < EPS).data] = EPS
    #p_i[(p_i < EPS).data] = EPS
    #L'implémentation de référence GitHub (↑) est PyTorch version 1.S'il est 3 ou plus, une erreur se produira.
    # https://discuss.pytorch.org/t/pytorch-1-3-showing-an-error-perhaps-for-loss-computed-from-paired-outputs/68790/3

    #Évitez de saisir une valeur proche de 0 dans le journal car elle diverge.
    p_i_j = torch.where(p_i_j < EPS, torch.tensor(
        [EPS], device=p_i_j.device), p_i_j)
    p_j = torch.where(p_j < EPS, torch.tensor([EPS], device=p_j.device), p_j)
    p_i = torch.where(p_i < EPS, torch.tensor([EPS], device=p_i.device), p_i)

    #Calculer la quantité d'informations mutuelles à partir de la probabilité simultanée de l'image originale et de l'image convertie et de la probabilité périphérique
    #Cependant, multipliez-le par moins pour en faire un problème de minimisation.
    """
Je veux maximiser la quantité d'informations mutuelles
⇒ Après tout, x_out, x_tf_Je souhaite que plus d'informations soient partagées par out
⇒ Le point est x_out, x_tf_Je veux être ensemble

    p_i_j est x_out, x_tf_Avec la distribution de probabilité simultanée de out, je suis heureux que le mini lot soit autant que possible, divers modèles de 10 × 10, uniformément uniformes
    
Première demi-section, torche.log(p_i_j)Est p_Si ij est proche de 1, il devient une grande valeur (proche de 0).
Si l'un d'entre eux est 1 et ne varie pas avec 0, log0 aura une petite valeur (grande valeur négative).
En d'autres termes, la première moitié du terme

Ce dernier terme est un terme qui calcule lequel des 10 types de l'image originale ou de l'image convertie sera marginalisé.
Si le premier demi-terme devient plus petit en soustrayant le motif marginalisé 10x10,
    x_out et x_tf_n'a pas partagé beaucoup d'informations.
    """
    # https://qiita.com/Amanokawa/items/0aa24bc396dd88fb7d2a
    #Ajouter un poids alpha en référence à
    #Petites pénalités dues à la variation du tableau de distribution de probabilité simultanée = Rendre la distribution de probabilité simultanée facile à varier
    alpha = 2.0  #Alpha est 1 pour les papiers et le calcul normal d'informations mutuelles

    loss = -1*(p_i_j * (torch.log(p_i_j) - alpha *
                        torch.log(p_j) - alpha*torch.log(p_i))).sum()

    return loss

Nous organiserons des formations.

#Mise en place de formations
total_epoch = 20


#modèle
model = NetIIC()
model.apply(weight_init)
model.to(device)

#Définir la fonction d'optimisation
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)


def train(total_epoch, model, train_loader, optimizer, device):

    model.train()
    scheduler = torch.optim.lr_scheduler.CosineAnnealingWarmRestarts(
        optimizer, T_0=2, T_mult=2)

    for epoch in range(total_epoch):
        for batch_idx, (data, target) in enumerate(train_loader):

            #Changement du taux d'apprentissage
            scheduler.step()

            #Créez des données subtilement converties. SIMULTANÉ_Faire une paire pour NUM
            data_perturb = perturb_imagedata(data)  #Faire du bruit

            #Envoyer si envoyé au GPU
            data = data.to(device)
            data_perturb = data_perturb.to(device)

            #Initialisation de la fonction d'optimisation
            optimizer.zero_grad()

            #Sortie de réseau neuronal
            output, output_overclustering = model(data)
            output_perturb, output_perturb_overclustering = model(data_perturb)

            #Calcul des pertes
            loss1 = IID_loss(output, output_perturb)
            loss2 = IID_loss(output_overclustering,
                             output_perturb_overclustering)
            loss = loss1 + loss2

            #Mis à jour pour réduire les pertes
            loss.backward()
            optimizer.step()

            #Sortie de journal
            if batch_idx % 10 == 0:
                print('Train Epoch {}:iter{} - \tLoss1: {:.6f}- \tLoss2: {:.6f}- \tLoss_total: {:.6f}'.format(
                    epoch, batch_idx, loss1.item(), loss2.item(), loss1.item()+loss2.item()))

    return model, optimizer


model_trained, optimizer = train(
    total_epoch, model, train_loader, optimizer, device)

Pendant l'entraînement, les redémarrages à chaud du recuit cosinus du planificateur sont utilisés pour modifier le taux d'apprentissage. Ce planificateur augmente ou réduit le taux d'apprentissage comme indiqué ci-dessous.

sgdr.jpg Figure: devis https://www.kaggle.com/c/imet-2019-fgvc6/discussion/94783

Lorsque le taux d'apprentissage diminue et augmente fortement, vous pouvez sortir de la solution locale et vous rapprocher des paramètres de la solution globale minimale.

Enfin, déduisez les données de test avec le modèle entraîné.

#Vérifiez les résultats du cluster de classification du modèle


def test(model, device, train_loader):
    model.eval()

    #Liste pour stocker les résultats
    out_targs = []
    ref_targs = []
    cnt = 0

    with torch.no_grad():
        for data, target in test_loader:
            cnt += 1
            data = data.to(device)
            target = target.to(device)
            outputs, outputs_overclustering = model(data)

            #Ajouter le résultat de la classification à la liste
            out_targs.append(outputs.argmax(dim=1).cpu())
            ref_targs.append(target.cpu())

    #Rassemblez la liste
    out_targs = torch.cat(out_targs)
    ref_targs = torch.cat(ref_targs)

    return out_targs.numpy(), ref_targs.numpy()


out_targs, ref_targs = test(model_trained, device, train_loader)

Enfin, trouvez le tableau des fréquences des résultats de sortie. L'axe vertical montre les étiquettes réelles de 0 à 9 et l'axe horizontal montre la classe qui a été jugée.

import numpy as np
import scipy.stats as stats

#Faire une matrice de confusion
matrix = np.zeros((10, 10))

#Créez une table de fréquences des classes jugées verticalement avec les nombres 0 à 9 et horizontalement
for i in range(len(out_targs)):
    row = ref_targs[i]
    col = out_targs[i]
    matrix[row][col] += 1

np.set_printoptions(suppress=True)
print(matrix)

Le résultat de sortie est

[[   1.  978.    1.    0.    0.    0.    0.    0.    0.    0.]
 [   1.    0.    4. 1110.    2.    0.    2.    0.   13.    3.]
 [   0.    5.    4.    0.    0.    0.    0.    0. 1023.    0.]
 [   0.    0.    2.    0.    0.    4.  962.    0.   39.    3.]
 [   1.    0.    0.    0.  960.    0.    0.   19.    1.    1.]
 [   1.    1.    0.    0.    0.  866.   17.    0.    3.    4.]
 [ 940.    7.    0.    0.    0.    3.    0.    0.    4.    4.]
 [   0.    0.  921.    1.    0.    0.    1.   92.   13.    0.]
 [   0.    6.    0.    0.    0.    2.    4.    2.    2.  958.]
 [   0.    4.   14.    0.    2.    7.   27.  949.    2.    4.]]

Par exemple, le nombre 0 est le premier de la classe à collecter 978. Si c'est le numéro 9, 949 pièces sont rassemblées à la 7ème place.

Si vous appliquez les mêmes nombres dans chaque classe estimée à chaque étiquette de réponse correcte,

#Toutes les données
total_num = matrix.sum().sum()
print(total_num)

#Chaque numéro est soigneusement divisé dans chaque classe.
#Par exemple, le nombre 0 est le premier de la classe à collecter 978. Si c'est le numéro 9, 949 pièces ont été collectées à la 7ème place.
#Par conséquent, si vous ajoutez les plus grandes, le nombre de bonnes réponses
correct_num_list = matrix.max(axis=0)
print(correct_num_list)
print(correct_num_list.sum())

print("Taux de réponse correct:", correct_num_list.sum()/total_num*100)

Et la sortie est

10000.0
[ 940.  978.  921. 1110.  960.  866.  962.  949. 1023.  958.]
9667.0
Taux de réponse correcte: 96.67

est. Le taux de réponse correcte était de 97%.

Le code d'implémentation "MNIST_IIC.ipynb" se trouve ici. Référentiel de code d'implémentation

à la fin

Nous avons introduit IIC (Invariant Information Clustering), qui est un apprentissage non supervisé qui utilise la maximisation des informations mutuelles.

L'idée d'assimiler des entrées similaires de la même image dans IIC est très similaire à l'apprentissage du contraste de SimCLR (A Simple Framework for Contrastive Learning of Visual Representations) dans le dernier article de Hinton et al.

Dans IIC lui-même, la quantité d'informations mutuelles n'apparaît que dans la fonction d'erreur, et l'écart entre le papier IIC et le cerveau biologique est assez grand.

Cependant, la quantité d'informations mutuelles peut également être exprimée par la quantité d'informations Calvac-Liber, et peut être étendue au principe d'énergie libre de Carl Friston (je pense).

● Explication du principe de l'énergie libre: Inférence de la perception, du comportement et des pensées des autres

IIC était un article et une méthode très intéressants. À l'avenir, j'espère que les progrès de l'apprentissage non supervisé et les progrès du cerveau et des neurosciences seront davantage intégrés.

Cette fois, j'ai réalisé IIC avec des données d'image, mais la prochaine fois j'écrirai un article sur ce qui se passe lorsque IIC est fait avec des données texte traitées par BERT (ici, universel pour les organismes avec un champ visuel appelé reconnaissance d'objet) C'est un résultat intéressant que la différence entre le mécanisme du cerveau cible et la propriété spécifique à l'homme du langage naturel devient remarquable).

Merci d'avoir lu ce qui précède.

[Clause de non-responsabilité] Cet article est l'opinion / la transmission de l'auteur, pas l'opinion officielle de l'entreprise à laquelle appartient l'auteur.

Recommended Posts

La relation entre la science du cerveau et l'apprentissage non supervisé. Maximisez la quantité d'informations MNIST: Google Colabratory (PyTorch)
[Explication de la mise en œuvre] Classer les actualités de livingoor par BERT japonais x apprentissage non supervisé (clustering de maximisation de la quantité d'informations): Google Colaboratory (PyTorch)
La relation subtile entre Gentoo et pip
Étude de la relation entre le prétraitement de la voix et la précision de la transcription dans l'API Google Cloud Speech