Networks – chatgpz.de – KI-Tools & Praxiswissen http://chatgpz.de Unabhängige Tests, Anleitungen und Hintergründe zu KI-Tools. Tue, 01 Apr 2025 09:26:35 +0000 de-DE hourly 1 https://wordpress.org/?v=6.4.2 234900186 Graph Neural Networks Teil 3: Wie Graphsage die Grafikstruktur verändert http://chatgpz.de/artificial-intelligence/graph-neural-networks-teil-3-wie-graphsage-die-grafikstruktur-veraendert/ http://chatgpz.de/artificial-intelligence/graph-neural-networks-teil-3-wie-graphsage-die-grafikstruktur-veraendert/#respond Tue, 01 Apr 2025 09:26:35 +0000 https://chatgpz.de/artificial-intelligence/graph-neural-networks-teil-3-wie-graphsage-die-grafikstruktur-veraendert/ [ad_1]

In Teilen dieser Serie haben wir uns mit Graph Faltungsnetzwerken (GCNs) und Graph Achtungsnetzwerken (GATs) befasst. Beide Architekturen funktionieren intestine, haben aber auch einige Einschränkungen! Ein großes ist, dass für große Graphen die Berechnung der Knotendarstellungen mit GCNs und GATs sehr langsam werden. Eine weitere Einschränkung besteht darin, dass GCNs und GATs, wenn sich die Graphenstruktur ändert, nicht verallgemeinert werden können. Wenn additionally Knoten zum Diagramm hinzugefügt werden, können ein GCN oder GAT keine Vorhersagen dafür treffen. Zum Glück können diese Probleme gelöst werden!

In diesem Beitrag werde ich erklären Graphsage und wie es häufige Probleme von GCNs und Gats löst. Wir trainieren Graphsage und verwenden sie für Diagrammvorhersagen, um die Leistung mit GCNs und GATs zu vergleichen.

Neu in Gnns? Sie können mit beginnen mit Submit 1 über GCNs (Enthält auch das anfängliche Setup zum Ausführen der Code -Beispiele) und Submit 2 über Gats.


Zwei wichtige Probleme mit GCNs und Gats

Ich habe es in der Einführung in Kürze angesprochen, aber lassen Sie uns ein bisschen tiefer tauchen. Was sind die Probleme mit den vorherigen GNN -Modellen?

Downside 1. Sie verallgemeinern nicht

GCNs und GATs haben Probleme mit der Verallgemeinerung auf unsichtbare Grafiken. Die Grafikstruktur muss mit den Trainingsdaten übereinstimmen. Dies ist bekannt als als transduktives Lernenwo das Modell trainiert und Vorhersagen in derselben festen Grafik macht. Es ist tatsächlich zu bestimmten Graph -Topologien übernommen. In Wirklichkeit ändern sich die Grafiken: Knoten und Kanten können hinzugefügt oder entfernt werden, und dies geschieht oft in Szenarien in realer Welt. Wir möchten induktiv Lernen).

Downside 2. Sie haben Skalierbarkeitsprobleme

Das Coaching von GCNs und GATS in groß angelegten Grafiken ist rechnerisch teuer. GCNs erfordern eine wiederholte Nachbaraggregation, die exponentiell mit der Graphengröße wächst, während GATs (Multihead-) Aufmerksamkeitsmechanismen mit zunehmenden Knoten schlecht skalieren.
In großen Produktionsempfehlungssystemen mit großen Grafiken mit Millionen von Benutzern und Produkten sind GCNs und GATS unpraktisch und langsam.

Schauen wir uns die Graphsage an, um diese Probleme zu beheben.

Graphsage (Probe und Aggregat)

Graphsage macht das Coaching viel schneller und skalierbar. Dies geschieht durch Probenahme nur eine Untergruppe von Nachbarn. Für tremendous große Grafiken ist es rechnerisch unmöglich, alle Nachbarn eines Knotens zu verarbeiten (außer wenn Sie unbegrenzt Zeit haben, was wir alle nicht…), wie bei traditionellen GCNs. Ein weiterer wichtiger Schritt der Graphsage ist Kombinieren Sie die Merkmale der abgetasteten Nachbarn mit einer Aggregationsfunktion.
Wir werden alle Schritte der Graphsage unten durchlaufen.

1. Probenahme Nachbarn

Bei tabellarischen Daten ist die Stichprobe einfach. Es ist etwas, was Sie in jedem gemeinsamen Projekt für maschinelles Lernen bei der Erstellung von Zug-, Check- und Validierungssätzen machen. Mit Diagrammen können Sie keine zufälligen Knoten auswählen. Dies kann zu getrennten Graphen, Knoten ohne Nachbarn usw. führen:

Zufällig auswählen Knoten, einige sind jedoch getrennt. Bild des Autors.

Was du dürfen Mit Diagrammen wählt eine zufällige Untergruppe von Nachbarn mit fester Größe aus. In einem sozialen Netzwerk können Sie beispielsweise 3 Freunde für jeden Benutzer (anstelle aller Freunde) probieren:

Alle in der GCN ausgewählten Nachbarn wählten zufällig drei Zeilen in der Tabelle aus, drei in Graphsage ausgewählten Nachbarn. Bild des Autors.

2. Gesamtinformationen

Nach der Auswahl der Nachbarn aus dem vorherigen Teil kombiniert Graphsage ihre Funktionen zu einer einzigen Darstellung. Es gibt mehrere Möglichkeiten, dies zu tun (mehrere Aggregationsfunktionen). Die am häufigsten und die im Papier erklärten Typen sind mittlere AggregationAnwesend LstmUnd Pooling.

Mit der mittleren Aggregation wird der Durchschnitt über alle Merkmale der abgetasteten Nachbarn berechnet (sehr einfach und oft effektiv). In einer Formel:

LSTM -Aggregation verwendet eine Lstm (Artwork des neuronalen Netzwerks), um Nachbarfunktionen nacheinander zu verarbeiten. Es kann komplexere Beziehungen aufnehmen und ist mächtiger als die mittlere Aggregation.

Die dritte Artwork, die Poolaggregation, wendet eine nichtlineare Funktion an, um wichtige Merkmale zu extrahieren (denken Sie an Max-Pooling In einem neuronalen Netzwerk, in dem Sie auch den Maximalwert einiger Werte nehmen).

3.. Aktualisieren der Knotendarstellung

Nach der Probenahme und Aggregation der Knoten kombiniert seine früheren Funktionen mit den aggregierten Nachbarnfunktionen. Knoten werden von ihren Nachbarn lernen, aber auch ihre eigene Identität behalten, genau wie zuvor mit GCNs und Gats. Informationen können effektiv über den Diagramm fließen.

Dies ist die Formel für diesen Schritt:

Die Aggregation von Schritt 2 erfolgt über alle Nachbarn, und dann wird die Merkmalsdarstellung des Knotens verkettet. Dieser Vektor wird mit der Gewichtsmatrix multipliziert und durch die Nichtlinearität (z. B. Relu) geleitet. Als letzter Schritt kann die Normalisierung angewendet werden.

4. Wiederholen Sie für mehrere Schichten

Die ersten drei Schritte können mehrmals wiederholt werden. In diesem Fall können Informationen von entfernten Nachbarn fließen. Im Bild unten sehen Sie einen Knoten mit drei in der ersten Schicht ausgewählten Nachbarn (direkte Nachbarn) und zwei in der zweiten Schicht ausgewählte Nachbarn (Nachbarn der Nachbarn).

Ausgewählter Knoten mit ausgewählten Nachbarn, drei in der ersten Schicht, zwei in der zweiten Schicht. Interessant ist, dass einer der Nachbarn der Knoten im ersten Schritt der ausgewählte Knoten ist, so dass man auch ausgewählt werden kann, wenn zwei Nachbarn im zweiten Schritt ausgewählt werden (nur etwas schwieriger zu visualisieren). Bild des Autors.

