Cela fait environ six mois que je suis passé de TensorFlow à Pytorch, je vais donc résumer les bases. Cette fois, je voudrais me concentrer sur les trois points suivants.
Les modèles pré-formés actuellement disponibles sont:
Cliquez ici pour plus de détails
Lorsque vous utilisez le modèle entraîné dans ImageNet, procédez comme suit.
import torchvision
model = torchvision.models.alexnet(pretrained=True)
pretrained = True
, les poids entraînés dans ImageNet ne seront pas chargés.pretrained = False
.--Si vous souhaitez vérifier la structure du modèle, vous pouvez le vérifier avec print (model)
. Voici le résultat de l'exécution.
AlexNet(
(features): Sequential(
(0): Conv2d(3, 64, kernel_size=(11, 11), stride=(4, 4), padding=(2, 2))
(1): ReLU(inplace=True)
(2): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
(3): Conv2d(64, 192, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
(4): ReLU(inplace=True)
(5): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
(6): Conv2d(192, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(7): ReLU(inplace=True)
(8): Conv2d(384, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(9): ReLU(inplace=True)
(10): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(11): ReLU(inplace=True)
(12): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(avgpool): AdaptiveAvgPool2d(output_size=(6, 6))
(classifier): Sequential(
(0): Dropout(p=0.5, inplace=False)
(1): Linear(in_features=9216, out_features=4096, bias=True)
(2): ReLU(inplace=True)
(3): Dropout(p=0.5, inplace=False)
(4): Linear(in_features=4096, out_features=4096, bias=True)
(5): ReLU(inplace=True)
(6): Linear(in_features=4096, out_features=1000, bias=True)
)
)
Si vous souhaitez classer par vos propres données, modifiez comme suit. Prenons l'exemple de la classification à deux classes.
model.classifier[6].out_features = 2
Si vous exécutez à nouveau print (model)
, vous pouvez voir qu'il a changé.
AlexNet(
(features): Sequential(
(0): Conv2d(3, 64, kernel_size=(11, 11), stride=(4, 4), padding=(2, 2))
(1): ReLU(inplace=True)
(2): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
(3): Conv2d(64, 192, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
(4): ReLU(inplace=True)
(5): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
(6): Conv2d(192, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(7): ReLU(inplace=True)
(8): Conv2d(384, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(9): ReLU(inplace=True)
(10): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(11): ReLU(inplace=True)
(12): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(avgpool): AdaptiveAvgPool2d(output_size=(6, 6))
(classifier): Sequential(
(0): Dropout(p=0.5, inplace=False)
(1): Linear(in_features=9216, out_features=4096, bias=True)
(2): ReLU(inplace=True)
(3): Dropout(p=0.5, inplace=False)
(4): Linear(in_features=4096, out_features=4096, bias=True)
(5): ReLU(inplace=True)
(6): Linear(in_features=4096, out_features=2, bias=True)
)
)
Passons maintenant au sujet principal. Cette fois, nous allons implémenter 1D CNN avec scratch. Voici un exemple simple.
import torch
import torch.nn as nn
class Net1D(nn.Module):
def __init__(self):
super(SimpleNet,self).__init__()
self.conv1 = nn.Conv1d(1, 8,kernel_size=3, stride=1)
self.bn1 = nn.BatchNorm1d(8)
self.relu = nn.ReLU()
self.maxpool = nn.MaxPool1d(kernel_size=3, stride=2)
self.conv2 = nn.Conv1d(8, 16,kernel_size=3, stride=1)
self.bn2 = nn.BatchNorm1d(16)
self.conv3 = nn.Conv1d(16,64,kernel_size=3, stride=1)
self.gap = nn.AdaptiveAvgPool1d(1)
self.fc = nn.Linear(64,2)
def forward(self,x):
x = self.conv1(x)
x = self.bn1(x)
x = self.relu(x)
x = self.maxpool(x)
x = self.conv2(x)
x = self.bn2(x)
x = self.relu(x)
x = self.maxpool(x)
x = self.conv3(x)
x = self.gap(x)
x = x.view(x.size(0),-1)
x = self.fc(x)
return x
Si vous voulez voir si ce modèle fonctionne, essayez ce qui suit:
model = SimpleNet()
in_data = torch.randn(8,1,50)
out_data = model(data)
print(out_size.size()) #torch.Size([8, 2])
--Préparez les données d'entrée appropriées avec torch.randn ()
. ← Cette méthode est pratique! Il peut également être appliqué en 2D!
L'entrée est torch.randn (taille du lot, nombre de canaux, taille du tableau unidimensionnel)
.
La taille de la sortie est «torch.Size ([8, 2])», ce qui signifie «torch.Size (taille du lot, dernière sortie)».
--Si vous souhaitez effectuer une tâche de classification, vous pouvez le faire via softmax après cela.
De plus, il existe une bibliothèque pratique appelée résumé de la torche
qui vous permet de vérifier la taille de la carte des caractéristiques, veuillez donc l'utiliser également. J'ai écrit un article avant, donc je publierai un lien.
===============================================================
===============================================================
【nn.Conv1d】
nn.Conv1d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')
parameters | Aperçu |
---|---|
in_channels | Nombre de canaux d'entrée. |
out_channels | Nombre de canaux après convolution. Nombre de filtres. |
kernel_size | La taille du noyau. |
stride | De combien déplacer le noyau. |
padding | La taille du rembourrage. Si 1 est spécifié, il sera inséré aux deux extrémités, donc il sera augmenté de 2. La valeur par défaut est 0. |
dilation | Modifiez l'espace entre les filtres. Utilisé dans atrous conv, etc. |
groups | La valeur par défaut est 1. L'augmentation du nombre réduit le coût du calcul. |
bias | S'il faut inclure les préjugés. La valeur par défaut est True |
padding_mode | Mode de remplissage. La valeur par défaut est 0. |
【nn.BatchNorm1d】
nn.BatchNorm1d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
Il est possible de saisir le même nombre de «num_features» que la valeur de «out_channels» de la couche précédente.
J'ai écrit un simple échantillon CNN. Cette fois, le nombre de filtres et la taille du noyau sont décidés de manière appropriée. Si vous créez votre propre réseau, tenez compte des valeurs au moment de décider.
import torch
import torch.nn as nn
class Net2D(nn.Module):
def __init__(self):
super(Net,self).__init__()
self.conv1 = nn.Conv2d(3,16,kernel_size=3,stride=2)
self.bn1 = nn.BatchNorm2d(16)
self.relu = nn.ReLU()
self.maxpool = nn.MaxPool2d(2)
self.conv2 = nn.Conv2d(16,32,kernel_size=3,stride=2)
self.bn2 = nn.BatchNorm2d(32)
self.conv3 = nn.Conv2d(32,64,kernel_size=3,stride=2)
self.gap = nn.AdaptiveAvgPool2d(1)
self.fc1 = nn.Linear(64,32)
self.fc2 = nn.Linear(32,2)
def forward(self,x):
x = self.conv1(x)
x = self.bn1(x)
x = self.relu(x)
x = self.maxpool(x)
x = self.conv2(x)
x = self.bn2(x)
x = self.relu(x)
x = self.maxpool(x)
x = self.conv3(x)
x = self.gap(x)
x = x.view(x.size(0),-1)
x = self.fc1(x)
x = self.fc2(x)
return x
nn.Module
.. Je vois souvent des articles qui définissent ʻinit
pour ceux avec des paramètres et forward
pour ceux sans paramètres, mais relu etc. ne sont pas affichés quand print (model)
, donc j'ai des paramètres Même quelque chose comme no relu est défini dans ʻinit` comme cette fois.--forward
détermine la structure du modèle.
【nn.Conv2d】
nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')
parameters | Aperçu |
---|---|
in_channels | Nombre de canaux d'entrée. Il devient 3 dans l'image RVB. |
out_channels | Nombre de canaux après convolution. Nombre de filtres. |
kernel_size | La taille du noyau. |
stride | De combien déplacer le noyau. |
padding | La taille du rembourrage. Si 1 est spécifié, il sera inséré aux deux extrémités, donc il sera augmenté de 2. La valeur par défaut est 0. |
dilation | Modifiez l'espace entre les filtres. Utilisé dans atrous conv, etc. |
groups | La valeur par défaut est 1. L'augmentation du nombre réduit le coût du calcul. |
bias | S'il faut inclure les préjugés. La valeur par défaut est True |
padding_mode | Mode de remplissage. La valeur par défaut est 0. |
【nn.BatchNorm2d】
nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
--Il y a aussi Layer Norm
, ʻInstance Norm,
Group Norm`, etc.
【nn.ReLU】
nn.ReLU(inplace=False)
【nn.MaxPool2d】
nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
Utilisez une couche de regroupement pour mettre en valeur les caractéristiques.
――Il y a environ deux modèles, alors vérifiez ci-dessous.
① Lorsque la taille de la piscine est carrée
m = nn.MaxPool2d(3, stride=2) #(pool of square window of size=3, stride=2)
② Lorsque vous souhaitez personnaliser la taille de la piscine
m = nn.MaxPool2d((3, 2), stride=(2, 1)) #(pool of non-square window)
【nn.AdaptiveMaxPool2d】
nn.AdaptiveMaxPool2d(output_size, return_indices=False)
Souvent appelé «Global Max Pooling».
Il est souvent utilisé avant de se connecter à une couche entièrement connectée, car il fait de chaque canal une valeur unique.
Mettez la taille de sortie d'un canal dans ʻoutput_size. Je pense que ʻoutput_size = 1
est souvent utilisé.
【nn.Linear】
nn.Linear(in_features, out_features, bias=True)
Spécifiez les fonctionnalités in_features et out_features à utiliser. Utilisez-le lors de la mise en œuvre d'une couche entièrement connectée.
Cela fait environ six mois que j'ai déménagé à Pytorch et c'est très facile à utiliser. J'espère que cet article vous sera utile.
Recommended Posts