wake-up-neo.net

Wie kann ich eine heiße Kodierung in Python durchführen?

Ich habe ein Klassifizierungsproblem beim maschinellen Lernen mit 80% kategorialen Variablen. Muss ich eine heiße Kodierung verwenden, wenn ich einen Klassifizierer für die Klassifizierung verwenden möchte? Kann ich die Daten ohne Kodierung an einen Klassifikator übergeben?

Ich versuche Folgendes für die Funktionsauswahl zu tun:

  1. Ich habe die Zugakte gelesen:

    num_rows_to_read = 10000
    train_small = pd.read_csv("../../dataset/train.csv",   nrows=num_rows_to_read)
    
  2. Ich ändere den Typ der kategorialen Features in "Kategorie":

    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. Ich benutze eine heiße Kodierung:

    train_small_with_dummies = pd.get_dummies(train_small, sparse=True)
    

Das Problem ist, dass der 3. Teil oft hängen bleibt, obwohl ich eine starke Maschine benutze.

Ohne die eine heiße Kodierung kann ich also keine Merkmalsauswahl vornehmen, um die Wichtigkeit der Merkmale zu bestimmen.

Was empfehlen Sie?

82
avicohen

Ansatz 1: Sie können get_dummies für pandas dataframe. verwenden.

Beispiel 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

Beispiel 2:

Das Folgende wandelt eine gegebene Spalte in eine heiße um. Verwenden Sie das Präfix, um mehrere Dummies zu haben.

import pandas as pd

df = pd.DataFrame({
          'A':['a','b','a'],
          'B':['b','a','c']
        })
df
Out[]: 
   A  B
0  a  b
1  b  a
2  a  c

# Get one hot encoding of columns B
one_hot = pd.get_dummies(df['B'])
# Drop column B as it is now encoded
df = df.drop('B',axis = 1)
# Join the encoded df
df = df.join(one_hot)
df  
Out[]: 
       A  a  b  c
    0  a  0  1  0
    1  b  1  0  0
    2  a  0  0  1

Ansatz 2: Verwenden Sie Scikit-Learn

Bei einem Datensatz mit drei Features und vier Beispielen lässt der Encoder den Maximalwert pro Feature ermitteln und die Daten in eine binäre One-Hot-Codierung umwandeln.

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

Hier ist der Link für dieses Beispiel: http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html

120
Sayali Sonawane

Sie können dies mit numpy.eye und mithilfe des Auswahlmechanismus für Array-Elemente tun:

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]

Der Rückgabewert von indices_to_one_hot(nb_classes, data) ist jetzt

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

Mit der Funktion .reshape(-1) stellen Sie sicher, dass Sie das richtige Etikettenformat haben (möglicherweise haben Sie auch [[2], [3], [4], [0]]).

21
Martin Thoma

Erstens, der einfachste Weg zu einer heißen Kodierung: Verwenden Sie Sklearn.

http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html

Zweitens glaube ich nicht, dass die Verwendung von pandas für eine heiße Kodierung so einfach ist (obwohl nicht bestätigt)

Erstellen von Dummy-Variablen in pandas for python

Ist es für Sie schließlich erforderlich, eine heiße Kodierung vorzunehmen? Durch eine Hot-Codierung wird die Anzahl der Features exponentiell erhöht, wodurch sich die Laufzeit aller Klassifizierer oder anderer Elemente, die Sie ausführen möchten, drastisch erhöht. Vor allem, wenn jedes kategoriale Merkmal viele Ebenen hat. Stattdessen können Sie Dummy-Codierung durchführen.

Die Verwendung von Dummy-Codierung funktioniert normalerweise gut, und dies bei deutlich geringerer Laufzeit und Komplexität. Ein weiser Profi sagte mir einmal: "Weniger ist mehr".

Hier ist der Code für meine benutzerdefinierte Codierungsfunktion, wenn Sie möchten.

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: Vergleich um klarer zu sein:

One-Hot-Codierung: Konvertieren Sie n Ebenen in n-1 Spalten.

Index  Animal         Index  cat  mouse
  1     dog             1     0     0
  2     cat       -->   2     1     0
  3    mouse            3     0     1

