Jak mogę jeden kod na gorąco w Pythonie?

132

Mam problem z klasyfikacją systemów uczących się z 80% zmiennych kategorialnych. Czy muszę używać jednego kodowania na gorąco, jeśli chcę użyć jakiegoś klasyfikatora do klasyfikacji? Czy mogę przekazać dane do klasyfikatora bez kodowania?

Próbuję wykonać następujące czynności w celu wyboru funkcji:

  1. Przeczytałem plik pociągu:

    num_rows_to_read = 10000
    train_small = pd.read_csv("../../dataset/train.csv",   nrows=num_rows_to_read)
    
  2. Zmieniam typ cech kategorialnych na „kategorię”:

    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. Używam jednego kodowania na gorąco:

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

Problem w tym, że trzecia część często się zacina, chociaż używam mocnej maszyny.

Tak więc bez jednego kodowania na gorąco nie mogę dokonać żadnego wyboru funkcji, aby określić znaczenie funkcji.

Co polecasz?

avicohen
źródło

Odpowiedzi:

159

Podejście 1: Możesz użyć get_dummies na pandach dataframe.

Przykład 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

Przykład 2:

Poniższy tekst przekształci daną kolumnę w jedną gorącą. Użyj przedrostka, aby mieć wiele manekinów.

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

Podejście 2: Użyj Scikit-learn

Biorąc pod uwagę zbiór danych z trzema funkcjami i czterema próbkami, pozwalamy koderowi znaleźć maksymalną wartość na cechę i przekształcić dane w binarne kodowanie typu one-hot.

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

Oto link do tego przykładu: http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html

Sayali Sonawane
źródło
20
ustawienie drop_first=Truez get_dummieseliminuje potrzebę oddzielnego upuszczania oryginalnej kolumny
OverflowingTheGlass
1
W przykładzie 2, czy istnieje sposób na dołączenie nowych kolumn do ramki danych bez użycia złączenia? Mam do czynienia z naprawdę dużym zestawem danych i dostaję MemoryError, gdy próbuję to zrobić.
J.Dahlgren
Możesz dodać nową kolumnę do dataframe bez użycia złączenia, jeśli masz df2 z taką samą liczbą wierszy. możesz skopiować, używając: df [„newColname”] = df2 [„col”]
Sayali Sonawane
1
Używanie obrazu na przykład 2 było złe
villasv
9
@ OverflowingTheGlass- drop-first = True nie usuwa oryginalnej kolumny. Opuszcza pierwszy poziom cechy jakościowej, tak że otrzymujesz k-1 kolumn zamiast k kolumn, gdzie k jest mocą jakościową.
Garima Jain
42

Znacznie łatwiejsze w użyciu Pandy do podstawowego kodowania na gorąco. Jeśli szukasz więcej opcji, możesz użyć scikit-learn.

Aby uzyskać podstawowe kodowanie na gorąco za pomocą Pandas , po prostu przekazujesz ramkę danych do funkcji get_dummies .

Na przykład, jeśli mam ramkę danych o nazwie imdb_movies :

wprowadź opis obrazu tutaj

... i chcę zakodować na gorąco kolumnę Rated, po prostu robię to:

pd.get_dummies(imdb_movies.Rated)

wprowadź opis obrazu tutaj

Zwraca to nową dataframez kolumną dla każdego istniejącego „ poziomu ” oceny, wraz z 1 lub 0 określającymi obecność tej oceny dla danej obserwacji.

Zwykle chcemy, aby było to częścią oryginału dataframe. W tym przypadku, po prostu dołączamy naszą nową fałszywą zakodowaną ramkę do oryginalnej ramki za pomocą „ wiązania kolumn ” .

Możemy wiązać kolumny za pomocą funkcji konkatacji Pandas :

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

wprowadź opis obrazu tutaj

Możemy teraz przeprowadzić analizę w pełni dataframe.

PROSTA FUNKCJA NARZĘDZIA