Zusammenfassend lässt sich sagen, dass die wichtigsten Stärken von Graphsage ihre Skalierbarkeit sind (die Abtastung macht es für large Grafiken effizient). Flexibilität können Sie es verwenden für Induktives Lernen (Funktioniert intestine, wenn es zur Vorhersage von unsichtbaren Knoten und Grafiken verwendet wird); Die Aggregation hilft bei der Verallgemeinerung, da sie laute Merkmale glättet. und die Mehrschichten erlauben das Modell, aus fernen Knoten zu lernen.

Cool! Und das Beste, Graphsage wird in implementiert PygSo können wir es leicht in Pytorch verwenden.

Vorhersage mit Graphsage

In den vorherigen Beiträgen haben wir einen MLP, GCN und GAT auf dem implementiert Cora Datensatz (CC BY-SA). Um Ihren Geist ein wenig zu aktualisieren, ist Cora ein Datensatz mit wissenschaftlichen Veröffentlichungen, in denen Sie das Thema jedes Papiers mit insgesamt sieben Klassen vorhersagen müssen. Dieser Datensatz ist relativ gering und ist daher möglicherweise nicht der beste Satz für das Testen von Graphsage. Wir werden dies trotzdem tun, nur um vergleichen zu können. Mal sehen, wie intestine Graphsage funktioniert.

Interessante Teile des Codes, die ich gerne mit Graphsage hervorhebt:

  • Der NeighborLoader Dadurch wird die Auswahl der Nachbarn für jede Schicht ausgeführt:
from torch_geometric.loader import NeighborLoader

# 10 neighbors sampled within the first layer, 10 within the second layer
num_neighbors = (10, 10)

# pattern information from the prepare set
train_loader = NeighborLoader(
    information,
    num_neighbors=num_neighbors,
    batch_size=batch_size,
    input_nodes=information.train_mask,
)
  • Der Aggregationstyp ist in der implementiert SAGEConv Schicht. Der Normal ist implySie können dies an ändern max oder lstm:
from torch_geometric.nn import SAGEConv

SAGEConv(in_c, out_c, aggr='imply')
  • Ein weiterer wichtiger Unterschied besteht darin, dass Graphsage in Mini -Chargen und GCN und GAT auf dem vollständigen Datensatz trainiert wird. Dies berührt die Essenz von Graphsage, da die Nachbarabtastung von Graphsage es ermöglicht, in Mini -Chargen zu trainieren, benötigen wir nicht mehr den vollständigen Diagramm. GCNs und GATs benötigen das komplette Diagramm für die korrekte Merkmalsausbreitung und Berechnung der Aufmerksamkeitswerte. Deshalb trainieren wir GCNs und GATS im vollständigen Diagramm.
  • Der Relaxation des Codes ist ähnlich wie zuvor, außer dass wir eine Klasse haben, in der alle verschiedenen Modelle basierend auf dem instanziiert werden model_type (GCN, Gat oder Salbei). Dies erleichtert es einfach, kleine Änderungen zu vergleichen oder vorzunehmen.

Dies ist das vollständige Skript. Wir trainieren 100 Epochen und wiederholen das Experiment 10 Mal, um die durchschnittliche Genauigkeit und Standardabweichung für jedes Modell zu berechnen:

import torch
import torch.nn.purposeful as F
from torch_geometric.nn import SAGEConv, GCNConv, GATConv
from torch_geometric.datasets import Planetoid
from torch_geometric.loader import NeighborLoader

# dataset_name could be 'Cora', 'CiteSeer', 'PubMed'
dataset_name = 'Cora'
hidden_dim = 64
num_layers = 2
num_neighbors = (10, 10)
batch_size = 128
num_epochs = 100
model_types = ('GCN', 'GAT', 'SAGE')

dataset = Planetoid(root='information', identify=dataset_name)
information = dataset(0)
machine = torch.machine('cuda' if torch.cuda.is_available() else 'cpu')
information = information.to(machine)

class GNN(torch.nn.Module):
    def __init__(self, in_channels, hidden_channels, out_channels, num_layers, model_type='SAGE', gat_heads=8):
        tremendous().__init__()
        self.convs = torch.nn.ModuleList()
        self.model_type = model_type
        self.gat_heads = gat_heads

        def get_conv(in_c, out_c, is_final=False):
            if model_type == 'GCN':
                return GCNConv(in_c, out_c)
            elif model_type == 'GAT':
                heads = 1 if is_final else gat_heads
                concat = False if is_final else True
                return GATConv(in_c, out_c, heads=heads, concat=concat)
            else:
                return SAGEConv(in_c, out_c, aggr='imply')

        if model_type == 'GAT':
            self.convs.append(get_conv(in_channels, hidden_channels))
            in_dim = hidden_channels * gat_heads
            for _ in vary(num_layers - 2):
                self.convs.append(get_conv(in_dim, hidden_channels))
                in_dim = hidden_channels * gat_heads
            self.convs.append(get_conv(in_dim, out_channels, is_final=True))
        else:
            self.convs.append(get_conv(in_channels, hidden_channels))
            for _ in vary(num_layers - 2):
                self.convs.append(get_conv(hidden_channels, hidden_channels))
            self.convs.append(get_conv(hidden_channels, out_channels))

    def ahead(self, x, edge_index):
        for conv in self.convs(:-1):
            x = F.relu(conv(x, edge_index))
        x = self.convs(-1)(x, edge_index)
        return x

@torch.no_grad()
def check(mannequin):
    mannequin.eval()
    out = mannequin(information.x, information.edge_index)
    pred = out.argmax(dim=1)
    accs = ()
    for masks in (information.train_mask, information.val_mask, information.test_mask):
        accs.append(int((pred(masks) == information.y(masks)).sum()) / int(masks.sum()))
    return accs

outcomes = {}

for model_type in model_types:
    print(f'Coaching {model_type}')
    outcomes(model_type) = ()

    for i in vary(10):
        mannequin = GNN(dataset.num_features, hidden_dim, dataset.num_classes, num_layers, model_type, gat_heads=8).to(machine)
        optimizer = torch.optim.Adam(mannequin.parameters(), lr=0.01, weight_decay=5e-4)

        if model_type == 'SAGE':
            train_loader = NeighborLoader(
                information,
                num_neighbors=num_neighbors,
                batch_size=batch_size,
                input_nodes=information.train_mask,
            )

            def prepare():
                mannequin.prepare()
                total_loss = 0
                for batch in train_loader:
                    batch = batch.to(machine)
                    optimizer.zero_grad()
                    out = mannequin(batch.x, batch.edge_index)
                    loss = F.cross_entropy(out, batch.y(:out.dimension(0)))
                    loss.backward()
                    optimizer.step()
                    total_loss += loss.merchandise()
                return total_loss / len(train_loader)

        else:
            def prepare():
                mannequin.prepare()
                optimizer.zero_grad()
                out = mannequin(information.x, information.edge_index)
                loss = F.cross_entropy(out(information.train_mask), information.y(information.train_mask))
                loss.backward()
                optimizer.step()
                return loss.merchandise()

        best_val_acc = 0
        best_test_acc = 0
        for epoch in vary(1, num_epochs + 1):
            loss = prepare()
            train_acc, val_acc, test_acc = check(mannequin)
            if val_acc > best_val_acc:
                best_val_acc = val_acc
                best_test_acc = test_acc
            if epoch % 10 == 0:
                print(f'Epoch {epoch:02d} | Loss: {loss:.4f} | Practice: {train_acc:.4f} | Val: {val_acc:.4f} | Check: {test_acc:.4f}')

        outcomes(model_type).append((best_val_acc, best_test_acc))

for model_name, model_results in outcomes.gadgets():
    model_results = torch.tensor(model_results)
    print(f'{model_name} Val Accuracy: {model_results(:, 0).imply():.3f} ± {model_results(:, 0).std():.3f}')
    print(f'{model_name} Check Accuracy: {model_results(:, 1).imply():.3f} ± {model_results(:, 1).std():.3f}')

Und hier sind die Ergebnisse:

GCN Val Accuracy: 0.791 ± 0.007
GCN Check Accuracy: 0.806 ± 0.006
GAT Val Accuracy: 0.790 ± 0.007
GAT Check Accuracy: 0.800 ± 0.004
SAGE Val Accuracy: 0.899 ± 0.005
SAGE Check Accuracy: 0.907 ± 0.004

Beeindruckende Verbesserung! Auch in diesem kleinen Datensatz übertrifft Graphsage Gat und GCN leicht! Ich wiederholte diesen Check für CiteSeer- und PubMed -Datensätze, und Graphsage kam immer am besten heraus.

Was ich hier gerne bemerkte, ist, dass GCN immer noch sehr nützlich ist, es ist eine der effektivsten Basislinien (wenn die Grafikstruktur dies zulässt). Außerdem habe ich nicht viel Hyperparameter-Tuning durchgeführt, sondern nur einige Standardwerte (wie 8 Köpfe für die Multi-Head-Aufmerksamkeit). In größeren, komplexeren und lauteren Graphen werden die Vorteile von Graphsage klarer als in diesem Beispiel. Wir haben keine Leistungstests durchgeführt, da für diese kleinen Graphen nicht schneller als GCN.


Abschluss

Graphsage bringt uns sehr nette Verbesserungen und Vorteile im Vergleich zu GATS und GCNs. Induktives Lernen ist möglich, Graphsage kann sich recht intestine ändern. Und wir haben es in diesem Beitrag nicht getestet, aber die Nachbar -Probenahme ermöglicht es, Characteristic -Darstellungen für größere Grafiken mit guter Leistung zu erstellen.

Verwandt

Optimierung von Verbindungen: Mathematische Optimierung innerhalb der Grafiken

Graph Neural Networks Teil 1. Graph Faltungsnetzwerke erläutert

Graph Neural Networks Teil 2. Diagramm -Aufmerksamkeitsnetzwerke vs. GCNs

[ad_2]

]]>
http://chatgpz.de/artificial-intelligence/graph-neural-networks-teil-3-wie-graphsage-die-grafikstruktur-veraendert/feed/ 0 8239
Asymmetrische zertifizierte Robustheit durch Function-Convex Neural Networks – Das Berkeley Synthetic Intelligence Analysis Weblog http://chatgpz.de/machine-learning/asymmetrische-zertifizierte-robustheit-durch-function-convex-neural-networks-das-berkeley-synthetic-intelligence-analysis-weblog/ http://chatgpz.de/machine-learning/asymmetrische-zertifizierte-robustheit-durch-function-convex-neural-networks-das-berkeley-synthetic-intelligence-analysis-weblog/#respond Mon, 22 Jul 2024 14:15:10 +0000 http://chatgpz.de/machine-learning/asymmetrische-zertifizierte-robustheit-durch-feature-convex-neural-networks-das-berkeley-artificial-intelligence-research-blog/ [ad_1]


Asymmetrische zertifizierte Robustheit durch Function-Convex Neural Networks

Kurz zusammengefasst: Wir schlagen vor, asymmetrische zertifizierte Robustheit Drawback, das zertifizierte Robustheit für nur eine Klasse erfordert und reale gegnerische Szenarien widerspiegelt. Diese fokussierte Einstellung ermöglicht es uns, merkmalskonvexe Klassifikatoren einzuführen, die geschlossene und deterministische zertifizierte Radien in der Größenordnung von Millisekunden erzeugen.

Diagramm zur Veranschaulichung der FCNN-Architektur

Abbildung 1. Darstellung von merkmalskonvexen Klassifikatoren und ihrer Zertifizierung für Eingaben sensibler Klassen. Diese Architektur erstellt eine Lipschitz-kontinuierliche Merkmalskarte $varphi$ mit einer gelernten konvexen Funktion $g$. Da $g$ konvex ist, wird es international durch seine Tangentialebene bei $varphi(x)$ unterapproximiert, was zertifizierte Normbälle im Merkmalsraum ergibt. Die Lipschitzheit von $varphi$ ergibt dann entsprechend skalierte Zertifikate im ursprünglichen Eingaberaum.

Trotz ihrer weiten Verbreitung sind Deep Studying-Klassifikatoren äußerst anfällig für kontroverse Beispiele: kleine, für den Menschen nicht wahrnehmbare Bildstörungen, die maschinelle Lernmodelle dazu verleiten, die modifizierte Eingabe falsch zu klassifizieren. Diese Schwäche untergräbt die Zuverlässigkeit sicherheitskritischer Prozesse, die maschinelles Lernen beinhalten, erheblich. Es wurden viele empirische Abwehrmaßnahmen gegen feindliche Störungen vorgeschlagen – oft nur, um später durch stärkere Angriffsstrategien besiegt zu werden. Wir konzentrieren uns daher auf Zertifizierbar robuste Klassifikatorendie eine mathematische Garantie dafür bieten, dass ihre Vorhersage für eine $ell_p$-Normkugel um eine Eingabe konstant bleibt.

Herkömmliche Methoden zur zertifizierten Robustheit haben eine Reihe von Nachteilen, darunter Nichtdeterminismus, langsame Ausführung, schlechte Skalierung und Zertifizierung nur für eine Angriffsnorm. Wir argumentieren, dass diese Probleme angegangen werden können, indem das Drawback der zertifizierten Robustheit verfeinert wird, um es besser an praktische gegnerische Situationen anzupassen.

Das Drawback der asymmetrischen zertifizierten Robustheit

Aktuelle nachweislich robuste Klassifizierer erstellen Zertifikate für Eingaben, die zu einer beliebigen Klasse gehören. Für viele reale gegnerische Anwendungen ist dies unnötig weit gefasst. Betrachten Sie den anschaulichen Fall eines Menschen, der eine Phishing-E-Mail verfasst und gleichzeitig versucht, Spamfilter zu umgehen. Dieser Angreifer wird immer versuchen, den Spamfilter zu täuschen, indem er ihn glauben lässt, dass seine Spam-E-Mail harmlos ist – niemals umgekehrt. Mit anderen Worten: Der Angreifer versucht lediglich, falsche Negativergebnisse vom Klassifikator zu erhalten. Ähnliche Einstellungen umfassen die Erkennung von Malware, die Kennzeichnung von Pretend Information, die Erkennung von Social-Media-Bots, das Filtern von Krankenversicherungsansprüchen, die Erkennung von Finanzbetrug, die Erkennung von Phishing-Web sites und vieles mehr.

ein motivierendes Spamfilter-Diagramm

Abbildung 2. Asymmetrische Robustheit bei der E-Mail-Filterung. In der Praxis ist in gegnerischen Umgebungen oft zertifizierte Robustheit nur für eine Klasse erforderlich.

Bei allen diesen Anwendungen handelt es sich um eine binäre Klassifizierungseinstellung mit einer smart Klasse die ein Angreifer zu vermeiden versucht (z. B. die Klasse „Spam-E-Mail“). Dies motiviert das Drawback der asymmetrische zertifizierte Robustheitdessen Ziel darin besteht, nachweislich robuste Vorhersagen für Eingaben in der sensiblen Klasse zu liefern und gleichzeitig eine hohe Genauigkeit für alle anderen Eingaben beizubehalten. Wir liefern im Haupttext eine formellere Problemstellung.

Merkmalskonvexe Klassifikatoren

Wir schlagen vor Merkmalskonvexe neuronale Netze um das Drawback der asymmetrischen Robustheit zu lösen. Diese Architektur komponiert eine einfache Lipschitz-kontinuierliche Function-Map ${varphi: mathbb{R}^d to mathbb{R}^q}$ mit einem gelernten Enter-Convex Neural Community (ICNN) ${g: mathbb{R}^q to mathbb{R}}$ (Abbildung 1). ICNNs erzwingen Konvexität vom Enter- zum Output-Logit, indem sie ReLU-Nichtlinearitäten mit nichtnegativen Gewichtsmatrizen komponieren. Da ein binärer ICNN-Entscheidungsbereich aus einem konvexen Set und seinem Komplement besteht, fügen wir die vorkomponierte Function-Map $varphi$ hinzu, um nichtkonvexe Entscheidungsbereiche zu ermöglichen.

