Wie kann ich eine Hotcodierung in Python durchführen?

132

Ich habe ein Klassifizierungsproblem beim maschinellen Lernen mit 80% kategorialen Variablen. Muss ich eine Hot-Codierung verwenden, wenn ich einen Klassifizierer für die Klassifizierung verwenden möchte? Kann ich die Daten ohne Codierung an einen Klassifizierer ü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 Hot-Codierung:

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

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

Daher kann ich ohne die einzige Hot-Codierung keine Feature-Auswahl treffen, um die Wichtigkeit der Features zu bestimmen.

Was empfehlen Sie?

avicohen
quelle

Antworten:

159

Ansatz 1: Sie können get_dummies für Pandas-Datenrahmen 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:

Im Folgenden wird eine bestimmte Spalte in eine heiße Spalte umgewandelt. 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 Samples lassen wir den 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

Sayali Sonawane
quelle
20
Einstellung drop_first=Truemit get_dummiesbeseitigt die Notwendigkeit, die ursprüngliche Spalte separat zu
löschen
1
Gibt es in Beispiel 2 eine Möglichkeit, die neuen Spalten mit dem Datenrahmen zu verbinden, ohne Join zu verwenden? Ich habe es mit einem wirklich großen Datensatz zu tun und bekomme MemoryError, wenn ich das versuche.
J. Dahlgren
Sie können dem Datenrahmen eine neue Spalte hinzufügen, ohne Join zu verwenden, wenn Sie df2 mit derselben Anzahl von Zeilen haben. Sie können kopieren mit: df ["newColname"] = df2 ["col"]
Sayali Sonawane
1
Die Verwendung eines Bildes zum Beispiel 2 war böse
villasv
9
@ OverflowingTheGlass- drop-first = True entfernt die ursprüngliche Spalte nicht. Die erste Ebene des kategorialen Features wird gelöscht, sodass Sie k-1-Spalten anstelle von k Spalten erhalten, wobei k die Kardinalität des kategorialen Features ist.
Garima Jain
41

Es ist viel einfacher, Pandas für die einfache One-Hot-Codierung zu verwenden. Wenn Sie nach mehr Optionen suchen, können Sie diese verwendenscikit-learn .

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

Wenn ich zum Beispiel einen Datenrahmen namens imdb_movies habe :

Geben Sie hier die Bildbeschreibung ein

... und ich möchte die Spalte "Rated" mit einem Hot-Coding codieren. Ich mache einfach Folgendes:

pd.get_dummies(imdb_movies.Rated)

Geben Sie hier die Bildbeschreibung ein

Dies gibt eine neue dataframemit einer Spalte für jede „ Ebene “ der Bewertung , die, zusammen mit entweder 1 oder 0 Angabe der Anwesenheit dieser Bewertung für eine gegebene Beobachtung existiert.

Normalerweise möchten wir, dass dies Teil des Originals ist dataframe. In diesem Fall befestigen wir einfach unseren neuen Dummy-codierten Rahmen mit " Spaltenbindung " am Originalrahmen .

Wir können mithilfe von Pandas Spalten binden Concat- Funktion :

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

Geben Sie hier die Bildbeschreibung ein

Wir können jetzt eine vollständige Analyse durchführen dataframe.

EINFACHE NUTZFUNKTION

Ich würde empfehlen, sich eine zu machen Utility-Funktion zu machen, 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 :

Geben Sie hier die Bildbeschreibung ein

Auch gemäß @ pmalbu Kommentar, wenn Sie die Funktion möchten 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) 

Sie können mehrere Funktionen gleichzeitig wie folgt codieren:

features_to_encode = ['feature_1', 'feature_2', 'feature_3',
                      'feature_4']
for feature in features_to_encode:
    res = encode_and_bind(train_set, feature)
Kybernetisch
quelle
1
Ich würde vorschlagen, den ursprünglichen feature_to_encode zu löschen, nachdem Sie die Hot-Ended-Spalten mit dem ursprünglichen Datenrahmen verkettet haben.
Pmalbu
Diese Option wurde hinzugefügt, um zu antworten. Vielen Dank.
Kybernetisch
28