Poleciłbym zrobić sobie funkcję narzędziową, aby zrobić to szybko:

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)

Użycie :

encode_and_bind(imdb_movies, 'Rated')

Wynik :

wprowadź opis obrazu tutaj

Ponadto, zgodnie z komentarzem @pmalbu, jeśli chcesz, aby funkcja usuwała oryginalny kod feature_to_encode, użyj tej wersji:

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) 

Możesz kodować wiele funkcji jednocześnie w następujący sposób:

features_to_encode = ['feature_1', 'feature_2', 'feature_3',
                      'feature_4']
for feature in features_to_encode:
    res = encode_and_bind(train_set, feature)
Cybernetyczny
źródło
1
Sugerowałbym porzucenie oryginalnego feature_to_encode po połączeniu jednej gorącej kolumny z oryginalną ramką danych.
pmalbu
Dodano tę opcję odpowiedzi. Dzięki.
Cybernetic
28

Możesz to zrobić za pomocą numpy.eyei używając mechanizmu wyboru elementów tablicy:

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]

Zwracana wartość indices_to_one_hot(nb_classes, data)to teraz

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

Jest po .reshape(-1)to, aby upewnić się, że masz odpowiedni format etykiet (możesz również mieć [[2], [3], [4], [0]]).

Martin Thoma
źródło
1
To nie zadziała dla OHE kolumn z wartością ciągu.
Abhilash Awasthi
2
@AbhilashAwasthi Jasne ... ale dlaczego miałbyś oczekiwać, że to zadziała?
Martin Thoma
22

Po pierwsze, najłatwiejszy sposób na jedno gorące kodowanie: użyj Sklearn.

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

Po drugie, nie sądzę, aby używanie pand do jednego gorącego kodowania było takie proste (choć niepotwierdzone)

Tworzenie fikcyjnych zmiennych w pandach dla Pythona

Wreszcie, czy konieczne jest jedno gorące kodowanie? Jedno kodowanie na gorąco wykładniczo zwiększa liczbę funkcji, drastycznie zwiększając czas działania dowolnego klasyfikatora lub czegokolwiek innego, co zamierzasz uruchomić. Zwłaszcza, gdy każda cecha kategoryczna ma wiele poziomów. Zamiast tego możesz wykonać fałszywe kodowanie.

Używanie kodowania fikcyjnego zwykle działa dobrze, przy znacznie krótszym czasie wykonywania i złożoności. Mądry profesor powiedział mi kiedyś: „Mniej znaczy więcej”.

Oto kod mojej niestandardowej funkcji kodowania, jeśli chcesz.

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

EDYCJA: Porównanie, aby było jaśniejsze:

Kodowanie na gorąco: przekonwertuj n poziomów na n-1 kolumn.

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

Możesz zobaczyć, jak eksploduje to twoją pamięć, jeśli masz wiele różnych typów (lub poziomów) w swojej funkcji kategorialnej. Pamiętaj, że to tylko JEDNA kolumna.

Kodowanie manekina:

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

Zamiast tego przekonwertuj na reprezentacje liczbowe. Znacznie oszczędza miejsce na funkcje, kosztem odrobiny dokładności.

