[PYTHON] Ingénierie de quantité de fonctionnalités voyageant avec Pokemon-Version numérique

Récemment, j'ai eu l'occasion de participer à des concours d'analyse de données, mais dans de nombreux cas, les résultats n'étaient pas efficaces à moins que des quantités de caractéristiques appropriées ne soient extraites en fonction de l'ensemble de données fourni dans le cadre du concours. Afin de résumer mes réflexions, je publierai un article dans l'espoir qu'il sera utile aux personnes en difficulté ainsi qu'à moi-même dans l'extraction de quantité de fonctionnalités. Cette fois, j'écrirai quelques caractéristiques des données numériques.

Concernant les données d'utilisation, j'ai utilisé Pokemon Dataset car il est plus facile d'imaginer les tendances des données si vous les connaissez. Les données se composent de drapeaux pour les types de Pokémon jusqu'à la 6ème génération (X / Y), les valeurs d'effort, les générations et les Pokémon légendaires.

Charge de la bibliothèque

import pandas as pd
import numpy as np

%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns

#Pour l'ingénierie de la quantité d'objets
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from sklearn.preprocessing import PowerTransformer

figsize  = (10, 7)

Lecture des données

df = pd.read_csv('./data/121_280_bundle_archive.zip')

Les données

# Name Type 1 Type 2 Total HP Attack Defense Sp. Atk Sp. Def Speed Generation Legendary
1 Bulbasaur Grass Poison 318 45 49 49 65 65 45 1 False
2 Ivysaur Grass Poison 405 60 62 63 80 80 60 1 False
3 Venusaur Grass Poison 525 80 82 83 100 100 80 1 False
3 VenusaurMega Venusaur Grass Poison 625 80 100 123 122 120 80 1 False
4 Charmander Fire NaN 309 39 52 43 60 50 65 1 False

mise à l'échelle

La mise à l'échelle est une image qui pousse la distribution de la quantité de caractéristiques dans une certaine plage sans la modifier (voir la figure). Il existe deux méthodes de mise à l'échelle typiques: la standardisation et la mise à l'échelle Min-Max.

Standardisation

La standardisation pousse la distribution des caractéristiques dans une distribution normale standard avec une moyenne de 0 et une variance de 1. La formule de normalisation est la suivante. Plus précisément, il est calculé en calculant la moyenne à partir de la quantité d'entités et en la divisant par l'écart type (à quelle distance il est de la moyenne). Il est plus facile d'imaginer regarder le code et les résultats après la mise à l'échelle.

#Standardisation
scaler = StandardScaler()
scaled_hp = scaler.fit_transform(df[['HP']])
scaled_hp = pd.DataFrame(scaled_hp, columns=['HP'])


#Comparer avant et après la normalisation
fig, ax = plt.subplots(1, 2, figsize=figsize)
sns.distplot(df['HP'], ax=ax[0])
ax[0].set_title('Untransformed')
sns.distplot(scaled_hp, ax=ax[1])
ax[1].set_title('Transformed')

plt.savefig('Standardisation.png')

標準化.png

Mise à l'échelle Min-Max

La mise à l'échelle Min-Max est utilisée pour pousser les fonctionnalités de 0 à 1. La formule de normalisation est la suivante. Puisque les valeurs maximale et minimale de la quantité d'entités sont utilisées, il existe un risque d'être facilement affecté par les valeurs aberrantes. Voici également le code et celui mis à l'échelle. Vous pouvez voir que la distribution reste la même et les valeurs sont poussées entre 0 et 1.

# Min-Mise à l'échelle maximale
scaler = MinMaxScaler()
scaled_hp = pd.DataFrame(scaler.fit_transform(df[['HP']]))

#Comparez avant et après la mise à l'échelle
fig, ax = plt.subplots(1, 2, figsize=figsize)
sns.distplot(df['HP'], ax=ax[0])
ax[0].set_title('Untransformed')
sns.distplot(scaled_hp, ax=ax[1])
ax[1].set_title('Transformed')

