[PYTHON] [Détails (?)] Introduction au pytorch ~ CNN de CIFAR10 ~

1.Tout d'abord

pytorch Une introduction au pytorch par des débutants.

Lorsque vous utilisez un tel nouveau cadre, je pense que le meilleur raccourci est de regarder l'exemple et de rechercher sur Google les fonctions utilisées, de lire le document ou de jouer avec, donc c'est un mémo.

Si vous essayez de vous familiariser avec pytorch de la même manière, cet article vous fera gagner du temps. (Je suis content si tu le deviens.)

Donc, dans le code de cifar10-tutorial faisant CNN avec CIFAR10 Le décodage ou le travail sur Google est terminé.

2. Préparer l'environnement

2.1. Environnement

2.2. Installation

L'installation de pytorch est super simple, et si vous cliquez sur votre environnement sur le site officiel, le code d'installation sera affiché. Dans le cas de mon environnement, c'était comme suit.

http://pytorch.org/ Screen Shot 2017-09-06 at 22.59.46.png

pip install http://download.pytorch.org/whl/cu80/torch-0.2.0.post3-cp36-cp36m-manylinux1_x86_64.whl 
pip install torchvision

3. Chargement et préparation des données

Jetons d'abord un œil à ce code qui charge et prépare les données.

import torch
import torchvision
import torchvision.transforms as transforms

transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
                                        download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2)

testset = torchvision.datasets.CIFAR10(root='./data', train=False,download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4,shuffle=False, num_workers=2)

