Gleichgewichtete Batch-Generierung für unbalancierte Datensätze

PythonPythonBeginner
Jetzt üben

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

In diesem Projekt lernst du, wie du einen unbalancierten Datenpipeline implementierst, der unbalancierte Datensätze verarbeiten und Batches mit annähernd balancierten Klassenverteilungen generieren kann. Dies ist eine häufige Aufgabe in der Maschinellen Lernen, bei der der Datensatz möglicherweise erheblich mehr Proben von einer Klasse im Vergleich zu anderen hat, was zu einem verzerrten Modelltraining und schlechter Leistung führen kann.

🎯 Aufgaben

In diesem Projekt wirst du lernen:

  • Wie du die Funktionalität des Upsamplings und Downsamplings implementierst, um die Stichprobenverteilung innerhalb eines Batches zu balancieren.
  • Wie du einen Batch von Proben mit einer Stichprobenanzahl ausgibst, die der Batchgröße entspricht, wobei die Verteilung der Labels innerhalb des Batches so gleichmäßig wie möglich ist.
  • Wie du die unbalancierte Datenpipeline testest, um sicherzustellen, dass sie wie erwartet funktioniert.

🏆 Errungenschaften

Nach Abschluss dieses Projekts wirst du in der Lage sein:

  • Unbalancierte Datensätze in der Maschinellen Lernen zu behandeln.
  • Techniken für Upsampling und Downsampling anzuwenden, um die Klassenverteilungen zu balancieren.
  • Einen Datenpipeline zu implementieren, der aus einem unbalancierten Datensatz balancierte Batches generieren kann.

Implementiere Upsampling und Downsampling

In diesem Schritt lernst du, wie du die Funktionalität des Upsamplings und Downsamplings implementierst, um die Stichprobenverteilung innerhalb eines Batches zu balancieren.

Öffne die Datei unbalanced_data_pipeline.py, die sich im Verzeichnis /home/labex/project befindet.

In der Funktion unbalanced_data_pipeline beginne mit der Erstellung eines defaultdict namens counter, um die Merkmalsvektoren und ihre zugehörigen One-Hot-Labelvektoren zu speichern.

    counter = defaultdict(list)
    for x, y in data:
        counter[tuple(y)].append(x)

Dies gruppiert die Daten nach ihren Labelvektoren, was es einfacher macht, Upsampling und Downsampling durchzuführen.

Als nächstes berechne die Anzahl der Stichproben, die in jedem Batch für jedes Label enthalten sein sollen. Dies kann durch die Division der Batchgröße durch die Anzahl der eindeutigen Label erfolgen, und der verbleibende Rest wird dann in der Variable num_left gespeichert.

    batch_data = []
    pre_num = batch_size // len(counter.keys())
    num_left = batch_size % len(counter.keys())

Jetzt iteriere durch das counter-Dictionary und wähle zufällig die erforderliche Anzahl von Stichproben für jedes Label aus. Füge diese Stichproben zur Liste batch_data hinzu.

    for y, x in counter.items():
        samples = random.sample(x, pre_num)
        batch_data.extend([[sample, list(y)] for sample in samples])

Schließlich behandle die verbleibenden Stichproben, indem du zufällig ein Label und eine Stichprobe aus der entsprechenden Liste wählst und sie zur Liste batch_data hinzufügst.

    for _ in range(num_left):
        y = random.choice(list(counter.keys()))
        x = random.choice(counter[y])
        batch_data.append([x, list(y)])

Gebe die Liste batch_data zurück.

    return batch_data

In diesem Schritt hast du die Funktionalität des Upsamplings und Downsamplings implementiert, um die Stichprobenverteilung innerhalb eines Batches zu balancieren. Die Funktion unbalanced_data_pipeline nimmt jetzt die Eingabedaten und die Batchgröße entgegen und gibt eine Liste von Batches mit annähernd balancierten Klassenverteilungen zurück.

✨ Lösung prüfen und üben

Teste die unbalancierte Datenpipeline

In diesem Schritt wirst du die Funktion unbalanced_data_pipeline testen, um sicherzustellen, dass sie wie erwartet funktioniert.

Füge den folgenden Code in die Datei unbalanced_data_pipeline.py hinzu.