Wboy
źródło
1
1. Mam zbiór danych zawierający 80% zmiennych kategorialnych. Zgodnie z moim zrozumieniem, jeśli chcę użyć klasyfikatora dla tych danych, muszę użyć jednego kodowania na gorąco, w przeciwnym razie w przypadku niewykonania jednego kodowania na gorąco klasyfikator nie będzie traktował zmiennych kategorialnych we właściwy sposób? Czy jest opcja, aby nie kodować? 2. Jeśli używam pd.get_dummies (train_small, sparse = True) z saprse = True - czy to nie rozwiązuje problemu z pamięcią? 3. Jak mam podejść do takiego problemu?
avicohen
Jak powiedziałem, są dwie opcje. 1) Jedno kodowanie na gorąco -> przekonwertuj każdy poziom cech kategorialnych na nową kolumnę. 2) Kodowanie fałszywe -> przekonwertuj każdą kolumnę na reprezentacje liczbowe. Zmienię powyższą odpowiedź, aby była jaśniejsza. Ale możesz po prostu uruchomić funkcję, którą dostarczyłem i powinna działać
Wboy
17
„kosztem odrobiny dokładności”. Jak możesz powiedzieć „trochę”? Może w niektórych przypadkach, ale w innych dokładność może bardzo ucierpieć. To rozwiązanie powoduje traktowanie cech jakościowych jako ciągłych, co oznacza, że ​​model nie będzie prawidłowo uczył się na podstawie danych.
Josh Morel,
2
Jak powiedział Josh powyżej, w swoim drugim przykładzie w końcu mówisz modelowi, że mouse > cat > dogtak nie jest. get_dummiesjest najprostszym sposobem przeniesienia zmiennych kategorialnych do danych przyjaznych modelowi z mojego doświadczenia (aczkolwiek bardzo ograniczonego)
Martin O Leary
5
To rozwiązanie jest bardzo niebezpieczne, na co wskazują inne komentarze. Dowolnie przypisuje rzędy i odległości do zmiennych kategorialnych. Takie postępowanie zmniejsza elastyczność modelu w losowy sposób. W przypadku modeli opartych na drzewie takie kodowanie ogranicza możliwe możliwości podzestawiania. Na przykład, możesz teraz uzyskać tylko dwa możliwe rozdzielenia [(0), (1,2)] i [(0,1), (2)], a podział [(0,2), (1)] to niemożliwy. Strata jest znacznie bardziej znacząca, gdy liczba kategorii jest duża.
Random Pewność
19

Jedno gorące kodowanie z pandami jest bardzo łatwe:

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

EDYTOWAĆ:

Inny sposób na one_hot przy użyciu 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)
Qy Zuo
źródło
14

Możesz użyć funkcji numpy.eye.

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

Wynik

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
źródło
2
Czy właśnie skopiowałeś moją odpowiedź?
Martin Thoma
@Martin Thoma - myślę, że nie
Dieter
5

pandas as ma wbudowaną funkcję „get_dummies”, aby uzyskać jedno gorące kodowanie tej konkretnej kolumny / kolumn.

jednowierszowy kod dla jednego gorącego kodowania:

df=pd.concat([df,pd.get_dummies(df['column name'],prefix='column name')],axis=1).drop(['column name'],axis=1)
Arshdeep Singh
źródło
4

Oto rozwiązanie wykorzystujące DictVectorizeri DataFrame.to_dict('records')metodę Pandy .

>>> 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
źródło
3

Kodowanie typu one-hot wymaga nieco więcej niż konwersja wartości na zmienne wskaźnikowe. Zazwyczaj proces ML wymaga kilkukrotnego zastosowania tego kodowania do walidacji lub testowania zestawów danych i zastosowania zbudowanego modelu do danych obserwowanych w czasie rzeczywistym. Należy zachować odwzorowanie (transformację), które zostało użyte do skonstruowania modelu. Dobrym rozwiązaniem byłoby użycie DictVectorizerlub LabelEncoder(po którym następuje get_dummies. Oto funkcja, której możesz użyć:

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)

Działa to na pandas dataframe i dla każdej kolumny tworzonej ramki danych i zwraca odwzorowanie. Więc nazwałbyś to tak:

train_data, le_dict = oneHotEncode2(train_data)

Następnie na danych testowych wywołanie jest realizowane przez przekazanie słownika zwróconego z treningu:

test_data, _ = oneHotEncode2(test_data, le_dict)

Równoważną metodą jest użycie DictVectorizer. Powiązany post na ten sam temat znajduje się na moim blogu. Wspominam o tym tutaj, ponieważ zapewnia to pewne uzasadnienie tego podejścia w stosunku do zwykłego używania postu get_dummies (ujawnienie: to jest mój własny blog).

Tukeys
źródło
3

