PyTorch a implémenté un nouveau réseau neuronal, $ \ Pi $ -Net, proposé dans l'article suivant adopté pour CVPR2020.
Chrysos, Grigorios G., et al. "
Le code complet utilisé pour l'apprentissage se trouve sur GitHub.
Dans $ \ Pi $ -Net, le réseau est ramifié au milieu, et ** la multiplication est effectuée à l'endroit où il se joint à nouveau **. Cela représente la sortie comme un polynôme d'entrée.
Dans un réseau neuronal ordinaire, la sortie de chaque couche est rendue non linéaire en appliquant des fonctions d'activation telles que ReLU et Sigmoid. Sans la fonction d'activation, quel que soit le nombre de couches que vous augmentez le réseau, vous ne pouvez sortir que de manière linéaire vers l'entrée, ce qui n'a aucun sens.
Cependant, dans $ \ Pi $ -Net, la sortie de la couche intermédiaire est multipliée pour donner au réseau une non-linéarité, donc même si vous n'utilisez pas la fonction d'activation **, vous pouvez l'exprimer fortement en la rendant multicouche. Vous pouvez acquérir des capacités.
Plusieurs structures de réseau ont été proposées dans le document, mais cette fois nous les avons implémentées sur la base de l'une d'elles, la structure suivante.
(Extrait du journal)
Il y a Skip-connection et il a une structure comme ResNet, mais la partie où il se joint n'est pas l'addition mais la multiplication (produit adamar). Puisque la sortie du bloc précédent est au carré dans chaque bloc, en empilant des blocs $ N $, il devient un polypole de l'ordre de $ 2 ^ N $, et la puissance expressive du réseau augmente de façon exponentielle.
J'ai créé le modèle suivant en empilant 5 blocs dans la figure ci-dessus. Par conséquent, la sortie du réseau est représentée par un ordre polymorphe de $ 2 ^ 5 = 32 $. Notez que nous n'utilisons aucune fonction d'activation.
model
class PolyNet(nn.Module):
def __init__(self, in_channels=1, n_classes=10):
super().__init__()
N = 16
kwds1 = {"kernel_size": 4, "stride": 2, "padding": 1}
kwds2 = {"kernel_size": 2, "stride": 1, "padding": 0}
kwds3 = {"kernel_size": 3, "stride": 1, "padding": 1}
self.conv11 = nn.Conv2d(in_channels, N, **kwds3)
self.conv12 = nn.Conv2d(in_channels, N, **kwds3)
self.conv21 = nn.Conv2d(N, N * 2, **kwds1)
self.conv22 = nn.Conv2d(N, N * 2, **kwds1)
self.conv31 = nn.Conv2d(N * 2, N * 4, **kwds1)
self.conv32 = nn.Conv2d(N * 2, N * 4, **kwds1)
self.conv41 = nn.Conv2d(N * 4, N * 8, **kwds2)
self.conv42 = nn.Conv2d(N * 4, N * 8, **kwds2)
self.conv51 = nn.Conv2d(N * 8, N * 16, **kwds1)
self.conv52 = nn.Conv2d(N * 8, N * 16, **kwds1)
self.fc = nn.Linear(N * 16 * 3 * 3, n_classes)
def forward(self, x):
h = self.conv11(x) * self.conv12(x)
h = self.conv21(h) * self.conv22(h)
h = self.conv31(h) * self.conv32(h)
h = self.conv41(h) * self.conv42(h)
h = self.conv51(h) * self.conv52(h)
h = self.fc(h.flatten(start_dim=1))
return h
J'ai appris la classification du MNIST et du CIFAR-10.
MNIST Accuracy
Loss
Exactitude du test d'environ 99%!
CIFAR-10 Accuracy
Loss
Le test est précis à environ 70%, mais vous surapprenez ...
Puisque la sortie est une entrée polymorphe, nous avons pu apprendre sans utiliser la fonction d'activation.
Comme mentionné ci-dessus, l'expressivité s'améliore de façon exponentielle en empilant des blocs, On sait que même les réseaux de neurones ordinaires améliorent leur expressivité de manière exponentielle par rapport au nombre de couches [^ 1], donc honnêtement, je n'ai pas vraiment compris les avantages de $ \ Pi $ -Net ...
Recommended Posts