Sie können dies mit numpy.eyeund unter Verwendung 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.]]])

Das .reshape(-1)ist da, um sicherzustellen, dass Sie das richtige Etikettenformat haben (möglicherweise auch [[2], [3], [4], [0]]).

Martin Thoma
quelle
1
Dies funktioniert nicht für OHE der Spalten mit Zeichenfolgenwert.
Abhilash Awasthi
2
@AbhilashAwasthi Sicher ... aber warum sollten Sie dann erwarten, dass es funktioniert?
Martin Thoma
22

Erstens, der einfachste Weg zu einer Hot-Codierung: Verwenden Sie Sklearn.

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

Zweitens denke ich nicht, dass die Verwendung von Pandas für eine Hot-Codierung so einfach ist (allerdings nicht bestätigt).

Erstellen von Dummy-Variablen in Pandas für Python

Ist es für Sie schließlich notwendig, eine Hot-Codierung durchzuführen? Eine Hot-Codierung erhöht die Anzahl der Features exponentiell und erhöht die Laufzeit eines Klassifikators oder anderer Elemente, die Sie ausführen möchten, drastisch. Besonders wenn jedes kategoriale Merkmal viele Ebenen hat. Stattdessen können Sie Dummy-Codierung durchführen.

Die Verwendung der Dummy-Codierung funktioniert normalerweise gut, bei viel weniger Laufzeit und Komplexität. Ein weiser Professor 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 explodieren lässt, wenn Ihre kategoriale Funktion viele verschiedene Typen (oder Ebenen) enthält. 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 viel Platz für Funktionen, was ein wenig Genauigkeit kostet.

Wboy
quelle
1
1. Ich habe einen Datensatz mit 80% kategorialen Variablen. Nach meinem Verständnis muss ich eine Hot-Codierung verwenden, wenn ich einen Klassifizierer für diese Daten verwenden möchte. Andernfalls behandelt der Klassifizierer die kategorialen Variablen nicht richtig, wenn er nicht die eine Hot-Codierung durchführt. Gibt es eine Option, nicht zu codieren? 2. Wenn ich pd.get_dummies (train_small, sparse = True) mit saprse = True verwende - löst das nicht das Speicherproblem? 3. Wie soll ich mich einem solchen Problem nähern?
Avicohen
Wie gesagt, es gibt zwei Möglichkeiten. 1) Eine Hot-Codierung -> Konvertieren Sie jede Ebene in kategorialen Features in eine neue Spalte. 2) Dummy-Codierung -> Konvertieren Sie jede Spalte in numerische Darstellungen. Ich werde meine Antwort oben bearbeiten, um klarer zu sein. Aber Sie können einfach die von mir bereitgestellte Funktion ausführen und es sollte funktionieren
Wboy
17
"auf Kosten ein bisschen Genauigkeit." Wie kannst du "ein bisschen" sagen? Vielleicht in einigen Fällen, aber in anderen kann die Genauigkeit stark beeinträchtigt werden. Diese Lösung führt dazu, dass qualitative Merkmale als kontinuierlich behandelt werden, was bedeutet, dass Ihr Modell nicht richtig aus den Daten lernt.
Josh Morel
2
Wie Josh oben sagte, sagen Sie dem Modell in Ihrem zweiten Beispiel am Ende, dass mouse > cat > dogdies nicht der Fall ist. get_dummiesist der einfachste Weg, kategoriale Variablen aus meiner Erfahrung in modellfreundliche Daten zu übertragen (wenn auch sehr begrenzt)
Martin O Leary
5
Diese Lösung ist sehr gefährlich, wie einige andere Kommentare hervorheben. Es ordnet kategorialen Variablen willkürlich Ordnungen und Entfernungen zu. Dadurch wird die Modellflexibilität auf zufällige Weise verringert. Bei baumbasierten Modellen reduziert eine solche Codierung mögliche Teilmengenmöglichkeiten. Zum Beispiel können Sie jetzt nur zwei mögliche Aufteilungen erhalten [(0), (1,2)] und [(0,1), (2)], und die Aufteilung [(0,2), (1)] ist unmöglich. Der Verlust ist viel bedeutender, wenn die Anzahl der Kategorien hoch ist.
Zufällige Gewissheit
19