Możesz przekazać dane do klasyfikatora catboost bez kodowania. Catboost sam obsługuje zmienne kategorialne, wykonując jedno-gorące i docelowe rozszerzające się kodowanie średniej.

Garima Jain
źródło
3

Możesz również wykonać następujące czynności. Uwaga dla poniższych, których nie musisz używać 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

Możesz również zmienić jawne kolumny na kategoryczne. Na przykład tutaj zmieniam ColoriGroup

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
źródło
2

Wiem, że spóźniłem się na tę imprezę, ale najprostszym sposobem na zakodowanie na gorąco ramki danych w sposób zautomatyzowany jest użycie tej funkcji:

def hot_encode(df):
    obj_df = df.select_dtypes(include=['object'])
    return pd.get_dummies(df, columns=obj_df.columns).values
Rambatino
źródło
1

Użyłem tego w moim modelu akustycznym: prawdopodobnie to pomaga w twoim modelu.

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
źródło
0

Aby dodać do innych pytań, pozwól mi podać, jak to zrobiłem z funkcją Python 2.0 przy użyciu 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

Linia n_values = np.max(y_) + 1może być zakodowana na stałe, abyś używał odpowiedniej liczby neuronów na przykład w przypadku użycia mini-partii.

Projekt demonstracyjny / samouczek, w którym wykorzystano tę funkcję: https://github.com/guillaume-chevalier/LSTM-Human-Activity-Recognition

Guillaume Chevalier
źródło
0

To działa dla mnie:

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

Wynik:

[0, 1, 2, 0]
scottlittle
źródło
0

Może i powinno być takie proste, jak:

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

Stosowanie :

ohe=OneHotEncoder(["A","B","C","D"])
print(ohe.A)
print(ohe.D)
Ofek Ron
źródło
0

Rozszerzanie odpowiedzi @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
źródło
0

Krótka odpowiedź

Oto funkcja do kodowania na gorąco bez używania numpy, pandy lub innych pakietów. Pobiera listę liczb całkowitych, wartości logicznych lub łańcuchów (i być może także innych typów).

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

Przykład:

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

Długa (e) odpowiedź

Wiem, że jest już wiele odpowiedzi na to pytanie, ale zauważyłem dwie rzeczy. Po pierwsze, większość odpowiedzi używa pakietów takich jak numpy i / lub pandy. I to jest dobra rzecz. Jeśli piszesz kod produkcyjny, prawdopodobnie powinieneś używać solidnych, szybkich algorytmów, takich jak te zawarte w pakietach numpy / pandas. Ale ze względu na edukację myślę, że ktoś powinien udzielić odpowiedzi, która ma przejrzysty algorytm, a nie tylko implementację cudzego algorytmu. Po drugie, zauważyłem, że wiele odpowiedzi nie zapewnia solidnej implementacji kodowania typu one-hot, ponieważ nie spełniają one jednego z poniższych wymagań. Poniżej znajdują się niektóre wymagania (tak jak je widzę) dotyczące użytecznej, dokładnej i niezawodnej funkcji kodowania na gorąco:

Funkcja kodowania typu one-hot musi:

  • obsługuje listę różnych typów (np. liczby całkowite, ciągi znaków, zmiennoprzecinkowe itp.) jako dane wejściowe
  • obsłużyć listę wejściową z duplikatami
  • zwraca listę list odpowiadających (w tej samej kolejności co) wejściom
  • zwraca listę list, z których każda jest możliwie najkrótsza

Przetestowałem wiele odpowiedzi na to pytanie i większość z nich nie spełnia jednego z powyższych wymagań.

Floyd
źródło
0

Spróbuj tego:

!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 ()

Wynikowa ramka danych df_train_encodedjest taka sama jak oryginał, ale funkcje kategorialne są teraz zastępowane ich wersjami zakodowanymi na gorąco.

Więcej informacji category_encoders tutaj .

Andrea Araldo
źródło
-1

Tutaj próbowałem z tym podejściem:

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
źródło