Merkmalskonvexe Klassifikatoren ermöglichen die schnelle Berechnung von zertifizierten Radien empfindlicher Klassen für alle $ell_p$-Normen. Unter Ausnutzung der Tatsache, dass konvexe Funktionen international von jeder Tangentialebene unterapproximiert werden, können wir einen zertifizierten Radius im Zwischenmerkmalsraum erhalten. Dieser Radius wird dann durch Lipschitzness in den Eingaberaum übertragen. Die asymmetrische Einstellung ist hier kritisch, da diese Architektur nur Zertifikate für die constructive Logit-Klasse $g(varphi(x)) > 0$ erzeugt.

Die resultierende, nach der $ell_p$-Norm zertifizierte Radiusformel ist besonders elegant:

(r_p(x) = frac{ shade{blue}{g(varphi(x))} } { mathrm{Lip}_p(varphi) shade{purple}{| nabla g(varphi(x)) | _{p,*}}}.)

Die nicht-konstanten Terme sind leicht zu interpretieren: Der Radius skaliert proportional zur Klassifikatorvertrauen und umgekehrt zum Klassifikatorempfindlichkeit. Wir bewerten diese Zertifikate anhand einer Reihe von Datensätzen und erzielen wettbewerbsfähige $ell_1$-Zertifikate und vergleichbare $ell_2$- und $ell_{infty}$-Zertifikate – obwohl andere Methoden im Allgemeinen auf eine bestimmte Norm zugeschnitten sind und um Größenordnungen mehr Laufzeit erfordern.

cifar10 Katzen Hunde zertifizierte Radien

Abbildung 3. Zertifizierte Radien der empfindlichen Klasse im CIFAR-10-Datensatz „Katzen vs. Hunde“ für die $ell_1$-Norm. Die Laufzeiten auf der rechten Seite sind über die $ell_1$-, $ell_2$- und $ell_{infty}$-Radien gemittelt (beachten Sie die logarithmische Skalierung).

Unsere Zertifikate gelten für jede $ell_p$-Norm und sind geschlossen und deterministisch, sodass professional Eingabe nur ein Vorwärts- und Rückwärtsdurchlauf erforderlich ist. Diese sind in der Größenordnung von Millisekunden berechenbar und lassen sich intestine mit der Netzwerkgröße skalieren. Zum Vergleich: Aktuelle hochmoderne Methoden wie randomisierte Glättung und Intervall-Grenzausbreitung benötigen in der Regel mehrere Sekunden, um selbst kleine Netzwerke zu zertifizieren. Randomisierte Glättungsmethoden sind außerdem von Natur aus nichtdeterministisch, mit Zertifikaten, die mit hoher Wahrscheinlichkeit einfach gelten.

Theoretisches Versprechen

Während die ersten Ergebnisse vielversprechend sind, deutet unsere theoretische Arbeit darauf hin, dass ICNNs auch ohne Function-Map noch erhebliches ungenutztes Potenzial haben. Obwohl binäre ICNNs auf das Lernen konvexer Entscheidungsbereiche beschränkt sind, beweisen wir, dass es ein ICNN gibt, das im CIFAR-10-Katzen-gegen-Hunde-Datensatz eine perfekte Trainingsgenauigkeit erreicht.

Tatsache. Es gibt einen Enter-konvexen Klassifikator, der eine perfekte Trainingsgenauigkeit für den CIFAR-10-Katzen-gegen-Hunde-Datensatz erreicht.

Unsere Architektur erreicht jedoch ohne eine Function-Map nur eine Trainingsgenauigkeit von 73,4 %. Obwohl die Trainingsleistung keine Generalisierung des Testsatzes impliziert, deutet dieses Ergebnis darauf hin, dass ICNNs zumindest theoretisch in der Lage sind, das moderne Paradigma des maschinellen Lernens der Überanpassung an den Trainingsdatensatz zu erreichen. Wir stellen daher das folgende offene Drawback für das Feld dar.

Offenes Drawback. Lernen Sie einen inputkonvexen Klassifikator kennen, der eine perfekte Trainingsgenauigkeit für den CIFAR-10-Katzen-gegen-Hunde-Datensatz erreicht.

Abschluss

Wir hoffen, dass das asymmetrische Robustheits-Framework zu neuen Architekturen inspiriert, die in diesem fokussierteren Umfeld zertifizierbar sind. Unser Function-konvexer Klassifikator ist eine solche Architektur und bietet schnelle, deterministische zertifizierte Radien für jede $ell_p$-Norm. Wir stellen auch das offene Drawback der Überanpassung des CIFAR-10-Trainingsdatensatzes „Katzen vs. Hunde“ mit einem ICNN, was, wie wir zeigen, theoretisch möglich ist.

Dieser Beitrag basiert auf dem folgenden Dokument:

Asymmetrische zertifizierte Robustheit durch Function-Convex Neural Networks

Samuel Pfrommer,
Brendon G. Anderson
,
Julien Piet,
Somayeh Sojoudi,

37. Konferenz zu neuronalen Informationsverarbeitungssystemen (NeurIPS 2023).

Weitere Einzelheiten finden Sie auf arXiv Und GitHub. Wenn unser Papier Ihre Arbeit inspiriert, denken Sie bitte daran, es wie folgt zu zitieren:

@inproceedings{
    pfrommer2023asymmetric,
    title={Uneven Licensed Robustness by way of Function-Convex Neural Networks},
    writer={Samuel Pfrommer and Brendon G. Anderson and Julien Piet and Somayeh Sojoudi},
    booktitle={Thirty-seventh Convention on Neural Info Processing Programs},
    12 months={2023}
}

[ad_2]

]]>
http://chatgpz.de/machine-learning/asymmetrische-zertifizierte-robustheit-durch-function-convex-neural-networks-das-berkeley-synthetic-intelligence-analysis-weblog/feed/ 0 2504
Die Geschichte der Convolutional Neural Networks zur Bildklassifizierung (1989 – heute) | von Avishek Biswas | Juni 2024 http://chatgpz.de/machine-learning/die-geschichte-der-convolutional-neural-networks-zur-bildklassifizierung-1989-heute-von-avishek-biswas-juni-2024/ http://chatgpz.de/machine-learning/die-geschichte-der-convolutional-neural-networks-zur-bildklassifizierung-1989-heute-von-avishek-biswas-juni-2024/#respond Mon, 01 Jul 2024 02:12:18 +0000 https://chatgpz.de/machine-learning/die-geschichte-der-convolutional-neural-networks-zur-bildklassifizierung-1989-heute-von-avishek-biswas-juni-2024/ [ad_1]

Eine visuelle Tour durch die größten Innovationen im Bereich Deep Studying und Pc Imaginative and prescient.

Vor CNNs bestand die Standardmethode zum Trainieren eines neuronalen Netzwerks zum Klassifizieren von Bildern darin, das Bild in eine Liste von Pixeln zu glätten und diese durch ein Feedforward-Neuralnetzwerk zu leiten, um die Klasse des Bilds auszugeben. Das Downside bei der Glättung des Bilds besteht darin, dass die wesentlichen räumlichen Informationen im Bild verworfen werden.

1989 führten Yann LeCun und sein Group Convolutional Neural Networks ein – das Rückgrat der Pc Imaginative and prescient-Forschung der letzten 15 Jahre! Im Gegensatz zu Feedforward-Netzwerken bewahren CNNs die 2D-Natur von Bildern und sind in der Lage, Informationen räumlich zu verarbeiten!

In diesem Artikel werden wir die Geschichte der CNNs speziell für Bildklassifizierungsaufgaben durchgehen – angefangen von den frühen Forschungsjahren in den 90er Jahren bis hin zur goldenen Ära Mitte der 2010er Jahre, als viele der genialsten Deep-Studying-Architekturen aller Zeiten konzipiert wurden. Abschließend diskutieren wir die neuesten Tendencies in der aktuellen CNN-Forschung, da sie mit Aufmerksamkeits- und Bildtransformatoren konkurrieren.