Eine Hot-Codierung 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 sklearn's 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)
Qy Zuo
quelle
14

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 __name__ == "__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.]]
Dieter
quelle
2
Hast du gerade meine Antwort kopiert?
Martin Thoma
@ Martin Thoma - Ich glaube, ich habe nicht
Dieter
5

pandas as hat die eingebaute Funktion "get_dummies", um eine Hot-Codierung 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)
Arshdeep Singh
quelle
4

Hier ist eine Lösung mit DictVectorizerund der Pandas- DataFrame.to_dict('records')Methode.

>>> 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.]])
Josh Morel
quelle
3

One-Hot-Codierung erfordert etwas mehr als die Konvertierung der Werte in Indikatorvariablen. In der Regel müssen Sie beim ML-Prozess diese Codierung mehrmals auf Validierungs- oder Testdatensätze anwenden und das von Ihnen erstellte Modell auf beobachtete Echtzeitdaten anwenden. Sie sollten die Zuordnung (Transformation) speichern, die zum Erstellen des Modells verwendet wurde. Eine gute Lösung wäre das DictVectorizeroder 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 bei einem Pandas-Datenrahmen und für jede Spalte des Datenrahmens wird eine Zuordnung erstellt und zurückgegeben. Sie würden es also so nennen:

train_data, le_dict = oneHotEncode2(train_data)

Bei den Testdaten erfolgt der Anruf dann, indem das vom Training zurückgegebene Wörterbuch zurückgegeben wird:

test_data, _ = oneHotEncode2(test_data, le_dict)

Eine äquivalente Methode ist zu verwenden DictVectorizer. Ein verwandter Beitrag dazu befindet sich in meinem Blog. Ich erwähne es hier, da es einige Gründe für diesen Ansatz liefert, einfach den Beitrag get_dummies zu verwenden (Offenlegung: Dies ist mein eigener Blog).

Tukeys
quelle
3

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

Garima Jain
quelle
3

Sie können auch Folgendes tun. Hinweis für das Folgende müssen Sie nicht verwenden pd.concat.

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 das ColorundGroup

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
Sushmit
quelle
2

Ich weiß, dass ich zu spät zu dieser Party komme, aber der einfachste Weg, einen Datenrahmen automatisch heiß 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
Rambatino
quelle
1

Ich habe dies in meinem akustischen Modell verwendet: wahrscheinlich hilft dies in Ihrem 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,))
Yunus
quelle
0

Um weitere Fragen zu ergänzen, möchte ich erläutern, wie ich es mit einer Python 2.0-Funktion unter Verwendung von 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 Linie n_values = np.max(y_) + 1könnte für Sie fest codiert sein, um die gute Anzahl von Neuronen zu verwenden, falls Sie beispielsweise Mini-Batches verwenden.

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

Guillaume Chevalier
quelle
0

Das funktioniert bei mir:

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

Ausgabe:

[0, 1, 2, 0]
scottlittle
quelle
0

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

Verwendung :

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

Erweitern der Antwort von @Martin Thoma

def one_hot_encode(y):
    """Convert an iterable of indices to one-hot encoded labels."""
    y = y.flatten() # Sometimes not flattened vector is passed e.g (118,1) in these cases
    # the function ends up creating a tensor e.g. (118, 2, 1). flatten removes this issue
    nb_classes = len(np.unique(y)) # get the number of unique classes
    standardised_labels = dict(zip(np.unique(y), np.arange(nb_classes))) # get the class labels as a dictionary
    # which then is standardised. E.g imagine class labels are (4,7,9) if a vector of y containing 4,7 and 9 is
    # directly passed then np.eye(nb_classes)[4] or 7,9 throws an out of index error.
    # standardised labels fixes this issue by returning a dictionary;
    # standardised_labels = {4:0, 7:1, 9:2}. The values of the dictionary are mapped to keys in y array.
    # standardised_labels also removes the error that is raised if the labels are floats. E.g. 1.0; element
    # cannot be called by an integer index e.g y[1.0] - throws an index error.
    targets = np.vectorize(standardised_labels.get)(y) # map the dictionary values to array.
    return np.eye(nb_classes)[targets]
