Datenverteilung im maschinellen Lernen
Lerne, wie Datenverteilungen in Python funktionieren: Normal-, schiefe und gleichmäßige Verteilungen erkennen und verstehen.
Datenverteilung beschreibt, wie Werte über einen Datensatz verteilt sind — welche Werte häufig vorkommen, welche selten sind und wie weit sie sich vom Zentrum entfernen. Bevor man ein Machine-Learning-Modell trainiert, hilft das Verständnis der Datenverteilung dabei, den richtigen Algorithmus zu wählen, Anomalien zu erkennen, zu entscheiden, ob Features skaliert oder transformiert werden sollen, und versteckte Verzerrungen in Vorhersagen zu vermeiden.
Dieses Kapitel behandelt die häufigsten Verteilungsformen, wie man sie in Python mit NumPy und SciPy misst und was jede Verteilung für Modellierungsentscheidungen bedeutet.
Was ist eine Datenverteilung?
Eine Datenverteilung ist das Muster, wie häufig jeder Wert (oder Wertebereich) in einem Datensatz vorkommt. Wenn man eine Verteilung darstellt, sieht man in der Regel eine Kurve oder ein Histogramm, dessen Form viel über die zugrunde liegenden Daten verrät.
Die drei Eigenschaften, die jede Verteilung definieren, sind:
- Zentrum — wo sich die meisten Werte häufen (gemessen durch Mittelwert, Median und Modus)
- Streuung — wie weit Werte vom Zentrum abweichen (gemessen durch Standardabweichung und Interquartilsabstand)
- Form — ob die Verteilung symmetrisch, schief oder flach ist
Das Verständnis aller drei Eigenschaften ist notwendig, bevor Daten in ein Modell eingespeist werden.
Häufige Verteilungstypen
Normalverteilung
Die Normalverteilung (auch Gaußsche Verteilung genannt) ist die wichtigste Verteilung in der Statistik und im maschinellen Lernen. Ihr Histogramm bildet eine symmetrische Glockenkurve: Werte häufen sich um den Mittelwert, und die Häufigkeit nimmt auf beiden Seiten gleichmäßig ab.
Wesentliche Eigenschaften:
- Mittelwert, Median und Modus sind alle gleich.
- Etwa 68 % der Werte liegen innerhalb einer Standardabweichung vom Mittelwert, 95 % innerhalb von zwei und 99,7 % innerhalb von drei (die empirische Regel).
- Vollständig definiert durch zwei Parameter: Mittelwert (μ) und Standardabweichung (σ).
Viele reale Phänomene nähern sich einer Normalverteilung an — menschliche Körpergrößen, Messfehler und IQ-Werte sind klassische Beispiele. Algorithmen wie die lineare Diskriminanzanalyse, der Gaußsche Naive Bayes und die lineare Regression setzen normalverteilte Features voraus (oder profitieren davon).
import numpy as np
from scipy import stats
# Simulate 1 000 adult heights (cm) drawn from a normal distribution
rng = np.random.default_rng(seed=42)
heights = rng.normal(loc=170, scale=10, size=1000)
print(f"Mean: {np.mean(heights):.1f} cm")
print(f"Std: {np.std(heights):.1f} cm")
# Verify the empirical rule
within_1_std = np.sum(np.abs(heights - 170) < 10) / 1000 * 100
within_2_std = np.sum(np.abs(heights - 170) < 20) / 1000 * 100
within_3_std = np.sum(np.abs(heights - 170) < 30) / 1000 * 100
print(f"Within 1 std: {within_1_std:.1f}% (expected ~68%)")
print(f"Within 2 std: {within_2_std:.1f}% (expected ~95%)")
print(f"Within 3 std: {within_3_std:.1f}% (expected ~99.7%)")Ausgabe:
Mean: 169.7 cm
Std: 9.9 cm
Within 1 std: 68.8% (expected ~68%)
Within 2 std: 95.7% (expected ~95%)
Within 3 std: 99.8% (expected ~99.7%)Schiefe Verteilung
Eine schiefe Verteilung ist asymmetrisch: ein Ausläufer ist länger als der andere. Schiefe wird durch den Schiefekennwert gemessen — positive Werte zeigen eine Rechtsschiefen (positive Schiefe) an, negative Werte eine Linksschiefe (negative Schiefe), und Werte nahe null deuten auf annähernde Symmetrie hin.
Rechtsschiefe (positive Schiefe): der Ausläufer erstreckt sich nach rechts. Der Mittelwert wird durch eine kleine Anzahl sehr großer Werte über den Median gezogen. Einkommen und Hauspreise sind typische Beispiele — einige sehr hohe Einkommensbezieher oder teure Immobilien ziehen den Mittelwert weit über den Median.
Linksschiefe (negative Schiefe): der Ausläufer erstreckt sich nach links. Prüfungsergebnisse bei einem einfachen Test zeigen oft dieses Muster — die meisten Schüler erzielen nahezu Höchstnoten, aber einige schneiden sehr schlecht ab.
import numpy as np
from scipy import stats
# Right-skewed: a small number of very high values pull the mean up
salaries = np.array([30000, 32000, 34000, 35000, 36000, 38000,
40000, 42000, 45000, 55000, 70000, 120000, 200000])
print("--- Salary distribution ---")
print(f"Mean: {np.mean(salaries):.0f}") # pulled up by outliers
print(f"Median: {np.median(salaries):.0f}") # more representative center
print(f"Skewness: {stats.skew(salaries):.2f}") # positive = right skew
# Left-skewed: most values are high, a few are very low
exam_scores = np.array([40, 68, 75, 80, 82, 85, 88, 90, 91, 92, 93, 95, 98])
print("\n--- Exam score distribution ---")
print(f"Mean: {np.mean(exam_scores):.1f}")
print(f"Median: {np.median(exam_scores):.1f}")
print(f"Skewness: {stats.skew(exam_scores):.2f}") # negative = left skewAusgabe:
--- Salary distribution ---
Mean: 59769
Median: 40000
Skewness: 2.16
--- Exam score distribution ---
Mean: 82.8
Median: 88.0
Skewness: -1.77Wenn Schiefe vorhanden ist, ist der Mittelwert ein irreführendes Maß für das Zentrum. Der Median ist in der Regel ein besseres zusammenfassendes Maß für schiefe Daten.
Gleichmäßige Verteilung
Bei einer gleichmäßigen Verteilung ist jeder Wert (oder Wertebereich) gleich wahrscheinlich. Ein fairer sechsseitiger Würfel erzeugt eine gleichmäßige diskrete Verteilung; das zufällige Auswählen einer Gleitkommazahl zwischen 0 und 1 ergibt eine stetige gleichmäßige Verteilung.
import numpy as np
rng = np.random.default_rng(seed=42)
# Continuous uniform distribution between 0 and 1
uniform_data = rng.uniform(low=0, high=1, size=10000)
print(f"Mean: {np.mean(uniform_data):.3f} (expected 0.500)")
print(f"Std: {np.std(uniform_data):.3f} (expected ~0.289)")
print(f"Min: {np.min(uniform_data):.3f}")
print(f"Max: {np.max(uniform_data):.3f}")Ausgabe:
Mean: 0.497 (expected 0.500)
Std: 0.288 (expected ~0.289)
Min: 0.000
Max: 1.000Gleichmäßige Verteilungen treten beim Zufallssampling, bei der Datenerweiterung und als a-priori-Verteilungen in Bayesianischen Modellen auf.
Eine Verteilung in Python zusammenfassen
Berechne vor der Modellierung stets eine schnelle Zusammenfassung jedes Features. NumPy und SciPy decken gemeinsam die wichtigsten Statistiken ab:
import numpy as np
from scipy import stats
data = np.array([12, 15, 14, 10, 18, 14, 13, 16, 14, 12])
print("--- Distribution Summary ---")
print(f"Mean: {np.mean(data):.1f}")
print(f"Median: {np.median(data):.1f}")
print(f"Std: {np.std(data, ddof=1):.2f}") # sample std deviation
print(f"Min: {np.min(data)}")
print(f"Max: {np.max(data)}")
print(f"Skewness: {stats.skew(data):.3f}") # near 0 = symmetricAusgabe:
--- Distribution Summary ---
Mean: 13.8
Median: 14.0
Std: 2.25
Min: 10
Max: 18
Skewness: 0.200Ein Schiefewert nahe 0.200 zeigt, dass die Daten annähernd symmetrisch sind — keine ausgeprägte Schiefe in eine Richtung.
Test auf Normalverteilung
Einige Algorithmen setzen ausdrücklich voraus, dass Features normalverteilt sind. Der Shapiro-Wilk-Test ist der zuverlässigste Test für kleine Stichproben (n < 5.000). Er gibt eine Teststatistik W und einen p-Wert zurück. Ein p-Wert größer als 0,05 bedeutet, dass die Hypothese, die Daten seien normalverteilt, nicht abgelehnt werden kann.
import numpy as np
from scipy import stats
rng = np.random.default_rng(seed=42)
# Sample from a normal distribution
normal_sample = rng.normal(loc=0, scale=1, size=50)
stat, p = stats.shapiro(normal_sample)
print(f"Shapiro-Wilk: W={stat:.3f}, p={p:.3f}")
if p > 0.05:
print("Data appears to be normally distributed.")
else:
print("Data does not appear to be normally distributed.")Ausgabe:
Shapiro-Wilk: W=0.984, p=0.730
Data appears to be normally distributed.Wann man ihn verwendet: Wende den Shapiro-Wilk-Test an, wenn die Annahmen eines Modells ausdrücklich Normalverteilung erfordern — zum Beispiel vor der Verwendung eines parametrischen t-Tests oder der linearen Diskriminanzanalyse. Viele moderne Algorithmen (Gradient Boosting, Random Forests, neuronale Netze) sind nicht empfindlich gegenüber der Verteilungsform der Features, sodass dieser Test nicht immer notwendig ist.
Warum die Verteilungsform für die Modellierung wichtig ist
| Situation | Bedeutung | Vorgehensweise |
|---|---|---|
| Normalverteilte Features | Standardannahmen gelten | Parametrische Modelle direkt verwenden |
| Rechtsschiefe Features | Mittelwert ist überhöht; Ausreißer dominieren | Log- oder Quadratwurzeltransformation anwenden |
| Linksschiefe Features | Niedrige Werte sind Ausreißer | Quadrat- oder Spiegelungstransformation anwenden |
| Gleichmäßige Features | Keine zentrale Häufung | Oft in Ordnung; für distanzbasierte Modelle normalisieren |
| Multimodale Features | Mehrere Cluster | Daten aufteilen oder einen Clustering-Schritt einsetzen |
Umgang mit schiefen Daten durch Log-Transformation
Ein gängiges Mittel bei rechtsschiefen Daten ist die Log-Transformation, die große Werte komprimiert und kleine ausdehnt, was häufig zu einer Verteilung führt, die der Normalverteilung näher kommt.
import numpy as np
from scipy import stats
rng = np.random.default_rng(seed=7)
# Simulate log-normally distributed incomes (a common real-world pattern)
incomes = rng.lognormal(mean=10.5, sigma=0.5, size=1000)
print(f"Before transform — skewness: {stats.skew(incomes):.2f}")
log_incomes = np.log(incomes)
print(f"After log transform — skewness: {stats.skew(log_incomes):.2f}")Ausgabe:
Before transform — skewness: 1.44
After log transform — skewness: 0.01Nach der Log-Transformation sinkt die Schiefe von 1.44 auf nahezu null, was die Daten für Modelle, die Normalverteilung voraussetzen, deutlich besser geeignet macht.
Hinweis: Die Log-Transformation erfordert, dass alle Werte strikt positiv sind. Addiere eine kleine Konstante (z. B. np.log(x + 1)), wenn die Daten Nullen enthalten.
Datenverteilung visualisieren
Visualisierung ist der schnellste Weg, eine Verteilung zu untersuchen. Ein Histogramm unterteilt Werte in Klassen und zeigt, wie viele Beobachtungen in jede Klasse fallen. Verwende Matplotlib-Histogramme, um sie zu erstellen:
import numpy as np
import matplotlib.pyplot as plt
rng = np.random.default_rng(seed=42)
data = rng.normal(loc=170, scale=10, size=500)
plt.figure(figsize=(8, 4))
plt.hist(data, bins=30, color='steelblue', edgecolor='white')
plt.title("Height Distribution (Normal)")
plt.xlabel("Height (cm)")
plt.ylabel("Frequency")
plt.tight_layout()
plt.show()Für einen schnelleren Überblick über mehrere Features gleichzeitig kannst du ein Streudiagramm verwenden, um Beziehungen zwischen Verteilungen zu erkennen.
Verteilung und Feature-Skalierung
Wenn Features sehr unterschiedliche Verteilungen oder Skalen aufweisen, werden distanzbasierte Algorithmen (k-nächste Nachbarn, SVM, k-Means-Clustering) von Features mit dem größten Wertebereich dominiert. Feature-Skalierung ist die Standardlösung: StandardScaler normalisiert jedes Feature auf einen Mittelwert von 0 und eine Standardabweichung von 1, und MinMaxScaler komprimiert Werte in [0, 1].
Wähle den Skalierer basierend auf der zugrunde liegenden Verteilung:
- Normalverteilung →
StandardScaler(entfernt den Mittelwert, skaliert auf Einheitsvarianz) - Gleichmäßige oder begrenzte Verteilung →
MinMaxScaler(erhält die Form) - Stark schiefe Verteilung mit Ausreißern →
RobustScaler(verwendet Median und IQR, ignoriert Extremwerte)
Zusammenfassung
- Normalverteilung: symmetrische Glockenkurve; Mittelwert ≈ Median; geeignet für parametrische Modelle.
- Schiefe Verteilung: asymmetrisch; Mittelwert wird zum Ausläufer hin gezogen; Log- oder Potenztransformationen können die Schiefe verringern.
- Gleichmäßige Verteilung: alle Werte gleich wahrscheinlich; tritt beim Zufallssampling und als nicht-informative a-priori-Verteilungen auf.
- Verwende
scipy.stats.skew()zur Messung der Asymmetrie undscipy.stats.shapiro()zum formalen Test auf Normalverteilung. - Untersuche Verteilungen immer vor der Modellierung — die Form beeinflusst die Wahl des Algorithmus, die Transformation der Features und die anzuwendende Skalierungsstrategie.
Als Nächstes kannst du Normalverteilung von Daten erkunden, um einen tieferen Einblick in die Gaußsche Verteilung zu erhalten und zu erfahren, wie man sie mit SciPy erzeugt und damit arbeitet.