Besuche die YouTube-Video das alle Konzepte in diesem Artikel visuell mit Animationen erklärt. Sofern nicht anders angegeben, werden alle in diesem Artikel verwendeten Bilder und Illustrationen von mir selbst beim Erstellen der Videoversion erstellt.

Die Papiere, die wir heute besprechen werden!

Das Herzstück eines CNN ist die Faltungsoperation. Wir scannen das Bild mit dem Filter und berechnen an jeder Überlappungsstelle das Skalarprodukt des Filters mit dem Bild. Diese resultierende Ausgabe wird als Function-Map bezeichnet und erfasst, wie stark und wo das Filtermuster im Bild vorhanden ist.

So funktioniert die Faltung – Der Kernel gleitet über das Eingabebild und berechnet die Überlappung (Skalarprodukt) an jeder Stelle – und gibt am Ende eine Function-Map aus!

In einer Faltungsschicht trainieren wir mehrere Filter, die verschiedene Merkmalskarten aus dem Eingabebild extrahieren. Wenn wir mehrere Faltungsschichten mit einer gewissen Nichtlinearität nacheinander stapeln, erhalten wir ein Faltungsneuronales Netzwerk (CNN).

Jede Faltungsschicht führt additionally gleichzeitig zwei Dinge aus:
1. räumliche Filterung mit der Faltungsoperation zwischen Bildern und Kerneln und
2. Kombinieren der mehreren Eingangskanäle und geben Sie einen neuen Satz Kanäle aus.

90 Prozent der Forschung in CNNs zielten darauf ab, genau diese beiden Dinge zu modifizieren oder zu verbessern.

Die beiden wichtigsten Dinge, die CNN tut

Das Papier von 1989

Dieses Papier von 1989 hat uns beigebracht, wie man nichtlineare CNNs von Grund auf mit Backpropagation trainiert. Sie geben 16×16 Graustufenbilder handgeschriebener Ziffern ein und durchlaufen zwei Faltungsschichten mit 12 Filtern der Größe 5×5. Die Filter bewegen sich während des Scannens auch mit einer Schrittweite von 2. Die Schrittweite-Faltung ist nützlich, um das Eingabebild herunterzusampeln. Nach den Konv-Schichten werden die Ausgabekarten abgeflacht und durch zwei vollständig verbundene Netzwerke geleitet, um die Wahrscheinlichkeiten für die 10 Ziffern auszugeben. Unter Verwendung des Softmax-Kreuzentropieverlusts wird das Netzwerk optimiert, um die richtigen Beschriftungen für die handgeschriebenen Ziffern vorherzusagen. Nach jeder Schicht wird auch die Tanh-Nichtlinearität verwendet – wodurch die gelernten Merkmalskarten komplexer und ausdrucksstärker werden. Mit nur 9760 Parametern battle dies ein sehr kleines Netzwerk im Vergleich zu den heutigen Netzwerken, die Hunderte Millionen Parameter enthalten.

Die ursprüngliche CNN-Architektur von 1989

Induktive Vorspannung

Induktive Voreingenommenheit ist ein Konzept des maschinellen Lernens, bei dem wir absichtlich bestimmte Regeln und Einschränkungen in den Lernprozess einführen, um unsere Modelle von Verallgemeinerungen wegzubringen und sie stärker in Richtung Lösungen zu bewegen, die unserem menschenähnlichen Verständnis entsprechen.

Wenn Menschen Bilder klassifizieren, führen wir auch eine räumliche Filterung durch nach gemeinsamen Mustern zu suchen, um mehrere Darstellungen zu bilden und dann Kombinieren Sie sie, um unsere Vorhersagen zu bilden. Die CNN-Architektur ist darauf ausgelegt, genau das nachzubilden. In Feedforward-Netzwerken wird jedes Pixel wie ein eigenes isoliertes Merkmal behandelt, da jedes Neuron in den Schichten mit allen Pixeln verbunden ist – in CNNs gibt es mehr Parameter-Sharing, da derselbe Filter das gesamte Bild scannt. Induktive Verzerrungen machen CNNs auch weniger datenhungrig, da sie aufgrund des Netzwerkdesigns lokale Mustererkennung kostenlos erhalten, aber Feedforward-Netzwerke müssen ihre Trainingszyklen damit verbringen, sie von Grund auf zu lernen.

[ad_2]

]]>
http://chatgpz.de/machine-learning/die-geschichte-der-convolutional-neural-networks-zur-bildklassifizierung-1989-heute-von-avishek-biswas-juni-2024/feed/ 0 1887
Löschen von Wolken aus Satellitenbildern mithilfe von GANs (Generative Adversarial Networks) | von Aleksei Rozanov | Juni 2024 http://chatgpz.de/machine-learning/loeschen-von-wolken-aus-satellitenbildern-mithilfe-von-gans-generative-adversarial-networks-von-aleksei-rozanov-juni-2024/ http://chatgpz.de/machine-learning/loeschen-von-wolken-aus-satellitenbildern-mithilfe-von-gans-generative-adversarial-networks-von-aleksei-rozanov-juni-2024/#respond Sat, 15 Jun 2024 06:23:01 +0000 http://chatgpz.de/machine-learning/loeschen-von-wolken-aus-satellitenbildern-mithilfe-von-gans-generative-adversarial-networks-von-aleksei-rozanov-juni-2024/ [ad_1]

GANs von Grund auf in Python erstellen

Foto von Michael & Diane Weidner An Unsplash

TDie Idee der Generative Adversarial Networks (GANs) wurde 2014 von Goodfellow und seinen Kollegen (1) vorgestellt und erfreute sich kurz darauf großer Beliebtheit im Bereich der Computervision und Bilderzeugung. Obwohl sich die KI in den letzten zehn Jahren rasant weiterentwickelt hat und immer mehr neue Algorithmen entwickelt wurden, sind die Einfachheit und Genialität dieses Konzepts immer noch äußerst beeindruckend. Heute möchte ich daher anhand des Versuchs, Wolken aus RGB-Satellitenbildern (Rot, Grün, Blau) zu entfernen, zeigen, wie leistungsfähig diese Netzwerke sein können.

Die Erstellung eines ausgewogenen, ausreichend großen und korrekt vorverarbeiteten CV-Datensatzes nimmt viel Zeit in Anspruch, daher habe ich mich entschlossen, die Möglichkeiten von Kaggle zu erkunden. Der Datensatz, der mir für diese Aufgabe am besten geeignet erschien, ist EuroSat (2), der eine offene Lizenz hat. Er umfasst 27000 beschriftete RGB-Bilder 64×64 Pixel von Sentinel-2 und ist für die Lösung des Issues der Mehrklassenklassifizierung konzipiert.

Bildbeispiel aus dem EuroSat-Datensatz. Lizenz.

An der Klassifizierung selbst sind wir nicht interessiert, aber eines der Hauptmerkmale des EuroSat-Datensatzes ist, dass alle seine Bilder einen klaren Himmel zeigen. Das ist genau das, was wir brauchen. Wir übernehmen diesen Ansatz aus (3), verwenden diese Sentinel-2-Aufnahmen als Ziele und erstellen Eingaben, indem wir ihnen Rauschen (Wolken) hinzufügen.

Bereiten wir additionally unsere Daten vor, bevor wir tatsächlich über GANs sprechen. Zuerst müssen wir die Daten herunterladen und alle Klassen in einem Verzeichnis zusammenführen.

🐍Der vollständige Python-Code: GitHub.

import numpy as np
import pandas as pd
import random

from os import listdir, mkdir, rename
from os.path import be part of, exists
import shutil
import datetime

import matplotlib.pyplot as plt
from highlight_text import ax_text, fig_text
from PIL import Picture

import warnings

warnings.filterwarnings('ignore')

lessons = listdir('./EuroSat')
path_target = './EuroSat/all_targets'
path_input = './EuroSat/all_inputs'