mcagriardic
quelle
0

Kurze Antwort

Hier ist eine Funktion zum Ausführen einer One-Hot-Codierung ohne Verwendung von Numpy, Pandas oder anderen Paketen. Es wird eine Liste von Ganzzahlen, Booleschen Werten oder Zeichenfolgen (und möglicherweise auch anderen Typen) benötigt.

import typing


def one_hot_encode(items: list) -> typing.List[list]:
    results = []
    # find the unique items (we want to unique items b/c duplicate items will have the same encoding)
    unique_items = list(set(items))
    # sort the unique items
    sorted_items = sorted(unique_items)
    # find how long the list of each item should be
    max_index = len(unique_items)

    for item in items:
        # create a list of zeros the appropriate length
        one_hot_encoded_result = [0 for i in range(0, max_index)]
        # find the index of the item
        one_hot_index = sorted_items.index(item)
        # change the zero at the index from the previous line to a one
        one_hot_encoded_result[one_hot_index] = 1
        # add the result
        results.append(one_hot_encoded_result)

    return results

Beispiel:

one_hot_encode([2, 1, 1, 2, 5, 3])

# [[0, 1, 0, 0],
#  [1, 0, 0, 0],
#  [1, 0, 0, 0],
#  [0, 1, 0, 0],
#  [0, 0, 0, 1],
#  [0, 0, 1, 0]]
one_hot_encode([True, False, True])

# [[0, 1], [1, 0], [0, 1]]
one_hot_encode(['a', 'b', 'c', 'a', 'e'])

# [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [1, 0, 0, 0], [0, 0, 0, 1]]

Lange Antwort

Ich weiß, dass es bereits viele Antworten auf diese Frage gibt, aber ich habe zwei Dinge bemerkt. Erstens verwenden die meisten Antworten Pakete wie Numpy und / oder Pandas. Und das ist gut so. Wenn Sie Produktionscode schreiben, sollten Sie wahrscheinlich robuste, schnelle Algorithmen verwenden, wie sie in den numpy / pandas-Paketen enthalten sind. Aus Gründen der Bildung denke ich jedoch, dass jemand eine Antwort geben sollte, die einen transparenten Algorithmus und nicht nur eine Implementierung des Algorithmus eines anderen hat. Zweitens habe ich festgestellt, dass viele der Antworten keine robuste Implementierung der One-Hot-Codierung bieten, da sie eine der folgenden Anforderungen nicht erfüllen. Im Folgenden sind einige der Anforderungen (wie ich sie sehe) für eine nützliche, genaue und robuste One-Hot-Codierungsfunktion aufgeführt:

Eine One-Hot-Codierungsfunktion muss:

  • Behandeln Sie eine Liste verschiedener Typen (z. B. Ganzzahlen, Zeichenfolgen, Gleitkommazahlen usw.) als Eingabe
  • Behandeln Sie eine Eingabeliste mit Duplikaten
  • Geben Sie eine Liste von Listen zurück, die den Eingaben entsprechen (in derselben Reihenfolge wie)
  • Geben Sie eine Liste mit Listen zurück, bei denen jede Liste so kurz wie möglich ist

Ich habe viele der Antworten auf diese Frage getestet und die meisten scheitern an einer der oben genannten Anforderungen.

Floyd
quelle
0

Versuche dies:

!pip install category_encoders
import category_encoders as ce

categorical_columns = [...the list of names of the columns you want to one-hot-encode ...]
encoder = ce.OneHotEncoder(cols=categorical_columns, use_cat_names=True)
df_train_encoded = encoder.fit_transform(df_train_small)

df_encoded.head ()

Der resultierende Datenrahmen df_train_encoded ist derselbe wie das Original, aber die kategorialen Funktionen werden jetzt durch ihre One-Hot-codierten Versionen ersetzt.

Weitere Informationen category_encoders hier .

Andrea Araldo
quelle
-1

Hier habe ich mit diesem Ansatz versucht:

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)
Aaditya Ura
quelle