[PYTHON] Standardisieren Sie die nicht normale Verteilung mit einem robusten Z-Score

Min-Max-Normalisierung und Z-Score-Normalisierung (Standardisierung) werden häufig zur Normalisierung / Standardisierung verwendet. Dieses Mal habe ich einen robusten Z-Score ausprobiert und ihn mit der obigen Normalisierung verglichen.

min-max normalization Die Min-Max-Normalisierung ist eine Methode, mit der die Daten einen Minimalwert von 0 und einen Maximalwert von 1 haben und mit der folgenden Formel normalisiert werden.

x' = \frac{x-min(x)}{max(x)-min(x)}

In Python können Sie mit minmax_scale oder MinMaxScaler in sklearn.preprocessing rechnen. Diese Normalisierung setzt voraus, dass die Verteilung der Daten ** gleichmäßig verteilt ** ist.

Z-score Normalization(Standardization) Die Z-Score-Normalisierung ist eine Methode, um den Datenmittelwert 0 und die Verteilung 1 zu ermitteln und mit der folgenden Formel zu normalisieren. Dieser Wert wird als ** Z-Score ** bezeichnet. * Μ * repräsentiert den Mittelwert und * σ * repräsentiert die Standardabweichung.

x' = \frac{x-\mu}{\sigma}

In Python können Sie mit scale oder StandardScaler von sklearn.preprocessing rechnen. Diese Normalisierung setzt voraus, dass die Verteilung der Daten ** Normalverteilung ** ist.

Was tun, wenn es weder einheitlich noch normal ist?

In den tatsächlichen Daten war es oft weder gleichmäßig noch normal verteilt. Als ich untersuchte, was zu tun ist, fand ich den robusten Z-Score im folgenden Artikel.

Robuster Z-Score: Median und Quadranten, Standardisierung einschließlich nicht normaler Verteilung und Ausreißer (Memo) Ausschluss von Ausreißern mit Robust Z-Score

Unten habe ich es mit Python versucht.

Implementierung eines robusten Z-Scores

Weitere Informationen zum robusten Z-Score finden Sie im obigen Artikel. Das Folgende ist eine kurze Beschreibung und Implementierung.

Der Z-Score setzt eine Normalverteilung voraus. Um dies jedoch auf eine nicht normale Verteilung anzuwenden, ersetzen Sie zuerst den Mittelwert * μ * durch den Median und die Standardabweichung * σ * durch den Quadrantenbereich (IQR).

x' = \frac{x-median(x)}{IQR}

Diese Formel kann mit robust_scale oder RobustScaler in sklearn.preprocessing berechnet werden.

Darüber hinaus ist es mit Standardnormalverteilungen kompatibel. Der IQR, der der Standardnormalverteilung entspricht, wird als normalisierter Quadrantenbereich (NIQR) bezeichnet. Dies ist der IQR geteilt durch F (0,75) - F (0,25) = 1,3489. (F (x) ist die Umkehrung der kumulativen Verteilungsfunktion)

NIQR = \frac{IQR}{1.3489}

Robuster Z-Score ist der Nenner der obigen Formel, die von IQR zu NIQR ersetzt wird.

robust Z score = \frac{x-median(x)}{NIQR}

Wenn basierend auf dem oben Gesagten implementiert, ist die Funktion wie folgt.


def robust_z(x):
    from sklearn.preprocessing import robust_scale
    from scipy.stats import norm

    coefficient = norm.ppf(0.75)-norm.ppf(0.25)
    robust_z_score = robust_scale(x)*coefficient

    return robust_z_score

Vergleich von drei Normalisierungen

Ich möchte die drei bisherigen Normalisierungen vergleichen. Bereiten Sie zuerst die Daten vor. Ich möchte Daten, die weder einheitlich noch normal sind, also habe ich Daten vorbereitet, die einheitliche und normale Verteilung kombinieren.

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from scipy.stats import chisquare, shapiro, norm
from sklearn.preprocessing import minmax_scale, scale, robust_scale

np.random.seed(2020)

#Daten, die Gleichverteilung und Normalverteilung kombinieren.
data = np.concatenate((np.random.uniform(low=5.0, high=10.0, size=100),
                       np.random.normal(loc=5.0, scale=1.0, size=100)))

#Zeichnen Sie ein Histogramm.
fig, axes = plt.subplots()
axes.hist(data)
axes.set_title("Histogram of data")
fig.show()

row.png

Testen Sie, um sicherzustellen, dass diese Daten nicht gleichmäßig und nicht normal verteilt sind. Die Gleichmäßigkeit wurde durch den Chi-Quadrat-Test und die Normalität durch den (Shapiro-Wilck-Test) bestätigt.

#Berechnen Sie die Häufigkeitsverteilung.
hist_data, _ = np.histogram(data, bins="auto")