"""RUN IT ONLY ONCE TO RENAME THE FILES IN THE UNPACKED ARCHIVE"""
mkdir(path_input)
mkdir(path_target)
okay = 1
for sort in lessons:
path = be part of('./EuroSat', str(sort))
for i, f in enumerate(listdir(path)):
shutil.copyfile(be part of(path, f),
be part of(path_target, f))
rename(be part of(path_target, f), be part of(path_target, f'{okay}.jpg'))
okay += 1

Der zweite wichtige Schritt ist die Erzeugung von Rauschen. Während Sie verschiedene Ansätze verwenden können, z. B. das zufällige Ausblenden einiger Pixel oder das Hinzufügen von Gaußschem Rauschen, möchte ich in diesem Artikel etwas Neues für mich ausprobieren – Perlin-Rauschen. Es wurde in den 80er Jahren von Ken Perlin (4) bei der Entwicklung filmischer Raucheffekte erfunden. Diese Artwork von Rauschen wirkt im Vergleich zu normalem Zufallsrauschen organischer. Lassen Sie es mich einfach beweisen.

def generate_perlin_noise(width, top, scale, octaves, persistence, lacunarity):
noise = np.zeros((top, width))
for i in vary(top):
for j in vary(width):
noise(i)(j) = pnoise2(i / scale,
j / scale,
octaves=octaves,
persistence=persistence,
lacunarity=lacunarity,
repeatx=width,
repeaty=top,
base=0)
return noise

def normalize_noise(noise):
min_val = noise.min()
max_val = noise.max()
return (noise - min_val) / (max_val - min_val)

def generate_clouds(width, top, base_scale, octaves, persistence, lacunarity):
clouds = np.zeros((top, width))
for octave in vary(1, octaves + 1):
scale = base_scale / octave
layer = generate_perlin_noise(width, top, scale, 1, persistence, lacunarity)
clouds += layer * (persistence ** octave)

clouds = normalize_noise(clouds)
return clouds

def overlay_clouds(picture, clouds, alpha=0.5):

clouds_rgb = np.stack((clouds) * 3, axis=-1)

picture = picture.astype(float) / 255.0
clouds_rgb = clouds_rgb.astype(float)

blended = picture * (1 - alpha) + clouds_rgb * alpha

blended = (blended * 255).astype(np.uint8)
return blended

width, top = 64, 64
octaves = 12 #variety of noise layers mixed
persistence = 0.5 #decrease persistence reduces the amplitude of higher-frequency octaves
lacunarity = 2 #larger lacunarity will increase the frequency of higher-frequency octaves
for i in vary(len(listdir(path_target))):
base_scale = random.uniform(5,120) #noise frequency
alpha = random.uniform(0,1) #transparency

clouds = generate_clouds(width, top, base_scale, octaves, persistence, lacunarity)

img = np.asarray(Picture.open(be part of(path_target, f'{i+1}.jpg')))
picture = Picture.fromarray(overlay_clouds(img,clouds, alpha))
picture.save(be part of(path_input,f'{i+1}.jpg'))
print(f'Processed {i+1}/{len(listdir(path_target))}')

idx = np.random.randint(27000)
fig,ax = plt.subplots(1,2)
ax(0).imshow(np.asarray(Picture.open(be part of(path_target, f'{idx}.jpg'))))
ax(1).imshow(np.asarray(Picture.open(be part of(path_input, f'{idx}.jpg'))))
ax(0).set_title("Goal")
ax(0).axis('off')
ax(1).set_title("Enter")
ax(1).axis('off')
plt.present()
Bild von Autor.

Wie Sie oben sehen können, sind die Wolken auf den Bildern sehr realistisch, sie haben unterschiedliche „Dichte“ und Texturen und ähneln den echten.

Wenn Sie Perlin-Rauschen genauso faszinierend finden wie ich, finden Sie hier ein wirklich cooles Video dazu, wie dieses Rauschen in der GameDev-Branche eingesetzt werden kann:

Da wir jetzt über einen gebrauchsfertigen Datensatz verfügen, sprechen wir über GANs.

Um diesen Gedanken besser zu veranschaulichen, stellen wir uns vor, Sie reisen durch Südostasien und brauchen dringend einen Kapuzenpullover, weil es draußen zu kalt ist. Auf dem nächsten Straßenmarkt finden Sie ein kleines Geschäft mit Markenkleidung. Der Verkäufer bringt Ihnen einen schönen Kapuzenpullover zum Anprobieren und sagt, es sei von der bekannten Marke ExpensiveButNotWorthIt. Sie sehen ihn sich genauer an und kommen zu dem Schluss, dass es sich offensichtlich um eine Fälschung handelt. Der Verkäufer sagt: „Second mal, ich habe den ECHTEN.“ Er kommt mit einem anderen Kapuzenpullover zurück, der noch mehr wie der Markenpullover aussieht, aber dennoch eine Fälschung ist. Nach mehreren Versuchen dieser Artwork bringt Ihnen der Verkäufer eine nicht zu unterscheidende Kopie des legendären ExpensiveButNotWorthIt und Sie kaufen ihn bereitwillig. So funktionieren die GANs im Grunde!

Im Fall von GANs nennt man Sie Diskriminator (D). Das Ziel eines Diskriminators ist es, zwischen einem echten und einem gefälschten Objekt zu unterscheiden oder die Aufgabe der binären Klassifizierung zu lösen. Der Verkäufer wird Generator (G) genannt, da er versucht, eine hochwertige Fälschung zu erzeugen. Diskriminator und Generator werden unabhängig voneinander trainiert, um sich gegenseitig zu übertreffen. Daher erhalten wir am Ende eine hochwertige Fälschung.

GAN-Architektur. Lizenz.

Der Trainingsprozess sieht ursprünglich folgendermaßen aus:

  1. Beispiel für Eingangsrauschen (in unserem Fall Bilder mit Wolken).
  2. Geben Sie G das Rauschen weiter und sammeln Sie die Vorhersage.
  3. Berechnen Sie den D-Verlust, indem Sie zwei Vorhersagen einholen, eine für die Ausgabe von G und eine für die realen Daten.
  4. Aktualisieren Sie die Gewichte von D.
  5. Probieren Sie das Eingangsrauschen erneut aus.
  6. Geben Sie G das Rauschen weiter und sammeln Sie die Vorhersage.
  7. Berechnen Sie den G-Verlust, indem Sie seine Vorhersage in D einspeisen.
  8. Aktualisieren Sie die Gewichte von G.
Trainingsschleife für GANs. Quelle: (1).

Mit anderen Worten können wir eine Wertfunktion V(G,D) definieren:

Quelle: (1).

wo wir den Begriff minimieren wollen log(1-D(G(z))) um G zu trainieren und zu maximieren log D(x) um D zu trainieren (in dieser Notation x – reale Datenprobe und z – Rauschen).

Versuchen wir jetzt, es in PyTorch zu implementieren!

Im Originalartikel sprechen die Autoren von der Verwendung von Multilayer Perceptron (MLP); es wird auch oft einfach als ANN bezeichnet, aber ich möchte einen etwas komplizierteren Ansatz ausprobieren – ich möchte die UNet-Architektur (5) als Generator und ResNet (6) als Diskriminator verwenden. Dies sind beides bekannte CNN-Architekturen, daher werde ich sie hier nicht erklären (lassen Sie mich in den Kommentaren wissen, ob ich einen separaten Artikel schreiben soll).

Lasst sie uns bauen. Diskriminator:

import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.useful as F
from torch.utils.knowledge import Dataset, DataLoader
from torchvision import transforms
from torch.utils.knowledge import Subset
class ResidualBlock(nn.Module):
def __init__(self, in_channels, out_channels, stride = 1, downsample = None):
tremendous(ResidualBlock, self).__init__()
self.conv1 = nn.Sequential(
nn.Conv2d(in_channels, out_channels, kernel_size = 3, stride = stride, padding = 1),
nn.BatchNorm2d(out_channels),
nn.ReLU())
self.conv2 = nn.Sequential(
nn.Conv2d(out_channels, out_channels, kernel_size = 3, stride = 1, padding = 1),
nn.BatchNorm2d(out_channels))
self.downsample = downsample
self.relu = nn.ReLU()
self.out_channels = out_channels