plt.savefig('./Min-Mise à l'échelle maximale.png')

Min-Maxスケーリング.png

Dois-je choisir la standardisation ou la mise à l'échelle?

Dans l'ingénierie de la quantité d'objets, si vous vous demandez si vous devez choisir la standardisation ou la mise à l'échelle, laquelle choisir? Fondamentalement, il s'agit d'une plaque de fer qui utilise la mise à l'échelle pour les données d'image et la normalisation pour d'autres valeurs numériques. Alors que les limites supérieure et inférieure des données d'image sont fixées entre 0 et 255, d'autres données peuvent avoir une large gamme de valeurs possibles. Par conséquent, si la mise à l'échelle est effectuée avec un grand nombre de valeurs aberrantes, la distribution mise à l'échelle peut être affectée par les valeurs aberrantes.

Conversion non linéaire

Les transformations non linéaires modifient la distribution des entités, par rapport à la normalisation et à la mise à l'échelle Min-Max, qui sont des transformations linéaires qui maintiennent la distribution des entités. Je pense qu'il est plus rapide de regarder la distribution convertie que d'entendre l'explication. Je vais introduire deux transformations non linéaires. Si la distribution des données ne suit pas la distribution normale, utilisez-la pour la convertir en une distribution normale.

Conversion de puissance

La transformation de puissance est une méthode typique de transformation non linéaire. La conversion du journal ne fonctionne pas si les données contiennent 0, donc généralement le journal (x + 1) est utilisé pour la conversion. Je publierai les données Pokémon converties.

#Conversion de puissance
log_hp = df['HP']
log_hp = pd.DataFrame(np.log1p(log_hp))

#Comparer avant et après la normalisation
fig, ax = plt.subplots(1, 2, figsize=figsize)
sns.distplot(df['HP'], ax=ax[0])
ax[0].set_title('Untransformed')
sns.distplot(log_hp, ax=ax[1])
ax[1].set_title('Transformed')

plt.savefig('Conversion de puissance.png')

べき変換.png

Conversion Box-Cox

La conversion Box-Cox n'est disponible que lorsque les données sont positives et convertit de force les données qui ne suivent pas la distribution normale en distribution normale. Il n'y a pas beaucoup de différence, mais voici une comparaison du code de conversion Box-Cox et de la distribution avant et après la conversion.

# Box-Conversion de Cox
#Vérifiez si les données prennent un nombre négatif
check = df['Speed'].min()
if check > 0:
    pt = PowerTransformer(method='box-cox')
    boxcox = pd.DataFrame(pt.fit_transform(df[['Speed']]), columns=['Speed'])

    # Box-Comparez les transformations de Cox
    fig, ax = plt.subplots(1, 2, figsize=figsize)
    sns.distplot(df['Speed'], ax=ax[0])
    ax[0].set_title('Untransformed')
    sns.distplot(boxcox, ax=ax[1])
    ax[1].set_title('Transformed')

    #Comparaison de la déformation et de la netteté
    print(f'Distorsion pré-conversion: {df["Speed"].skew(): .2f},kurtosis: {df["Speed"].kurtosis(): .2f}')
    print(f'Distorsion post-conversion: {boxcox["Speed"].skew(): .2f},kurtosis: {boxcox["Speed"].kurtosis(): .2f}')

    #Résultat de sortie
    #Distorsion pré-conversion:  0.36,kurtosis: -0.24
    #Distorsion post-conversion: -0.05,kurtosis: -0.40
    
    plt.savefig('Box-Conversion de Cox.png')

Box-Cox変換.png

Clipping Le découpage est littéralement une technique de découpage de données à un certain seuil. Les données supérieures ou inférieures au seuil (valeurs aberrantes) peuvent être exclues. Prenons l'exemple de Pokemon. Coupe les données avec une vitesse de 10 ou moins et de 150 ou plus.

# Clipping
# Clipping
clipping_hp = df['Speed'].clip(10, 130)

#Comparer avant et après le clip
fig, ax = plt.subplots(1, 2, figsize=figsize)
sns.distplot(df['Speed'], ax=ax[0])
ax[0].set_title('Unclipped')
sns.distplot(clipping_hp, ax=ax[1])
ax[1].set_title('Clipped')

plt.savefig('Clipping.png')

Clipping.png

Binning Le binning est une technique qui remplace les données comprises dans un certain intervalle par une valeur qui représente cet intervalle. A titre d'exemple, lorsque les données de vitesse sont divisées en sections de ~ 50, 50 ~ 100, 100 ~ 150, 150 ~ et remplacées par des variables différentes (ici, 4 sur 0, 1, 2, 3) pour chaque section. Jetons un coup d'œil au code. Vous avez remplacé les données d'une section particulière par une autre variable (données de catégorie dans ce cas).

# Binning
binned = pd.cut(df['Speed'], 4, labels=False)

print('---------Avant le binning----------')
print(df['Speed'].head())
print('---------Après le binning----------')
print(binned.head())

#Résultat d'exécution
# ---------Avant le binning----------
# 0    45
# 1    60
# 2    80
# 3    80
# 4    65
# Name: Speed, dtype: int64
# ---------Après le binning----------
# 0    0
# 1    1
# 2    1
# 3    1
# 4    1
# Name: Speed, dtype: int64

à la fin

La méthode de conversion à appliquer diffère selon qu'il s'agit de données d'image ou si elle suit une distribution normale de données. Il peut être intéressant d'expérimenter différentes données et de voir comment les données sont transformées. Dans le cas des données Pokemon, il n'y avait pas beaucoup de données qui s'écartaient de la distribution normale, mais [Ensemble de données pour la prévision des prix des logements](https://www.kaggle.com/c/house-prices-advanced-regression- Vous pouvez l'essayer avec des techniques)! IMG_9573.JPG

Recommended Posts

Ingénierie de quantité de fonctionnalités voyageant avec Pokemon-Version numérique
Ingénierie de la quantité de fonctionnalités voyageant avec des variables de catégorie Pokémon-
Note sur «l'ingénierie des fonctionnalités» de HJvanVeen
Ingénierie des fonctionnalités pour l'apprentissage automatique à partir de la partie 3 Échelle collaborative de Google
Seq2Seq (3) ~ Edition CopyNet ~ avec chainer
Prix des maisons Kaggle ① ~ Ingénierie des fonctionnalités ~