Comment puis-je coder un hot en Python?
j'ai un problème de classification d'apprentissage automatique avec 80% de variables catégoriques. Dois-je utiliser un encodage si je veux utiliser certains classificateur pour le classement? Puis-je transmettre les données à un classificateur sans l'encodage?
j'essaie de faire ce qui suit pour la sélection de fonctionnalité:
-
j'ai lu le dossier du train:
num_rows_to_read = 10000 train_small = pd.read_csv("../../dataset/train.csv", nrows=num_rows_to_read)
-
je changer le type de la catégorique fonctionnalités de "catégorie":
non_categorial_features = ['orig_destination_distance', 'srch_adults_cnt', 'srch_children_cnt', 'srch_rm_cnt', 'cnt'] for categorical_feature in list(train_small.columns): if categorical_feature not in non_categorial_features: train_small[categorical_feature] = train_small[categorical_feature].astype('category')
-
j'utilise un codage à chaud:
train_small_with_dummies = pd.get_dummies(train_small, sparse=True)
le problème est que la 3'rd est souvent coincée, bien que j'utilise une machine forte.
donc, sans l'encodage à chaud, Je ne peux pas faire de sélection de fonctionnalité, pour déterminer l'importance des fonctionnalités.
que recommandez-vous?
12 réponses
approche 1: vous pouvez utiliser get_dummies sur pandas dataframe.
exemple 1:
import pandas as pd
s = pd.Series(list('abca'))
pd.get_dummies(s)
Out[]:
a b c
0 1.0 0.0 0.0
1 0.0 1.0 0.0
2 0.0 0.0 1.0
3 1.0 0.0 0.0
exemple 2:
ce qui suit transformera une colonne donnée en une colonne chaude. Utilisez le préfixe pour avoir plusieurs mannequins.
approche 2: Utilisation Scikit-learn
avec un ensemble de données comportant trois caractéristiques et quatre échantillons, nous laissons l'encodeur trouver la valeur maximale par caractéristique et transformer les données en un encodage binaire à chaud.
>>> from sklearn.preprocessing import OneHotEncoder
>>> enc = OneHotEncoder()
>>> enc.fit([[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]])
OneHotEncoder(categorical_features='all', dtype=<class 'numpy.float64'>,
handle_unknown='error', n_values='auto', sparse=True)
>>> enc.n_values_
array([2, 3, 4])
>>> enc.feature_indices_
array([0, 2, 5, 9], dtype=int32)
>>> enc.transform([[0, 1, 1]]).toarray()
array([[ 1., 0., 0., 1., 0., 0., 1., 0., 0.]])
voici le lien pour cet exemple: http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html
vous pouvez le faire avec numpy.eye
et a en utilisant le mécanisme de sélection des éléments du tableau:
import numpy as np
nb_classes = 6
data = [[2, 3, 4, 0]]
def indices_to_one_hot(data, nb_classes):
"""Convert an iterable of indices to one-hot encoded labels."""
targets = np.array(data).reshape(-1)
return np.eye(nb_classes)[targets]
La valeur de retour de indices_to_one_hot(nb_classes, data)
est maintenant
array([[[ 0., 0., 1., 0., 0., 0.],
[ 0., 0., 0., 1., 0., 0.],
[ 0., 0., 0., 0., 1., 0.],
[ 1., 0., 0., 0., 0., 0.]]])
le .reshape(-1)
est là pour s'assurer que vous avez le bon format d'étiquettes (vous pourriez aussi avoir [[2], [3], [4], [0]]
).
tout d'abord, la manière la plus facile pour un encodage à chaud: utilisez Sklearn.
http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html
deuxièmement, je ne pense pas que l'utilisation de pandas pour un encodage à chaud soit aussi simple (non confirmé cependant)
la Création de variables muettes dans les pandas pour python
Enfin, est-il nécessaire pour vous d'une chaude encoder? Un encodage à chaud augmente exponentiellement le nombre de fonctionnalités, augmentant drastiquement le temps d'exécution de n'importe quel Classificateur ou n'importe quoi d'autre que vous allez exécuter. Surtout quand chaque caractéristique catégorique a plusieurs niveaux. Au lieu de cela, vous pouvez faire mannequin de codage.
utilisant l'encodage dummy fonctionne généralement bien, pour beaucoup moins de temps d'exécution et de complexité. Un sage professeur m'a dit un jour: "moins, C'est plus".
voici le code de ma fonction d'encodage personnalisée si vous voulez.
from sklearn.preprocessing import LabelEncoder
#Auto encodes any dataframe column of type category or object.
def dummyEncode(df):
columnsToEncode = list(df.select_dtypes(include=['category','object']))
le = LabelEncoder()
for feature in columnsToEncode:
try:
df[feature] = le.fit_transform(df[feature])
except:
print('Error encoding '+feature)
return df
EDIT: Comparaison pour être plus clair:
One-hot " encoding: convertir des niveaux de n à n-1 colonnes.
Index Animal Index cat mouse
1 dog 1 0 0
2 cat --> 2 1 0
3 mouse 3 0 1
vous pouvez voir comment cela explosera votre mémoire si vous avez beaucoup de différents types (ou niveaux) dans votre caractéristique catégorique. Gardez à l'esprit, c'est juste UNE colonne.
Code Fictif:
Index Animal Index Animal
1 dog 1 0
2 cat --> 2 1
3 mouse 3 2
convertir en représentations numériques à la place. Grandement sauve l'espace de la fonctionnalité, au prix d'un peu de précision.
vous pouvez utiliser numpy.les yeux de la fonction.
import numpy as np
def one_hot_encode(x, n_classes):
"""
One hot encode a list of sample labels. Return a one-hot encoded vector for each label.
: x: List of sample Labels
: return: Numpy array of one-hot encoded labels
"""
return np.eye(n_classes)[x]
def main():
list = [0,1,2,3,4,3,2,1,0]
n_classes = 5
one_hot_list = one_hot_encode(list, n_classes)
print(one_hot_list)
if __name__ == "__main__":
main()
résultat
D:\Desktop>python test.py
[[ 1. 0. 0. 0. 0.]
[ 0. 1. 0. 0. 0.]
[ 0. 0. 1. 0. 0.]
[ 0. 0. 0. 1. 0.]
[ 0. 0. 0. 0. 1.]
[ 0. 0. 0. 1. 0.]
[ 0. 0. 1. 0. 0.]
[ 0. 1. 0. 0. 0.]
[ 1. 0. 0. 0. 0.]]
un codage à chaud avec pandas est très facile:
def one_hot(df, cols):
"""
@param df pandas DataFrame
@param cols a list of columns to encode
@return a DataFrame with one-hot encoding
"""
for each in cols:
dummies = pd.get_dummies(df[each], prefix=each, drop_first=False)
df = pd.concat([df, dummies], axis=1)
return df
EDIT:
une autre façon de one_hot en utilisant sklearn LabelBinarizer
:
from sklearn.preprocessing import LabelBinarizer
label_binarizer = LabelBinarizer()
label_binarizer.fit(all_your_labels_list) # need to be global or remembered to use it later
def one_hot_encode(x):
"""
One hot encode a list of sample labels. Return a one-hot encoded vector for each label.
: x: List of sample Labels
: return: Numpy array of one-hot encoded labels
"""
return label_binarizer.transform(x)
Voici une solution utilisant DictVectorizer
et la méthode Pandas DataFrame.to_dict('records')
.
>>> import pandas as pd
>>> X = pd.DataFrame({'income': [100000,110000,90000,30000,14000,50000],
'country':['US', 'CAN', 'US', 'CAN', 'MEX', 'US'],
'race':['White', 'Black', 'Latino', 'White', 'White', 'Black']
})
>>> from sklearn.feature_extraction import DictVectorizer
>>> v = DictVectorizer()
>>> qualitative_features = ['country','race']
>>> X_qual = v.fit_transform(X[qualitative_features].to_dict('records'))
>>> v.vocabulary_
{'country=CAN': 0,
'country=MEX': 1,
'country=US': 2,
'race=Black': 3,
'race=Latino': 4,
'race=White': 5}
>>> X_qual.toarray()
array([[ 0., 0., 1., 0., 0., 1.],
[ 1., 0., 0., 1., 0., 0.],
[ 0., 0., 1., 0., 1., 0.],
[ 1., 0., 0., 0., 0., 1.],
[ 0., 1., 0., 0., 0., 1.],
[ 0., 0., 1., 1., 0., 0.]])
l'encodage à une température exige un peu plus que la conversion des valeurs en variables indicatrices. Typiquement, le processus ML exige que vous appliquiez ce codage plusieurs fois pour valider ou tester les ensembles de données et appliquer le modèle que vous construisez aux données observées en temps réel. Vous devez stocker le mapping (transformer) qui a été utilisé pour construire le modèle. Une bonne solution serait d'utiliser le DictVectorizer
ou LabelEncoder
(suivi de get_dummies
. Voici une fonction que vous pouvez utiliser:
def oneHotEncode2(df, le_dict = {}):
if not le_dict:
columnsToEncode = list(df.select_dtypes(include=['category','object']))
train = True;
else:
columnsToEncode = le_dict.keys()
train = False;
for feature in columnsToEncode:
if train:
le_dict[feature] = LabelEncoder()
try:
if train:
df[feature] = le_dict[feature].fit_transform(df[feature])
else:
df[feature] = le_dict[feature].transform(df[feature])
df = pd.concat([df,
pd.get_dummies(df[feature]).rename(columns=lambda x: feature + '_' + str(x))], axis=1)
df = df.drop(feature, axis=1)
except:
print('Error encoding '+feature)
#df[feature] = df[feature].convert_objects(convert_numeric='force')
df[feature] = df[feature].apply(pd.to_numeric, errors='coerce')
return (df, le_dict)
cela fonctionne sur une base de données pandas et pour chaque colonne de la base de données il crée et renvoie un mapping. Donc vous appelleriez ça comme ça:
train_data, le_dict = oneHotEncode2(train_data)
puis sur les données d'essai, l'appel est fait en passant le dictionnaire retourné de la formation:
test_data, _ = oneHotEncode2(test_data, le_dict)
une méthode équivalente est d'utiliser DictVectorizer
. Un poste sur le même est sur mon blog. J'en parle ici, car il fournit un certain raisonnement derrière cette approche plus simplement en utilisant get_dummies post (divulgation: c'est mon propre blog).
pandas as a la fonction intégrée "get_dummies" pour obtenir un encodage à chaud de cette colonne/s particulière.
une seule ligne de code pour un hot-encoding:
df=pd.concat([df,pd.get_dummies(df['column name'],prefix='column name')],axis=1).drop(['column name'],axis=1)
je sais que je suis en retard à cette fête, mais la façon la plus simple de coder à chaud une dataframe de manière automatisée est d'utiliser cette fonction:
def hot_encode(df):
obj_df = df.select_dtypes(include=['object'])
return pd.get_dummies(df, columns=obj_df.columns).values
pour ajouter à d'autres questions, permettez-moi de fournir comment je l'ai fait avec une fonction Python 2.0 en utilisant Numpy:
def one_hot(y_):
# Function to encode output labels from number indexes
# e.g.: [[5], [0], [3]] --> [[0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0]]
y_ = y_.reshape(len(y_))
n_values = np.max(y_) + 1
return np.eye(n_values)[np.array(y_, dtype=np.int32)] # Returns FLOATS
la ligne n_values = np.max(y_) + 1
pourrait être codée de façon à ce que vous utilisiez le bon nombre de neurones au cas où vous utilisiez des mini-lots par exemple.
projet de Démonstration/tutoriel où cette fonction a été utilisé: https://github.com/guillaume-chevalier/LSTM-Human-Activity-Recognition
j'ai utilisé ceci dans mon modèle acoustique: cela aide probablement dans le modèle ur.
def one_hot_encoding(x, n_out):
x = x.astype(int)
shape = x.shape
x = x.flatten()
N = len(x)
x_categ = np.zeros((N,n_out))
x_categ[np.arange(N), x] = 1
return x_categ.reshape((shape)+(n_out,))
ici j'ai essayé avec cette approche:
import numpy as np
#converting to one_hot
def one_hot_encoder(value, datal):
datal[value] = 1
return datal
def _one_hot_values(labels_data):
encoded = [0] * len(labels_data)
for j, i in enumerate(labels_data):
max_value = [0] * (np.max(labels_data) + 1)
encoded[j] = one_hot_encoder(i, max_value)
return np.array(encoded)