def ahead(self, x):
residual = x
out = self.conv1(x)
out = self.conv2(out)
if self.downsample:
residual = self.downsample(x)
out += residual
out = self.relu(out)
return out

class ResNet(nn.Module):
def __init__(self, block=ResidualBlock, all_connections=(3,4,6,3)):
tremendous(ResNet, self).__init__()
self.inputs = 16
self.conv1 = nn.Sequential(
nn.Conv2d(3, 16, kernel_size = 3, stride = 1, padding = 1),
nn.BatchNorm2d(16),
nn.ReLU()) #16x64x64
self.maxpool = nn.MaxPool2d(kernel_size = 2, stride = 2) #16x32x32

self.layer0 = self.makeLayer(block, 16, all_connections(0), stride = 1) #connections = 3, form: 16x32x32
self.layer1 = self.makeLayer(block, 32, all_connections(1), stride = 2)#connections = 4, form: 32x16x16
self.layer2 = self.makeLayer(block, 128, all_connections(2), stride = 2)#connections = 6, form: 1281x8x8
self.layer3 = self.makeLayer(block, 256, all_connections(3), stride = 2)#connections = 3, form: 256x4x4
self.avgpool = nn.AvgPool2d(4, stride=1)
self.fc = nn.Linear(256, 1)

def makeLayer(self, block, outputs, connections, stride=1):
downsample = None
if stride != 1 or self.inputs != outputs:
downsample = nn.Sequential(
nn.Conv2d(self.inputs, outputs, kernel_size=1, stride=stride),
nn.BatchNorm2d(outputs),
)
layers = ()
layers.append(block(self.inputs, outputs, stride, downsample))
self.inputs = outputs
for i in vary(1, connections):
layers.append(block(self.inputs, outputs))

return nn.Sequential(*layers)

def ahead(self, x):
x = self.conv1(x)
x = self.maxpool(x)
x = self.layer0(x)
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.avgpool(x)
x = x.view(-1, 256)
x = self.fc(x).flatten()
return F.sigmoid(x)

Generator:


class DoubleConv(nn.Module):
def __init__(self, in_channels, out_channels):
tremendous(DoubleConv, self).__init__()
self.double_conv = nn.Sequential(
nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1),
nn.BatchNorm2d(out_channels),
nn.ReLU(inplace=True),
nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1),
nn.BatchNorm2d(out_channels),
nn.ReLU(inplace=True)
)

def ahead(self, x):
return self.double_conv(x)

class UNet(nn.Module):
def __init__(self):
tremendous().__init__()
self.conv_1 = DoubleConv(3, 32) # 32x64x64
self.pool_1 = nn.MaxPool2d(kernel_size=2, stride=2) # 32x32x32

self.conv_2 = DoubleConv(32, 64) #64x32x32
self.pool_2 = nn.MaxPool2d(kernel_size=2, stride=2) #64x16x16

self.conv_3 = DoubleConv(64, 128) #128x16x16
self.pool_3 = nn.MaxPool2d(kernel_size=2, stride=2) #128x8x8

self.conv_4 = DoubleConv(128, 256) #256x8x8
self.pool_4 = nn.MaxPool2d(kernel_size=2, stride=2) #256x4x4

self.conv_5 = DoubleConv(256, 512) #512x2x2

#DECODER
self.upconv_1 = nn.ConvTranspose2d(512, 256, kernel_size=2, stride=2) #256x4x4
self.conv_6 = DoubleConv(512, 256) #256x4x4

self.upconv_2 = nn.ConvTranspose2d(256, 128, kernel_size=2, stride=2) #128x8x8
self.conv_7 = DoubleConv(256, 128) #128x8x8

self.upconv_3 = nn.ConvTranspose2d(128, 64, kernel_size=2, stride=2) #64x16x16
self.conv_8 = DoubleConv(128, 64) #64x16x16

self.upconv_4 = nn.ConvTranspose2d(64, 32, kernel_size=2, stride=2) #32x32x32
self.conv_9 = DoubleConv(64, 32) #32x32x32

self.output = nn.Conv2d(32, 3, kernel_size = 3, stride = 1, padding = 1) #3x64x64

def ahead(self, batch):

conv_1_out = self.conv_1(batch)
conv_2_out = self.conv_2(self.pool_1(conv_1_out))
conv_3_out = self.conv_3(self.pool_2(conv_2_out))
conv_4_out = self.conv_4(self.pool_3(conv_3_out))
conv_5_out = self.conv_5(self.pool_4(conv_4_out))

conv_6_out = self.conv_6(torch.cat((self.upconv_1(conv_5_out), conv_4_out), dim=1))
conv_7_out = self.conv_7(torch.cat((self.upconv_2(conv_6_out), conv_3_out), dim=1))
conv_8_out = self.conv_8(torch.cat((self.upconv_3(conv_7_out), conv_2_out), dim=1))
conv_9_out = self.conv_9(torch.cat((self.upconv_4(conv_8_out), conv_1_out), dim=1))

output = self.output(conv_9_out)

return F.sigmoid(output)

Jetzt müssen wir unsere Daten in Practice/Take a look at aufteilen und sie in einen Torch-Datensatz packen:

class dataset(Dataset):
def __init__(self, batch_size, images_paths, targets, img_size = 64):
self.batch_size = batch_size
self.img_size = img_size
self.images_paths = images_paths
self.targets = targets
self.len = len(self.images_paths) // batch_size

self.remodel = transforms.Compose((
transforms.ToTensor(),
))

self.batch_im = (self.images_paths(idx * self.batch_size:(idx + 1) * self.batch_size) for idx in vary(self.len))
self.batch_t = (self.targets(idx * self.batch_size:(idx + 1) * self.batch_size) for idx in vary(self.len))

def __getitem__(self, idx):
pred = torch.stack((
self.remodel(Picture.open(be part of(path_input,file_name)))
for file_name in self.batch_im(idx)
))
goal = torch.stack((
self.remodel(Picture.open(be part of(path_target,file_name)))
for file_name in self.batch_im(idx)
))
return pred, goal

def __len__(self):
return self.len

Perfekt. Es ist Zeit, die Trainingsschleife zu schreiben. Bevor wir das tun, definieren wir unsere Verlustfunktionen und den Optimierer:

gadget = torch.gadget("cuda" if torch.cuda.is_available() else "cpu")

batch_size = 64
num_epochs = 15
learning_rate_D = 1e-5
learning_rate_G = 1e-4

discriminator = ResNet()
generator = UNet()

bce = nn.BCEWithLogitsLoss()
l1loss = nn.L1Loss()

optimizer_D = optim.Adam(discriminator.parameters(), lr=learning_rate_D)
optimizer_G = optim.Adam(generator.parameters(), lr=learning_rate_G)

scheduler_D = optim.lr_scheduler.StepLR(optimizer_D, step_size=10, gamma=0.1)
scheduler_G = optim.lr_scheduler.StepLR(optimizer_G, step_size=10, gamma=0.1)

Wie Sie sehen, unterscheiden sich diese Verluste von dem Bild mit dem GAN-Algorithmus. Insbesondere habe ich L1Loss hinzugefügt. Die Idee ist, dass wir nicht einfach ein zufälliges Bild aus Rauschen erzeugen, sondern die meisten Informationen aus der Eingabe behalten und nur das Rauschen entfernen möchten. Der G-Verlust beträgt additionally:

G_Verlust = log(1 − D(G(z))) + 𝝀 |G(z)-y|

statt nur

G_Verlust = log(1 − D(G(z)))

𝝀 ist ein beliebiger Koeffizient, der zwei Komponenten der Verluste ausgleicht.

Lassen Sie uns abschließend die Daten aufteilen, um den Trainingsprozess zu starten:

test_ratio, train_ratio = 0.3, 0.7
num_test = int(len(listdir(path_target))*test_ratio)
num_train = int((int(len(listdir(path_target)))-num_test))

img_size = (64, 64)