if __name__ == "__main__":
    data = [
        [[1, 2, 5], [1, 0]],
        [[1, 6, 0], [1, 0]],
        [[4, 1, 8], [1, 0]],
        [[7, 0, 4], [0, 1]],
        [[5, 9, 4], [0, 1]],
        [[2, 0, 1], [0, 1]],
        [[1, 9, 3], [0, 1]],
        [[5, 5, 5], [0, 1]],
        [[8, 4, 0], [0, 1]],
        [[9, 6, 3], [0, 1]],
        [[7, 7, 0], [0, 1]],
        [[0, 3, 4], [0, 1]],
     ]
    for epoch in range(10):
        batch_data = unbalanced_data_pipeline(data, 6)
        batch_data = list(batch_data)
        print(f"{epoch=}, {batch_data=}")

Im Block if __name__ == "__main__": rufen wir die Funktion unbalanced_data_pipeline mit den Beispiel-Daten und einer Batchgröße von 6 auf.

Führe die Datei unbalanced_data_pipeline.py aus, um die Ausgabe zu sehen.

python unbalanced_data_pipeline.py

Die Ausgabe sollte ähnlich dem in der ursprünglichen Aufgabe angegebenen Beispiel aussehen:

epoch=0, batch_data=[[[1, 2, 5], [1, 0]], [[4, 1, 8], [1, 0]], [[1, 6, 0], [1, 0]], [[2, 0, 1], [0, 1]], [[7, 0, 4], [0, 1]], [[5, 9, 4], [0, 1]]]
epoch=1, batch_data=[[[4, 1, 8], [1, 0]], [[1, 2, 5], [1, 0]], [[1, 6, 0], [1, 0]], [[2, 0, 1], [0, 1]], [[9, 6, 3], [0, 1]], [[1, 9, 3], [0, 1]]]
epoch=2, batch_data=[[[4, 1, 8], [1, 0]], [[1, 2, 5], [1, 0]], [[1, 6, 0], [1, 0]], [[5, 5, 5], [0, 1]], [[7, 0, 4], [0, 1]], [[8, 4, 0], [0, 1]]]
epoch=3, batch_data=[[[1, 2, 5], [1, 0]], [[1, 6, 0], [1, 0]], [[4, 1, 8], [1, 0]], [[7, 7, 0], [0, 1]], [[8, 4, 0], [0, 1]], [[0, 3, 4], [0, 1]]]
epoch=4, batch_data=[[[4, 1, 8], [1, 0]], [[1, 6, 0], [1, 0]], [[1, 2, 5], [1, 0]], [[5, 5, 5], [0, 1]], [[0, 3, 4], [0, 1]], [[8, 4, 0], [0, 1]]]
epoch=5, batch_data=[[[1, 6, 0], [1, 0]], [[4, 1, 8], [1, 0]], [[1, 2, 5], [1, 0]], [[2, 0, 1], [0, 1]], [[7, 0, 4], [0, 1]], [[7, 7, 0], [0, 1]]]
epoch=6, batch_data=[[[1, 2, 5], [1, 0]], [[1, 6, 0], [1, 0]], [[4, 1, 8], [1, 0]], [[8, 4, 0], [0, 1]], [[5, 9, 4], [0, 1]], [[0, 3, 4], [0, 1]]]
epoch=7, batch_data=[[[1, 2, 5], [1, 0]], [[1, 6, 0], [1, 0]], [[4, 1, 8], [1, 0]], [[2, 0, 1], [0, 1]], [[0, 3, 4], [0, 1]], [[1, 9, 3], [0, 1]]]
epoch=8, batch_data=[[[1, 6, 0], [1, 0]], [[4, 1, 8], [1, 0]], [[1, 2, 5], [1, 0]], [[7, 7, 0], [0, 1]], [[2, 0, 1], [0, 1]], [[0, 3, 4], [0, 1]]]
epoch=9, batch_data=[[[1, 2, 5], [1, 0]], [[4, 1, 8], [1, 0]], [[1, 6, 0], [1, 0]], [[7, 0, 4], [0, 1]], [[0, 3, 4], [0, 1]], [[5, 5, 5], [0, 1]]]

In diesem Schritt hast du die Funktion unbalanced_data_pipeline getestet, um sicherzustellen, dass sie wie erwartet funktioniert. Die Funktion sollte jetzt in der Lage sein, die unbalancierten Daten zu verarbeiten und Batches von Daten mit annähernd balancierten Klassenverteilungen zurückzugeben.

✨ Lösung prüfen und üben

Zusammenfassung

Herzlichen Glückwunsch! Du hast dieses Projekt abgeschlossen. Du kannst in LabEx weitere Labs absolvieren, um deine Fähigkeiten zu verbessern.