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é:

  1. 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)
    
  2. 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')
    
  3. 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?

44
demandé sur Martin Thoma 2016-05-18 10:26:52

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.

enter image description here

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

77
répondu Sayali Sonawane 2018-04-26 09:55:40

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]] ).

14
répondu Martin Thoma 2017-08-12 05:46:05

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.

13
répondu Wboy 2017-05-23 12:26:42

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.]]
11
répondu Dieter 2017-03-18 21:16:05

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)
9
répondu Qy Zuo 2017-07-11 07:59:23

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.]])
3
répondu Josh Morel 2018-03-02 20:41:15

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).

2
répondu Tukeys 2017-05-13 18:26:30

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)
1
répondu Arshdeep Singh 2018-09-13 04:36:04

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
1
répondu Rambatino 2018-09-25 23:33:45

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

0
répondu Guillaume Chevalier 2017-03-28 00:04:56

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,))
0
répondu yunus 2018-06-12 18:41:12

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)
-1
répondu Ayodhyankit Paul 2018-06-02 23:53:26