Sie können sehen, wie dies Ihr Gedächtnis sprengt, wenn Sie in Ihrer Kategoriefunktion viele verschiedene Typen (oder Ebenen) haben. Denken Sie daran, dies ist nur eine Spalte.

Dummy-Codierung:

Index  Animal         Index  Animal
  1     dog             1      0   
  2     cat       -->   2      1 
  3    mouse            3      2

Konvertieren Sie stattdessen in numerische Darstellungen. Spart sehr viel Platz bei den Funktionen, und das auf Kosten der Genauigkeit.

19
Wboy

Eine heiße Kodierung mit pandas ist sehr einfach:

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

BEARBEITEN:

Ein anderer Weg zu one_hot mit dem LabelBinarizer von sklearn:

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)
16
Qy Zuo

Sie können die Funktion numpy.eye verwenden.

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 __== "__main__":
    main()

Ergebnis

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.]]
13
Dieter

Viel einfacher zu verwenden Pandas für die einfache One-Hot-Codierung. Wenn Sie nach mehr Optionen suchen, können Sie scikit-learn verwenden.

Für die grundlegende One-Hot-Codierung mit Pandas übergeben Sie einfach Ihren Datenrahmen an die get_dummies Funktion.

Wenn ich zum Beispiel einen Datenrahmen mit dem Namen imdb_movies habe:

enter image description here

... und ich möchte die Rated-Spalte einmal heiß codieren, ich mache einfach Folgendes:

pd.get_dummies(imdb_movies.Rated)

enter image description here

Dies gibt einen neuen Datenrahmen mit einer Spalte für jede " Stufe " der Bewertung zurück, zusammen mit einer 1 oder 0, die das Vorhandensein dieser Bewertung für angibt eine gegebene Beobachtung.

Normalerweise soll dies Teil des ursprünglichen Datenrahmens sein. In diesem Fall befestigen wir einfach unseren neuen Dummy-codierten Rahmen mit " Spaltenbindung am ursprünglichen Rahmen.

Wir können eine Spaltenbindung durchführen, indem wir die Pandas concat -Funktion verwenden:

rated_dummies = pd.get_dummies(imdb_movies.Rated)
pd.concat([imdb_movies, rated_dummies], axis=1)

enter image description here

Wir können jetzt die Analyse für unseren gesamten Datenrahmen ausführen.

EINFACHE NÜTZLICHKEITSFUNKTION

Ich würde empfehlen, sich eine Utility-Funktion zu erstellen, um dies schnell zu erledigen:

def encode_and_bind(original_dataframe, feature_to_encode):
    dummies = pd.get_dummies(original_dataframe[[feature_to_encode]])
    res = pd.concat([original_dataframe, dummies], axis=1)
    return(res)

Verwendung :

encode_and_bind(imdb_movies, 'Rated')

Ergebnis :

enter image description here

Wenn Sie gemäß @pmalbu-Kommentar möchten, dass die Funktion den ursprünglichen feature_to_encode entfernt, verwenden Sie diese Version:

def encode_and_bind(original_dataframe, feature_to_encode):
    dummies = pd.get_dummies(original_dataframe[[feature_to_encode]])
    res = pd.concat([original_dataframe, dummies], axis=1)
    res = res.drop([feature_to_encode], axis=1)
    return(res) 
13
Cybernetic

pandas as hat die eingebaute Funktion "get_dummies", um eine heiße Kodierung dieser bestimmten Spalte (n) zu erhalten.

einzeilencode für One-Hot-Codierung:

df=pd.concat([df,pd.get_dummies(df['column name'],prefix='column name')],axis=1).drop(['column name'],axis=1)
4
Arshdeep Singh

One-Hot-Codierung erfordert etwas mehr als das Konvertieren der Werte in Indikatorvariablen. In der Regel müssen Sie diese Kodierung bei ML-Prozessen mehrmals auf Validierungs- oder Testdatensätze anwenden und das von Ihnen erstellte Modell auf in Echtzeit beobachtete Daten anwenden. Sie sollten die Zuordnung (Transformation) speichern, die zum Erstellen des Modells verwendet wurde. Eine gute Lösung wäre die Verwendung von DictVectorizer oder LabelEncoder (gefolgt von get_dummies. Hier ist eine Funktion, die Sie verwenden können:

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)

