La normalisation min-max et la normalisation du score Z (standardisation) sont souvent utilisées pour la normalisation / normalisation. Cette fois, j'ai essayé le score Z robuste et je l'ai comparé à la normalisation ci-dessus.
min-max normalization La normalisation min-max est une méthode pour que les données aient une valeur minimale de 0 et une valeur maximale de 1, et se normalise avec la formule suivante.
x' = \frac{x-min(x)}{max(x)-min(x)}
En python, vous pouvez calculer avec minmax_scale
ou MinMaxScaler
dans sklearn.preprocessing
.
Cette normalisation suppose que la distribution des données est une ** distribution uniforme **.
Z-score Normalization(Standardization) La normalisation du score Z est une méthode pour rendre la moyenne des données 0 et la distribution 1 et la normaliser avec la formule suivante. Cette valeur est appelée ** Z-score **. * Μ * représente la moyenne et * σ * représente l'écart type.
x' = \frac{x-\mu}{\sigma}
En python, vous pouvez calculer avec scale
ou StandardScaler
de sklearn.preprocessing
.
Cette normalisation suppose que la distribution des données est une ** distribution normale **.
Dans les données réelles, ce n'était souvent ni une distribution uniforme ni normale, donc lorsque j'ai cherché ce qu'il fallait faire, j'ai trouvé le score Z robuste dans l'article suivant.
Score z robuste: médiane et quadrants, standardisation avec distribution non normale et valeurs aberrantes (Memo) Exclusion des valeurs aberrantes à l'aide du score z robuste
Ci-dessous, je l'ai essayé avec Python.
Pour plus d'informations sur le score Z robuste, veuillez lire l'article ci-dessus. Voici une brève description et mise en œuvre.
Le score Z suppose une distribution normale, mais pour l'appliquer à une distribution non normale, remplacez d'abord la moyenne * μ * par la médiane et l'écart-type * σ * par la plage de quadrants (IQR).
x' = \frac{x-median(x)}{IQR}
Cette formule peut être calculée avec robust_scale
ou RobustScaler
dans sklearn.preprocessing
.
De plus, il le rend compatible avec les distributions normales standard. L'IQR correspondant à la distribution normale standard est appelé la plage de quadrants normalisés (NIQR), qui est l'IQR divisé par F (0,75) --F (0,25) = 1,3489. (F (x) est l'inverse de la fonction de distribution cumulative)
NIQR = \frac{IQR}{1.3489}
Le score Z robuste est le dénominateur de la formule ci-dessus remplacée de IQR par NIQR.
robust Z score = \frac{x-median(x)}{NIQR}
Si elle est mise en œuvre sur la base de ce qui précède, la fonction sera la suivante.
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
Je voudrais comparer les trois normalisations qui sont sorties jusqu'à présent. Préparez d'abord les données. Je veux des données qui ne sont ni uniformes ni normales, j'ai donc préparé des données qui combinent une distribution uniforme et normale.
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)
#Données combinant une distribution uniforme et une distribution normale.
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)))
#Dessinez un histogramme.
fig, axes = plt.subplots()
axes.hist(data)
axes.set_title("Histogram of data")
fig.show()
Test pour confirmer que ces données ne sont pas uniformément distribuées et ne sont pas normalement distribuées. L'uniformité a été confirmée par le test du chi carré et la normalité a été confirmée par le (test de Shapiro-Wilck).
#Calculez la distribution de fréquence.
hist_data, _ = np.histogram(data, bins="auto")
#Test d'uniformité (test du chi carré)
_, chisquare_p = chisquare(hist_data)
print("Valeur P du test d'uniformité (test du chi carré): {}".format(chisquare_p))
#Test de normalité (test de Shapiro-Wilk)
_, shapiro_p = shapiro(data)
print("Valeur P du test de normalité (test de Shapiro-Wilck): {}".format(shapiro_p))
Les résultats sont les suivants. Les deux ont une valeur P inférieure à 0,05, on peut donc dire qu'ils ne sont ni uniformes ni normaux.
Valeur P du test d'uniformité (test du chi carré): 3.8086163670115985e-09
Valeur P du test de normalité (test de Shapiro-Wilck): 8.850588528730441e-06
Utilisez ces données pour calculer la normalisation min-max, le Z-score et le Z-score robuste et les comparer.
#Normaliser par chaque méthode et placez-le dans le bloc de données.
score_df = pd.DataFrame(data=np.array([minmax_scale(data), scale(data), robust_z(data)]).T,
columns=["min-max", "Z-score", "robust Z-score"])
#Créer un graphique
fig, axs = plt.subplots(ncols=3, constrained_layout=True)
#réglage de la largeur de l'axe x
xrange = {"min-max":(0,1),
"Z-score":(-2.5,2.5),
"robust Z-score":(-2.5,2.5)}
#Dessin de chaque histogramme
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()
Le résultat est présenté ci-dessous. Il n'y a pas beaucoup de différence. Cela peut faire une différence en fonction de la distribution des données.
En premier lieu, «robuste» dans le score Z robuste signifie qu'il est robuste contre les ** valeurs aberrantes **. Le score Z robuste est également utilisé pour la détection des valeurs aberrantes. Par conséquent, je voudrais mettre une valeur aberrante dans les données et comparer. Pour faciliter la comparaison, essayez de saisir un grand nombre de valeurs aberrantes extrêmes.
#Combinez les valeurs aberrantes (distribution uniforme) dans les données.
outier = np.concatenate((data,
np.random.uniform(low=19.0, high=20.0, size=15)))
#Normaliser par chaque méthode et placez-le dans le bloc de données.
outlier_df = pd.DataFrame(data=np.array([minmax_scale(outier), scale(outier), robust_z(outier)]).T,
columns=["min-max", "Z-score", "robust Z-score"])
#Combinez des trames de données sans valeurs aberrantes et avec des valeurs aberrantes.
concat_df = pd.concat([score_df, outlier_df],
axis=1,
keys=['without outlier', 'with outlier'])
#Créer un graphique
fig, axs = plt.subplots(nrows=2, ncols=3, constrained_layout=True)
#réglage de la largeur de l'axe x
xrange = {"min-max":(0, 1),
"Z-score":(-6.5, 6.5),
"robust Z-score":(-6.5, 6.5)}
#Dessiner un histogramme
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()
Le résultat est présenté ci-dessous. Le haut est lorsqu'il n'y a pas de valeur aberrante et le bas est lorsqu'il y a une valeur aberrante. La normalisation min-max est très sensible aux valeurs aberrantes. Le score Z est également affecté par les valeurs aberrantes et est très différent de l'absence de valeurs aberrantes. Le score Z robuste est le moins affecté par les valeurs aberrantes et est relativement similaire à l'absence de valeurs aberrantes.
Le score Z robuste donne le même résultat que le score Z lorsque les données sont normalement distribuées, je pense donc à utiliser un score Z robuste en cas de doute. En particulier, j'ai estimé qu'un score Z robuste est efficace lorsque je souhaite également utiliser des valeurs aberrantes.