print("Variety of prepare samples:", num_train)
print("Variety of check samples:", num_test)

random.seed(231)
train_idxs = np.array(random.pattern(vary(num_test+num_train), num_train))
masks = np.ones(num_train+num_test, dtype=bool)
masks(train_idxs) = False

photos = {}
options = random.pattern(listdir(path_input),num_test+num_train)
targets = random.pattern(listdir(path_target),num_test+num_train)

random.Random(231).shuffle(options)
random.Random(231).shuffle(targets)

train_input_img_paths = np.array(options)(train_idxs)
train_target_img_path = np.array(targets)(train_idxs)
test_input_img_paths = np.array(options)(masks)
test_target_img_path = np.array(targets)(masks)

train_loader = dataset(batch_size=batch_size, img_size=img_size, images_paths=train_input_img_paths, targets=train_target_img_path)
test_loader = dataset(batch_size=batch_size, img_size=img_size, images_paths=test_input_img_paths, targets=test_target_img_path)

Jetzt können wir unsere Trainingsschleife ausführen:

train_loss_G, train_loss_D, val_loss_G, val_loss_D = (), (), (), ()
all_loss_G, all_loss_D = (), ()
best_generator_epoch_val_loss, best_discriminator_epoch_val_loss = -np.inf, -np.inf
for epoch in vary(num_epochs):

discriminator.prepare()
generator.prepare()

discriminator_epoch_loss, generator_epoch_loss = 0, 0

for inputs, targets in train_loader:
inputs, true = inputs, targets

'''1. Coaching the Discriminator (ResNet)'''
optimizer_D.zero_grad()

pretend = generator(inputs).detach()

pred_fake = discriminator(pretend).to(gadget)
loss_fake = bce(pred_fake, torch.zeros(batch_size, gadget=gadget))

pred_real = discriminator(true).to(gadget)
loss_real = bce(pred_real, torch.ones(batch_size, gadget=gadget))

loss_D = (loss_fake+loss_real)/2

loss_D.backward()
optimizer_D.step()

discriminator_epoch_loss += loss_D.merchandise()
all_loss_D.append(loss_D.merchandise())

'''2. Coaching the Generator (UNet)'''
optimizer_G.zero_grad()

pretend = generator(inputs)
pred_fake = discriminator(pretend).to(gadget)

loss_G_bce = bce(pred_fake, torch.ones_like(pred_fake, gadget=gadget))
loss_G_l1 = l1loss(pretend, targets)*100
loss_G = loss_G_bce + loss_G_l1
loss_G.backward()
optimizer_G.step()

generator_epoch_loss += loss_G.merchandise()
all_loss_G.append(loss_G.merchandise())

discriminator_epoch_loss /= len(train_loader)
generator_epoch_loss /= len(train_loader)
train_loss_D.append(discriminator_epoch_loss)
train_loss_G.append(generator_epoch_loss)

discriminator.eval()
generator.eval()

discriminator_epoch_val_loss, generator_epoch_val_loss = 0, 0

with torch.no_grad():
for inputs, targets in test_loader:
inputs, targets = inputs, targets

pretend = generator(inputs)
pred = discriminator(pretend).to(gadget)

loss_G_bce = bce(pretend, torch.ones_like(pretend, gadget=gadget))
loss_G_l1 = l1loss(pretend, targets)*100
loss_G = loss_G_bce + loss_G_l1
loss_D = bce(pred.to(gadget), torch.zeros(batch_size, gadget=gadget))

discriminator_epoch_val_loss += loss_D.merchandise()
generator_epoch_val_loss += loss_G.merchandise()

discriminator_epoch_val_loss /= len(test_loader)
generator_epoch_val_loss /= len(test_loader)

val_loss_D.append(discriminator_epoch_val_loss)
val_loss_G.append(generator_epoch_val_loss)

print(f"------Epoch ({epoch+1}/{num_epochs})------nTrain Loss D: {discriminator_epoch_loss:.4f}, Val Loss D: {discriminator_epoch_val_loss:.4f}")
print(f'Practice Loss G: {generator_epoch_loss:.4f}, Val Loss G: {generator_epoch_val_loss:.4f}')

if discriminator_epoch_val_loss > best_discriminator_epoch_val_loss:
discriminator_epoch_val_loss = best_discriminator_epoch_val_loss
torch.save(discriminator.state_dict(), "discriminator.pth")
if generator_epoch_val_loss > best_generator_epoch_val_loss:
generator_epoch_val_loss = best_generator_epoch_val_loss
torch.save(generator.state_dict(), "generator.pth")
#scheduler_D.step()
#scheduler_G.step()

fig, ax = plt.subplots(1,3)
ax(0).imshow(np.transpose(inputs.numpy()(7), (1,2,0)))
ax(1).imshow(np.transpose(targets.numpy()(7), (1,2,0)))
ax(2).imshow(np.transpose(pretend.detach().numpy()(7), (1,2,0)))
plt.present()

Nachdem der Code fertig ist, können wir die Verluste plotten. Dieser Code wurde teilweise übernommen von diese coole Webseite:

from matplotlib.font_manager import FontProperties

background_color = '#001219'
font = FontProperties(fname='LexendDeca-VariableFont_wght.ttf')
fig, ax = plt.subplots(1, 2, figsize=(16, 9))
fig.set_facecolor(background_color)
ax(0).set_facecolor(background_color)
ax(1).set_facecolor(background_color)

ax(0).plot(vary(len(all_loss_G)), all_loss_G, colour='#bc6c25', lw=0.5)
ax(1).plot(vary(len(all_loss_D)), all_loss_D, colour='#00b4d8', lw=0.5)

ax(0).scatter(
(np.array(all_loss_G).argmax(), np.array(all_loss_G).argmin()),
(np.array(all_loss_G).max(), np.array(all_loss_G).min()),
s=30, colour='#bc6c25',
)
ax(1).scatter(
(np.array(all_loss_D).argmax(), np.array(all_loss_D).argmin()),
(np.array(all_loss_D).max(), np.array(all_loss_D).min()),
s=30, colour='#00b4d8',
)

ax_text(
np.array(all_loss_G).argmax()+60, np.array(all_loss_G).max()+0.1,
f'{spherical(np.array(all_loss_G).max(),1)}',
fontsize=13, colour='#bc6c25',
font=font,
ax=ax(0)
)
ax_text(
np.array(all_loss_G).argmin()+60, np.array(all_loss_G).min()-0.1,
f'{spherical(np.array(all_loss_G).min(),1)}',
fontsize=13, colour='#bc6c25',
font=font,
ax=ax(0)
)

ax_text(
np.array(all_loss_D).argmax()+60, np.array(all_loss_D).max()+0.01,
f'{spherical(np.array(all_loss_D).max(),1)}',
fontsize=13, colour='#00b4d8',
font=font,
ax=ax(1)
)
ax_text(
np.array(all_loss_D).argmin()+60, np.array(all_loss_D).min()-0.005,
f'{spherical(np.array(all_loss_D).min(),1)}',
fontsize=13, colour='#00b4d8',
font=font,
ax=ax(1)
)
for i in vary(2):
ax(i).tick_params(axis='x', colours='white')
ax(i).tick_params(axis='y', colours='white')
ax(i).spines('left').set_color('white')
ax(i).spines('backside').set_color('white')
ax(i).set_xlabel('Epoch', colour='white', fontproperties=font, fontsize=13)
ax(i).set_ylabel('Loss', colour='white', fontproperties=font, fontsize=13)

ax(0).set_title('Generator', colour='white', fontproperties=font, fontsize=18)
ax(1).set_title('Discriminator', colour='white', fontproperties=font, fontsize=18)
plt.savefig('Loss.jpg')
plt.present()
# ax(0).set_axis_off()
# ax(1).set_axis_off()

[ad_2]

]]>
http://chatgpz.de/machine-learning/loeschen-von-wolken-aus-satellitenbildern-mithilfe-von-gans-generative-adversarial-networks-von-aleksei-rozanov-juni-2024/feed/ 0 1441