#Homogenitätstest (Chi-Quadrat-Test)
_, chisquare_p = chisquare(hist_data)
print("P-Wert des Gleichmäßigkeitstests (Chi-Quadrat-Test): {}".format(chisquare_p))

#Normalitätstest (Shapiro-Wilk-Test)
_, shapiro_p = shapiro(data)
print("P-Wert des Normalitätstests (Shapiro-Wilck-Test): {}".format(shapiro_p))

Die Ergebnisse sind wie folgt. Beide haben einen P-Wert von weniger als 0,05, so dass gesagt werden kann, dass sie weder einheitlich noch normal sind.

P-Wert des Gleichmäßigkeitstests (Chi-Quadrat-Test): 3.8086163670115985e-09
P-Wert des Normalitätstests (Shapiro-Wilck-Test): 8.850588528730441e-06

Verwenden Sie diese Daten, um die Min-Max-Normalisierung, den Z-Score und den robusten Z-Score zu berechnen und zu vergleichen.

#Normalisieren Sie mit jeder Methode und fügen Sie sie in den Datenrahmen ein.
score_df = pd.DataFrame(data=np.array([minmax_scale(data), scale(data), robust_z(data)]).T,
                        columns=["min-max", "Z-score", "robust Z-score"])


#Erstellen Sie ein Diagramm
fig, axs = plt.subplots(ncols=3, constrained_layout=True)

#Einstellung der Breite der x-Achse
xrange = {"min-max":(0,1),
          "Z-score":(-2.5,2.5),
          "robust Z-score":(-2.5,2.5)}

#Zeichnung jedes Histogramms
for i, score_name in enumerate(score_df.columns):
    
    axs[i].hist(score_df[score_name])
    axs[i].set_title(score_name)
    axs[i].set_xlim(xrange[score_name])

fig.show()

Das Ergebnis ist unten dargestellt. Es gibt keinen großen Unterschied. Dies kann je nach Verteilung der Daten einen Unterschied machen.

score.png

Vergleichen Sie mit Daten, die Ausreißer haben

Erstens bedeutet "robust" im robusten Z-Score, dass es robust gegen ** Ausreißer ** ist. Der robuste Z-Score wird auch zur Erkennung von Ausreißern verwendet. Daher möchte ich einen Ausreißer in die Daten einfügen und vergleichen. Versuchen Sie zum leichteren Vergleich, eine große Anzahl extremer Ausreißer einzugeben.

#Kombinieren Sie Ausreißer (gleichmäßige Verteilung) in den Daten.
outier = np.concatenate((data,
                         np.random.uniform(low=19.0, high=20.0, size=15)))

#Normalisieren Sie mit jeder Methode und fügen Sie sie in den Datenrahmen ein.
outlier_df = pd.DataFrame(data=np.array([minmax_scale(outier), scale(outier), robust_z(outier)]).T,
                          columns=["min-max", "Z-score", "robust Z-score"])

#Kombinieren Sie Datenrahmen ohne Ausreißer und mit Ausreißern.
concat_df = pd.concat([score_df, outlier_df],
               axis=1,
               keys=['without outlier', 'with outlier'])


#Erstellen Sie ein Diagramm
fig, axs = plt.subplots(nrows=2, ncols=3, constrained_layout=True)

#Einstellung der Breite der x-Achse
xrange = {"min-max":(0, 1),
          "Z-score":(-6.5, 6.5),
          "robust Z-score":(-6.5, 6.5)}

#Zeichnen eines Histogramms
for i, (data_name, score_name) in enumerate(concat_df.columns):
    row, col = divmod(i, 3)
    axs[row, col].hist(concat_df[(data_name, score_name)])
    axs[row, col].set_xlim(xrange[score_name])
    
    title = "\n".join([data_name, score_name])    
    axs[row, col].set_title(title)       
    
plt.show()

Das Ergebnis ist unten dargestellt. Oben ist, wenn es keinen Ausreißer gibt, und unten, wenn es einen Ausreißer gibt. Die Min-Max-Normalisierung reagiert sehr empfindlich auf Ausreißer. Der Z-Score wird auch von Ausreißern beeinflusst und unterscheidet sich stark von keinen Ausreißern. Der robuste Z-Score ist am wenigsten von Ausreißern betroffen und relativ ähnlich wie keine Ausreißer.

outlier.png

Schließlich

Der robuste Z-Score liefert das gleiche Ergebnis wie der Z-Score, wenn die Daten normal verteilt sind. Wenn Sie also verloren gehen, denke ich darüber nach, einen robusten Z-Score zu verwenden. Insbesondere hatte ich das Gefühl, dass ein robuster Z-Score effektiv ist, wenn ich auch Ausreißer verwenden möchte.

Recommended Posts

Standardisieren Sie die nicht normale Verteilung mit einem robusten Z-Score
3. Normalverteilung mit neuronalem Netz!
Standardisieren Sie nach Gruppen mit Pandas
Robuste lineare Regression mit Scikit-Learn