classes = ('plane', 'car', 'bird', 'cat',
           'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

3.1 Qu'est-ce que la vision de la torche?

torchvision est un package pour la vision par ordinateur de pytorch, et il semble qu'il contienne des fonctions de chargement de données et de prétraitement. ..

3.2. Préparation des données

Utilisez transforms.Compose pour configurer la fonction de prétraitement à exécuter après le chargement des données.

Comme son nom l'indique, «ToTensor ()» change le type de données en un tenseur appelé «torch.Tensor» défini par pytorch.

Puisque l'argument de transforms.Normalize est torch.Tensor, les fonctions seront exécutées dans l'ordre à partir du début de la liste.

[`` transforms.Normalize ((0.5, 0.5, 0.5), (0.5, 0.5, 0.5) `](http://pytorch.org/docs/master/torchvision/transforms.html#torchvision.transforms. Dans Normaliser), le premier taple de l'argument représente la moyenne de chaque canal RVB et le second taple représente l'écart type. Normaliser en fonction de ces moyennes et écarts types.

En d'autres termes

transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

Vous avez maintenant une fonction qui transforme les données en un type de tenseur pour pytorch et effectue la normalisation.

3.3 Torchvision.datasets Qu'est-ce que CIFAR10?

`` `Torchvision.datasets.CIFAR10``` est une classe de chargement de données CIFAR10 comme son nom l'indique.

Si download = True, enregistrez les données à l'emplacement racine.

Pour MNIST et CIFAR10, les ensembles de données sont déjà divisés en formation et test. (Je pense que vous pouvez le mélanger et le diviser vous-même)

Dans CIFAR10, il y a 60000 images, dont 50000 pour la formation et 10000 pour les tests. Lorsque train = True est défini, 50000, qui est censé être utilisé pour l'entraînement à l'avance, est chargé, et lorsque train = False, 10000 données de test sont chargées.

Si vous passez une série de flux de prétraitement créés avec transforms.Compose avec l'argument transform, le prétraitement passé après le chargement sera exécuté.

3.4. Qu'est-ce que Data Loader?

DataLoader place sampler sur l'ensemble de données chargé. /_modules/torch/utils/data/sampler.html) Il s'agit d'une classe, qui est un objet d'échantillonnage de données. Si vous le vérifiez, l'échantillonneur est certainement attaché.

trainloader.sampler
# <torch.utils.data.sampler.RandomSampler at 0x7f9099e13ef0>

sampler avait apparemment un échantillonnage aléatoire, un échantillonnage séquentiel, un échantillonnage pondéré, etc. ..

Il y a un échantillonneur dans l'argument de DataLoader, donc si vous passez l'échantillonneur que vous avez défini ici J'ai un bon pressentiment, alors essayons-le.

Ici, afin de rendre le résultat facile à comprendre, nous pondérerons et n'échantillonnerons qu'une seule donnée. Étant donné que le nombre de données est petit et facile, je vais l'essayer avec des données de test.

import numpy as np

#Créez un vecteur de poids de 1 pour une seule image.
weights = np.zeros(10000) #Le nombre de données de test est de 10000
weights[300] = 1. #300 convient
num_samples = 4 #Nombre d'échantillons

#Essayez WeightedRandomSampler.
my_sampler = torch.utils.data.sampler.WeightedRandomSampler(weights, num_samples, replacement=True)
my_testloader = torch.utils.data.DataLoader(testset, batch_size=4,shuffle=False, num_workers=2, sampler=my_sampler)

my_testiter = iter(my_testloader)
images, labels = my_testiter.next()

#La fonction imshow sera expliquée par la suite, mais je l'utiliserai un peu plus tôt.
def imshow(img):
    img = img / 2 + 0.5     # unnormalize
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1, 2, 0)))

imshow(torchvision.utils.make_grid(images))

fig2.png

Oh, c'est juste une grenouille.

3.5. Graphique d'image

import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline

# functions to show an image
def imshow(img):
    img = img / 2 + 0.5     # unnormalize
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1, 2, 0)))

# get some random training images
dataiter = iter(trainloader)
images, labels = dataiter.next()

# show images
imshow(torchvision.utils.make_grid(images))
# print labels
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))

fig1.png

3.6 Qu'est-ce qui est anormal?

img = img / 2 + 0.Il y a une non-normalisation dans le commentaire de la 5ème partie, mais je pense que la non-normalisation est un peu trompeuse. On dit que c'est normalisé.



 Puisque l'entrée de [plt.imshow](https://matplotlib.org/devdocs/api/_as_gen/matplotlib.pyplot.imshow.html) est [0,1], elle est décalée en conséquence.

## 3.7. Qu'est-ce que img.numpy ()?

```python
type(img) # torch.FloatTensor

torch.Tensor est le type de tenseur manipulé par pytorch et est nommé "type de données d'élément + Tensor". .. Dans ce cas, puisqu'il s'agit d'un Float Tensor, il s'agit d'un float, c'est-à-dire d'une virgule flottante 32 bits.

Soit le ndarray retourné dans `` `Document``` et le tenseur d'origine partagent la même zone. Si vous le modifiez, l'autre sera également modifié.

Vérifions-le.

a = torch.FloatTensor([1])
b = a.numpy()

#Changer ndarray
b[0] = 2

#Le tenseur d'origine est également 2.
print("original tensor: ", a) # original tensor: 2
print("ndarray : ", b) # ndarray :  [ 2.]

#Il fait référence à une autre zone de mémoire.
print(id(a)) # 140024484781832
print(id(b)) # 140024044621056

Oh, les changements de ndarray sont également reflétés dans le tenseur d'origine. Puisque les zones de mémoire réservées sont différentes, il semble qu'elles fonctionnent comme si elles partageaient virtuellement la même zone en conservant les mêmes valeurs.

3.8. Qu'est-ce que plt.imshow (np.transpose (npimg, (1, 2, 0)))?

npimg = img.numpy()
npimg2 = np.transpose(npimg, (1, 2, 0))

print(npimg.shape) # (3, 36, 138)
print(npimg2.shape) # (36, 138, 3)

En regardant la documentation, les arguments pour plt.imshow sont alignés comme (n, m, RGB). Doit être. Puisque npimg est à l'origine aligné avec (RVB, vertical, horizontal), il est trié dans l'ordre du deuxième argument de `` np.transpose ''.

3.9 Qu'est-ce que dataiter = iter (trainloader)?

dataiter = iter(trainloader)

print(type(trainloader))
# <class 'torch.utils.data.dataloader.DataLoader'>

print(type(dataiter))
# <class 'torch.utils.data.dataloader.DataLoaderIter'>

Le __iter__ défini dans DataLoader est appelé par iter () et renvoie DataLoaderIter.

Contrairement à un itérateur normal, vous devez passer les données par incréments de batch_size, il semble donc qu'ils aient défini un itérateur dédié. (Code)

En conséquence, chaque fois que vous appelez dataiter.next (), le nième lot, le n + 1ème lot et les données répétées seront acquis.

3.10. Qu'est-ce que make_grid?

img = torchvision.utils.make_grid(images)
print(type(images)) # <class 'torch.FloatTensor'>
print(images.size) # torch.Size([4, 3, 32, 32])
print(type(img)) # <class 'torch.FloatTensor'>
print(img.size) # torch.Size([3, 36, 138])

La documentation est torchvision.utils.make_grid.

La fonction make_grid organise plusieurs images côte à côte. L'argument de make_grid est un tenseur à 4 dimensions, tandis que la valeur de retour est un tenseur à 3 dimensions. L'argument tenseur était un tenseur à 4 dimensions de [nombre d'images, RVB, vertical, horizontal], mais la dimension du nombre d'images a disparu.

Et comme le dit la documentation, par défaut padding = 2```, donc 2 sont ajoutés au-dessus et en dessous à 36, et 2 est ajouté entre chaque image et aux deux extrémités, 32 * n + 2 * (n + 1) = 138 (n = 4) En d'autres termes, 32 vaut 138 pour l'horizontale.

4. Définition du modèle

Jetons un coup d'œil à ce code.

from torch.autograd import Variable
import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16 * 5 * 5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x


net = Net()

4.1 Qu'est-ce qu'une variable?

Variable enveloppe torch.Tensor pour qu'il puisse contenir des données de gradient, etc. ..

Variable encapsule un tenseur, donc une étape est nécessaire lorsque vous souhaitez voir les données contenues dans Variable.

a = torch.FloatTensor([1.])
a2 = Variable(a)

print(type(a)) # <class 'torch.FloatTensor'>
print(type(a2)) # <class 'torch.autograd.variable.Variable'>
print(type(a2.data)) # <class 'torch.FloatTensor'>

print(a.numpy()) # [ 1.]
print(a2.data.numpy()) # [ 1.]

Comme indiqué ci-dessus, le tenseur est stocké dans «.data». (Référence)

À propos, les informations sur le gradient sont

print(a2.grad) # None

Il est enregistré ici. Il n'y a rien pour le moment, donc Aucun n'est inclus. Il semble que seuls "Aucun" ou "Variable" sont acceptés.

a2.grad = Variable(torch.FloatTensor([100]))
print(a2.grad) # Variable containing: 100

Je pense que c'est une bonne idée de le remplacer comme ça au verso. Et le fait que seule Variable soit acceptée signifie que les informations de gradient y seront également stockées.

a2.grad.grad =  Variable(torch.FloatTensor([200]))
print(a2.grad.grad) # Variable containing: 200

Le dérivé supérieur est-il falsifié de cette manière? c'est intéressant.

4.2. Qu'est-ce que nn.Module?

class Net(nn.Module):

nn.Module La classe est une classe de base, et forward etc. sont définis ici, et lors de la création d'un modèle Il hérite de cela. (En fait, quelque chose de concret n'est pas défini dans forward, et il semble que l'on suppose qu'il sera attribué après l'héritage.)

4.3. Qu'est-ce que nn.Conv2d?

L'argument de nn.Conv2d est À partir de la gauche, le nombre de canaux d'entrée, le nombre de canaux de sortie et la taille du noyau.

Au moment de la définition de ce modèle, une valeur aléatoire proche de 0 est placée dans le filtre, qui est un paramètre de la couche de convolution, et elle est préparée. Cela peut être confirmé comme suit.

conv1 = nn.Conv2d(3, 6, 5)
print(conv1.weight)

Parameter containing:
(0 ,0 ,.,.) = 
 -0.0011 -0.1120  0.0351 -0.0488  0.0323
 -0.0529 -0.0126  0.1139 -0.0234 -0.0729
  0.0384 -0.0263 -0.0903  0.1065  0.0702
  0.0087 -0.0492  0.0519  0.0254 -0.0941
  0.0351 -0.0556 -0.0279 -0.0641 -0.0790

(0 ,1 ,.,.) = 
 -0.0738  0.0853  0.0817 -0.1121  0.0463
 -0.0266  0.0360  0.0215 -0.0997 -0.0559
  0.0441 -0.0151  0.0309 -0.0026  0.0167
 -0.0534  0.0699 -0.0295 -0.1043 -0.0614
 -0.0820 -0.0549 -0.0654 -0.1144  0.0049
 ...
 [torch.FloatTensor of size 6x3x5x5]

Puisque la taille du noyau est définie sur 5, le tenseur (nombre de canaux de sortie, RVB, taille du noyau, taille du noyau) est préparé. Au fait,

conv1 = nn.Conv2d(3, 6, (5,1))
print(conv1.weight)

Parameter containing:
(0 ,0 ,.,.) = 
  0.2339
 -0.0756
  0.0604
 -0.0185
 -0.0975
 ...

Il semble que vous puissiez faire autre chose que le carré.

En outre, ce paramètre est

type(conv1.weight)
# torch.nn.parameter.Parameter

Il est défini par l'objet Parameter comme celui-ci, et il s'agit d'une sous-classe de Variable, et cela ressemble à un rapide coup d'œil. , La fonction d'affichage est définie, et si elle est Variable, elle sera affichée comme Variable contenant, mais dans Paramètre, elle sera affichée comme Paramètre contenant:.

4.4. Qu'est-ce que nn.MaxPool2d?

nn.MaxPool2d est la couche de regroupement MAX. Les principaux arguments utilisés sont kernel_size, stride et padding.

Alors, plions et regroupons MAX l'image adaptative et voyons comment elle est convertie.

images, labels = dataiter.next()
print(images.size())
print(type(images))
image_plot = images[0][1].numpy()
plt.imshow(image_plot, cmap='Greys', interpolation='nearest')
plt.show()

#Définition du modèle
img_input = Variable(images)
conv = nn.Conv2d(3, 1, 3, padding=1)
pool = nn.MaxPool2d(3, padding=1, stride=1)

#vers l'avant
conv_output = conv(img_input)
pool_output = pool(conv_output)
print(pool_output.size())

#terrain
conv_plot = conv_output[0][0].data.numpy()
conv_plot 
plt.imshow(conv_plot, cmap='Greys', interpolation='nearest')
plt.show()

pool_plot = pool_output[0][0].data.numpy()
plt.imshow(pool_plot, cmap='Greys', interpolation='nearest')
plt.show()

--Image originale fig3.png C'est un cheval.

-Image après pliage fig4.png Ici, comme la convolution n'a pas encore appris les paramètres du filtre, c'est un paramètre aléatoire proche de 0, et tous ont la même valeur, il semble donc qu'il n'y ait pas beaucoup de différence.

-Image après pliage et mise en commun MAX fig5.png Vous pouvez voir que le pool MAX a un 3 * 3 MAX et est flou.

4.5. Définition de la fonction objectif et définition de la méthode d'optimisation

Ensuite, jetez un œil à ce code.

import torch.optim as optim

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

4.6. Qu'est-ce que nn.CrossEntropyLoss ()?

nn.CrossEntropyLoss () définit un objet comme étant la fonction objectif.

4.7. Qu'est-ce qu'optim.SGD?

`` `torch.optim``` définit divers algorithmes d'optimisation. SGD, Adam, etc.

Parmi les algorithmes d'optimisation définis dans torch.optim, ici optim.SGD est utilisé. Je vais.

Nous transmettons net.parameters () comme argument à ʻoptim.SGD. net.parameters () semble renvoyer les paramètres définis dans le modèle (torch.nn.parameter.Parameter`) en tant que générateur.

type(net.parameters())
# generator

type(net.parameters().__next__())
# torch.nn.parameter.Parameter

print(net.parameters().__next__())

Parameter containing:
(0 ,0 ,.,.) = 
 -0.0998  0.0035 -0.0438 -0.1150 -0.0435
  0.0310 -0.0750 -0.0405 -0.0745 -0.1095
 -0.0355  0.0065 -0.0225  0.0729 -0.1114
  0.0708 -0.0170 -0.0253  0.1060  0.0557
  0.1057  0.0873  0.0793 -0.0309 -0.0861
  ...

Si vous vérifiez l'objet détenu par l'optimiseur,

optimizer.__dict__

{'param_groups': [{'dampening': 0,
   'lr': 0.001,
   'momentum': 0.9,
   'nesterov': False,
   'params': [Parameter containing:
    (0 ,0 ,.,.) = 
      0.0380 -0.1152  0.0761  0.0964 -0.0555
     -0.0325 -0.0455 -0.0755  0.0413 -0.0589
      0.0116  0.1136 -0.0992 -0.1149 -0.0414
     -0.0611  0.0827 -0.0906  0.0631  0.0170
      0.0903 -0.0816 -0.0690  0.0470 -0.0578
  ...

net.parameters () conserve tous les paramètres inclus dans le modèle, y compris mes paramètres.

5. Formation sur modèle

Jetons un œil au [code] pour la formation (http://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html#train-the-network).

for epoch in range(2):  # loop over the dataset multiple times

    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        #Le deuxième argument est la position de départ, qui est 0, donc énumérer(trainloader)Pareil que
        # https://docs.python.org/3/library/functions.html#enumerate
        
        # get the inputs
        inputs, labels = data

        # wrap them in Variable
        inputs, labels = Variable(inputs), Variable(labels)

        # zero the parameter gradients
        optimizer.zero_grad()

        # forward + backward + optimize
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        # print statistics
        running_loss += loss.data[0]
        if i % 2000 == 1999:    # print every 2000 mini-batches
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

print('Finished Training')

5.1. Qu'est-ce que optimizer.zero_grad ()?

Comme nous l'avons confirmé précédemment, optimizer contient tous les paramètres.

ʻOptimizer.zero_grad () ` initialise le grad de ces variables conservées. Il semble. Je pense que tout est Aucun.

5.2 Qu'est-ce que les sorties = net (entrées)?

outputs = net(inputs)

print(type(outputs))
# <class 'torch.autograd.variable.Variable'>

print(outputs.size())
# torch.Size([4, 10])

outputs
Variable containing:
-2.4825 -4.4286  2.2041  3.4353  2.0734  2.8198  1.9374  0.7751 -2.6798 -3.1932
-1.7512 -4.6657  2.7911  3.9570  0.7931  5.9005 -0.8023  2.9664 -4.3328 -3.2921
 2.4015  2.8962  0.9330 -1.2107 -0.0525 -2.2119 -1.2474 -2.6026 -0.1120  0.4869
-1.3042 -2.7538  1.0985 -0.2462  3.7435  1.1724 -1.4233  6.6892 -3.8201 -2.3132
[torch.FloatTensor of size 4x10]

En le passant à net, vous pouvez voir que la sortie finale via la fonction objectif est renvoyée.

5.3 Qu'est-ce que perte = critère (sorties, étiquettes)?

Le commentaire dit avant + arrière + optimiser, mais je ne vois pas la méthode avant.

C'est en fait parce que CrossEntropyLoss appelle en avant avec call, ce qui signifie

loss = criterion(outputs, labels)
loss = criterion.forward(outputs, labels)

Les deux font la même chose. Donc «perte = critère (sorties, étiquettes)» est en avant.

5.4. Qu'est-ce que loss.backward ()?

loss est un objet Variable.

type(loss)
# torch.autograd.variable.Variable

Variable.backward () se trouve à l'intérieur de cette [torch.autograd.backward ()](http: / /pytorch.org/docs/master/autograd.html#torch.autograd.backward) est appelée.

Ensuite, ce que fait ce «.backward ()» est de trouver le coefficient différentiel du paramètre contenu dans la fonction objectif. Essayons avec un exemple simple.

x = torch.autograd.Variable(torch.Tensor([3,4]), requires_grad=True)
# requires_grad=Vrai, vous dit que cette variable va différencier

print("x.grad : ", x.grad)
# None
#À ce stade, rien n'y est encore.

#Créez une fonction objective de manière appropriée.
y = x[0]**2 + 5*x[1]  + x[0]*x[1]
# x[0]Dérivé de: 2*x[0] + x[1]
# x[0]Coefficient différentiel de: 2*3 + 4 = 10
# x[1]Dérivé de: 5 + x[0]
# x[1]Coefficient différentiel de: 5 + 3 = 8

y.backward()
# torch.autograd.backward(y)Mais c'est d'accord.

print("x.grad : ", x.grad)
# 10
# 8

# .zero_grad()au lieu de
x.grad = None

C'est le coefficient différentiel de la fonction objectif «y» au point de données d'entrée. Il convient de noter ici que vers l'arrière concerne la fonction de perte, donc y vers l'arrière doit être un scalaire.

Par exemple

y = x
y.backward()

# RuntimeError: grad can be implicitly created only for scalar outputs

Ensuite, je me fâche d'en faire un scalaire.

5.5. Qu'est-ce que optimizer.step ()?

.step () met à jour les paramètres en fonction du gradient calculé par .backward () Le fera. Regardons ça.

optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()

print(net.parameters().__next__())
Parameter containing:
(0 ,0 ,.,.) = 
 -0.0839  0.1434 -0.0371 -0.1394 -0.0277

Après l'avoir exécuté plusieurs fois (bien qu'il soit optimisé avec les mêmes données)

print(net.parameters().__next__())
Parameter containing:
(0 ,0 ,.,.) = 
 -0.0834  0.1436 -0.0371 -0.1389 -0.0276

Et ainsi, les paramètres sont mis à jour petit à petit.

6. Validez

Prédisez le modèle pour les données de test. Ce code.

correct = 0
total = 0
for data in testloader:
    images, labels = data
    outputs = net(Variable(images))
    _, predicted = torch.max(outputs.data, 1)
    total += labels.size(0)
    correct += (predicted == labels).sum()

print('Accuracy of the network on the 10000 test images: %d %%' % (
    100 * correct / total))
class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
for data in testloader:
    images, labels = data
    #print("images type : ", type(images))
    #print("images.shape : ", images.shape)
    outputs = net(Variable(images))
    _, predicted = torch.max(outputs.data, 1)
    c = (predicted == labels).squeeze()
    for i in range(4):
        label = labels[i]
        class_correct[label] += c[i]
        class_total[label] += 1


for i in range(10):
    print('Accuracy of %5s : %2d %%' % (
        classes[i], 100 * class_correct[i] / class_total[i]))

# Accuracy of plane : 51 %
# Accuracy of   car : 54 %
# Accuracy of  bird : 53 %
# Accuracy of   cat : 33 %
# Accuracy of  deer : 41 %
# Accuracy of   dog : 50 %
# Accuracy of  frog : 54 %
# Accuracy of horse : 65 %
# Accuracy of  ship : 70 %
# Accuracy of truck : 67 %

6.1. Qu'est-ce que .squeeze ()?

Est-ce le seul que je ne connaisse pas? torch.squeeze Dans la dimension du tenseur, effacez celui de 1. Il semble que presser signifie presser.

7. À la fin

7.1. Quelque chose d'utile

Vous pouvez trouver de quel type de modèle il s'agit en regardant ~~ net.parameters. ~~ (Corrigé le 27 octobre 2017)

Puisque le __repr__ de nn.Module est défini de sorte que le modèle soit affiché de manière facile à lire, vous pouvez approximativement comprendre de quel type de modèle il s'agit comme suit.

In [22]: net
Out[22]:
Net (
  (conv1): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
  (pool): MaxPool2d (size=(2, 2), stride=(2, 2), dilation=(1, 1))
  (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
  (fc1): Linear (400 -> 120)
  (fc2): Linear (120 -> 84)
  (fc3): Linear (84 -> 10)
)

7.2. Impressions

Recommended Posts

[Détails (?)] Introduction au pytorch ~ CNN de CIFAR10 ~
Introduction à Lightning Pytorch
Introduction à PyTorch (1) Différenciation automatique
[Introduction à Pytorch] J'ai essayé de catégoriser Cifar10 avec VGG16 ♬
Introduction à l'apprentissage profond ~ Expérience CNN ~
[PyTorch] Introduction à la classification de documents à l'aide de BERT
[Introduction à Pytorch] J'ai joué avec sinGAN ♬
Introduction à MQTT (Introduction)
Introduction à Scrapy (1)
Introduction à Scrapy (3)
Premiers pas avec Supervisor
Introduction à Tkinter 1: Introduction
pytorch super introduction
Introduction à PyQt
Introduction à Scrapy (2)
[Linux] Introduction à Linux
Introduction à Scrapy (4)
Introduction à discord.py (2)
[Super introduction à l'apprentissage automatique] Découvrez les didacticiels Pytorch
[PyTorch] Introduction à la classification des documents japonais à l'aide de BERT
[Super introduction à l'apprentissage automatique] Découvrez les didacticiels Pytorch
Premiers pas avec le Web Scraping
Introduction aux baies non paramétriques
Introduction à EV3 / MicroPython
Introduction au langage Python
Introduction à la reconnaissance d'image TensorFlow
Introduction à OpenCV (python) - (2)
[Pytorch] numpy à tenseur
Introduction à PyQt4 Partie 1
Introduction à l'injection de dépendances
Introduction à Private Chainer
Introduction à PyTorch (environnement virtuel)
PyTorch Super Introduction Principes de base de PyTorch
Introduction à l'apprentissage automatique
[Introduction à Pytorch] Je souhaite générer des phrases dans des articles de presse
AOJ Introduction à la programmation Sujet 1, Sujet 2, Sujet 3, Sujet 4
Introduction au module de papier électronique
Introduction à l'algorithme de recherche de dictionnaire
Introduction à la méthode Monte Carlo
[PyTorch] Classification des images du CIFAR-10
[Mémorandum d'apprentissage] Introduction à vim
opencv-python Introduction au traitement d'image
Introduction à Python Django (2) Win
Introduction à l'écriture de Cython [Notes]
Introduction à Private TensorFlow
Une introduction à l'apprentissage automatique
[Introduction à cx_Oracle] Présentation de cx_Oracle
Une super introduction à Linux
AOJ Introduction à la programmation Sujet n ° 7, Sujet n ° 8
Introduction à la détection des anomalies 1 principes de base
Introduction à RDB avec sqlalchemy Ⅰ
[Introduction au système] Retracement de Fibonacci ♬
Introduction à l'optimisation non linéaire (I)
Introduction à la communication série [Python]
AOJ Introduction à la programmation Sujet n ° 5, Sujet n ° 6