PyTorch hat ein neues neuronales Netzwerk implementiert, $ \ Pi $ -Net, das in dem folgenden für CVPR2020 angenommenen Dokument vorgeschlagen wird.
Chrysos, Grigorios G., et al. "
Den gesamten zum Lernen verwendeten Code finden Sie unter GitHub.
In $ \ Pi $ -Net ist das Netzwerk in der Mitte verzweigt, und die ** Multiplikation wird an dem Teil durchgeführt, an dem es wieder verbunden wird **. Dies stellt die Ausgabe als Eingabepolynom dar.
In einem normalen neuronalen Netzwerk wird die Ausgabe jeder Schicht durch Anwenden von Aktivierungsfunktionen wie ReLU und Sigmoid nichtlinear gemacht. Ohne die Aktivierungsfunktion können Sie unabhängig von der Anzahl der Ebenen, in denen Sie das Netzwerk vergrößern, nur linear an die Eingabe ausgeben, was bedeutungslos ist.
In $ \ Pi $ -Net wird die Ausgabe der Zwischenschicht jedoch multipliziert, um dem Netzwerk eine Nichtlinearität zu verleihen. Selbst wenn Sie die Aktivierungsfunktion ** nicht verwenden, können Sie sie stark ausdrücken, indem Sie sie mehrschichtig machen. Sie können Fähigkeiten erwerben.
In dem Papier wurden mehrere Netzwerkstrukturen vorgeschlagen, aber dieses Mal haben wir sie basierend auf einer davon implementiert, der folgenden Struktur.
(Zitiert aus dem Papier)
Es gibt eine Skip-Verbindung und sie hat eine Struktur wie ResNet, aber der Teil, dem sie beitritt, ist nicht Addition, sondern Multiplikation (Adamar-Produkt). Da die Ausgabe des vorherigen Blocks in jedem Block quadriert wird, wird sie durch Stapeln von $ N $ -Blöcken zu einem Polypoly in der Größenordnung von $ 2 ^ N $, und die Ausdruckskraft des Netzwerks steigt exponentiell an.
Ich habe das folgende Modell erstellt, indem ich in der obigen Abbildung 5 Blöcke gestapelt habe. Daher wird die Ausgabe des Netzwerks durch eine polymorphe Ordnung von $ 2 ^ 5 = 32 $ dargestellt. Beachten Sie, dass wir keine Aktivierungsfunktionen verwenden.
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
Ich habe die Klassifizierung von MNIST und CIFAR-10 gelernt.
MNIST Accuracy
Loss
Testgenauigkeit von ca. 99%!
CIFAR-10 Accuracy
Loss
Der Test ist ungefähr 70% genau, aber Sie lernen zu viel ...
Da es sich bei der Ausgabe um eine polymorphe Eingabe handelt, konnten wir ohne Verwendung der Aktivierungsfunktion lernen.
Wie oben erwähnt, verbessert sich die Ausdruckskraft exponentiell durch Stapeln von Blöcken. Es ist bekannt, dass selbst gewöhnliche neuronale Netze ihre Ausdruckskraft in Bezug auf die Anzahl der Schichten exponentiell verbessern [^ 1]. Ehrlich gesagt habe ich die Vorteile von $ \ Pi $ -Net nicht wirklich verstanden ...
Recommended Posts