Dies funktioniert auf einem pandas dataframe und für jede Spalte des Dataframes, den es erstellt, und gibt ein Mapping zurück. Sie würden es also folgendermaßen aufrufen:

train_data, le_dict = oneHotEncode2(train_data)

Bei den Testdaten erfolgt der Aufruf durch Übergeben des vom Training zurückgegebenen Wörterbuchs:

test_data, _ = oneHotEncode2(test_data, le_dict)

Eine äquivalente Methode ist die Verwendung von DictVectorizer. Ein verwandter Beitrag dazu ist auf meinem Blog. Ich erwähne es hier, da es einige Gründe für diesen Ansatz liefert, einfach get_dummies post (Disclosure: Dies ist mein eigener Blog) zu verwenden.

3
Tukeys

Hier ist eine Lösung mit DictVectorizer und der Methode 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
Josh Morel

Ich weiß, dass ich zu spät zu dieser Party komme, aber der einfachste Weg, einen Datenrahmen auf automatisierte Weise im laufenden Betrieb zu codieren, ist die Verwendung dieser Funktion:

def hot_encode(df):
    obj_df = df.select_dtypes(include=['object'])
    return pd.get_dummies(df, columns=obj_df.columns).values
2
Rambatino

Sie können die Daten ohne Codierung an den catboost-Klassifizierer übergeben. Catboost behandelt kategoriale Variablen selbst, indem es eine One-Hot- und eine Target-Expanding-Mean-Codierung durchführt.

2
Garima Jain

Lassen Sie mich, um andere Fragen zu beantworten, angeben, wie ich es mit einer Python 2.0-Funktion mit Numpy gemacht habe:

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

Die Zeile n_values = np.max(y_) + 1 könnte fest codiert sein, damit Sie die richtige Anzahl von Neuronen verwenden können, wenn Sie beispielsweise Minibatches verwenden.

Demoprojekt/Tutorial, in dem diese Funktion verwendet wurde: https://github.com/guillaume-chevalier/LSTM-Human-Activity-Recognition

0

Ich habe das in meinem Akustikmodell verwendet: wahrscheinlich hilft das in deinem Modell.

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
yunus

Das funktioniert bei mir:

pandas.factorize( ['B', 'C', 'D', 'B'] )[0]

Ausgabe:

[0, 1, 2, 0]
0
scottlittle

Sie können auch Folgendes tun. Beachten Sie, dass Sie für das Folgende nicht pd.concat Verwenden müssen.

import pandas as pd 
# intialise data of lists. 
data = {'Color':['Red', 'Yellow', 'Red', 'Yellow'], 'Length':[20.1, 21.1, 19.1, 18.1],
       'Group':[1,2,1,2]} 

# Create DataFrame 
df = pd.DataFrame(data) 

for _c in df.select_dtypes(include=['object']).columns:
    print(_c)
    df[_c]  = pd.Categorical(df[_c])
df_transformed = pd.get_dummies(df)
df_transformed

Sie können explizite Spalten auch in kategorial ändern. Zum Beispiel ändere ich hier die Color und Group

import pandas as pd 
# intialise data of lists. 
data = {'Color':['Red', 'Yellow', 'Red', 'Yellow'], 'Length':[20.1, 21.1, 19.1, 18.1],
       'Group':[1,2,1,2]} 

# Create DataFrame 
df = pd.DataFrame(data) 
columns_to_change = list(df.select_dtypes(include=['object']).columns)
columns_to_change.append('Group')
for _c in columns_to_change:
    print(_c)
    df[_c]  = pd.Categorical(df[_c])
df_transformed = pd.get_dummies(df)
df_transformed
0
sushmit

Es kann und sollte einfach sein als:

class OneHotEncoder:
    def __init__(self,optionKeys):
        length=len(optionKeys)
        self.__dict__={optionKeys[j]:[0 if i!=j else 1 for i in range(length)] for j in range(length)}

Verwendungszweck :

ohe=OneHotEncoder(["A","B","C","D"])
print(ohe.A)
print(ohe.D)
0
Ofek Ron