versiones guia español descargar actualizar python pandas machine-learning anaconda one-hot-encoding

python - guia - qgis manual



¿Cómo puedo una codificación en caliente en Python? (17)

Tengo un problema de clasificación de aprendizaje automático con 80% de variables categóricas. ¿Debo usar una codificación activa si quiero usar algún clasificador para la clasificación? ¿Puedo pasar los datos a un clasificador sin la codificación?

Estoy tratando de hacer lo siguiente para la selección de funciones:

  1. Leí el archivo del tren:

    num_rows_to_read = 10000 train_small = pd.read_csv("../../dataset/train.csv", nrows=num_rows_to_read)

  2. Cambio el tipo de características categóricas a ''categoría'':

    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. Yo uso una codificación en caliente:

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

El problema es que la tercera parte a menudo se atasca, aunque estoy usando una máquina fuerte.

Por lo tanto, sin la codificación activa no puedo hacer ninguna selección de funciones para determinar la importancia de las funciones.

¿Que recomiendas?


Aquí hay una solución usando DictVectorizer y el DataFrame.to_dict(''records'') 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.]])


Aquí probé con este enfoque:

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)


En primer lugar, la forma más fácil de una codificación activa: usar Sklearn.

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

En segundo lugar, no creo que usar pandas para una codificación en caliente sea tan simple (aunque sin confirmar)

Crear variables ficticias en pandas para python

Por último, ¿es necesario que realice una codificación activa? Una codificación activa aumenta exponencialmente el número de características, aumentando drásticamente el tiempo de ejecución de cualquier clasificador o cualquier otra cosa que vaya a ejecutar. Especialmente cuando cada característica categórica tiene muchos niveles. En cambio, puedes hacer una codificación ficticia.

El uso de la codificación ficticia generalmente funciona bien, por mucho menos tiempo de ejecución y complejidad. Un sabio profesor una vez me dijo: ''Menos es más''.

Aquí está el código para mi función de codificación personalizada si lo desea.

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

EDITAR: Comparación para ser más claro:

Codificación única: convierta n niveles en n-1 columnas.

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

Puede ver cómo esto explotará su memoria si tiene muchos tipos (o niveles) diferentes en su función categórica. Tenga en cuenta que esto es solo UNA columna.

Codificación ficticia:

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

Convierte a representaciones numéricas en su lugar. Ahorra mucho espacio de funciones, a costa de un poco de precisión.


Esto funciona para mi:

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

Salida:

[0, 1, 2, 0]


La codificación en caliente requiere un poco más que convertir los valores en variables indicadoras. Normalmente, el proceso de ML requiere que aplique esta codificación varias veces a los conjuntos de datos de validación o prueba y que aplique el modelo que construye a los datos observados en tiempo real. Debe almacenar la asignación (transformación) que se utilizó para construir el modelo. Una buena solución usaría DictVectorizer o LabelEncoder (seguido de get_dummies . Aquí hay una función que puede usar:

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)

Esto funciona en un marco de datos de pandas y para cada columna del marco de datos que crea y devuelve una asignación. Entonces lo llamarías así:

train_data, le_dict = oneHotEncode2(train_data)

Luego, en los datos de prueba, la llamada se realiza pasando el diccionario devuelto de la capacitación:

test_data, _ = oneHotEncode2(test_data, le_dict)

Un método equivalente es usar DictVectorizer . Una publicación relacionada sobre el mismo está en mi blog. Lo menciono aquí, ya que proporciona algún razonamiento detrás de este enfoque sobre el simple uso de la post get_dummies (divulgación: este es mi propio blog).


Mucho más fácil de usar Pandas para la codificación básica en caliente. Si está buscando más opciones, puede usar scikit-learn.

Para la codificación básica de un solo uso con Pandas , simplemente pase su marco de datos a la función get_dummies .

Por ejemplo, si tengo un marco de datos llamado imdb_movies :

... y quiero codificar en caliente la columna Calificado, simplemente hago esto:

pd.get_dummies(imdb_movies.Rated)

Esto devuelve un nuevo marco de datos con una columna para cada " nivel " de calificación que existe, junto con un 1 o 0 que especifica la presencia de esa calificación para una observación dada.

Por lo general, queremos que esto sea parte del marco de datos original. En este caso, simplemente adjuntamos nuestro nuevo marco codificado ficticio al marco original usando " enlace de columna ".

Podemos enlazar columnas usando la función concat de Pandas:

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

Ahora podemos ejecutar análisis en nuestro marco de datos completo.

FUNCIÓN DE UTILIDAD SIMPLE

Recomiendo que se haga una función de utilidad para hacer esto rápidamente:

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)

Uso :

encode_and_bind(imdb_movies, ''Rated'')

Resultado :

Además, según el comentario de @pmalbu, si desea que la función elimine el feature_to_encode original , use esta versión:

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)


Para agregar a otras preguntas, déjenme proporcionarles cómo lo hice con una función de Python 2.0 usando 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 línea n_values = np.max(y_) + 1 podría estar codificada para que use la buena cantidad de neuronas en caso de que use mini lotes por ejemplo.

Proyecto de demostración / tutorial donde se ha utilizado esta función: https://github.com/guillaume-chevalier/LSTM-Human-Activity-Recognition


Puede hacerlo con numpy.eye y utilizando el mecanismo de selección de elementos de matriz:

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]

El valor de retorno de indices_to_one_hot(nb_classes, data) ahora es

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

El .reshape(-1) está ahí para asegurarse de que tiene el formato de etiquetas correcto (también puede tener [[2], [3], [4], [0]] ).


Puede pasar los datos al clasificador catboost sin codificación. Catboost maneja las variables categóricas por sí mismo al realizar una codificación media expansiva de destino y objetivo.


Puede usar la función 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()

Resultado

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


Puede y debe ser fácil como:

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

Uso:

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


Puedes hacer lo siguiente también. Tenga en cuenta que a continuación no tiene que usar 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

También puede cambiar las columnas explícitas a categóricas. Por ejemplo, aquí estoy cambiando el Color y el 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


Sé que llego tarde a esta fiesta, pero la forma más sencilla de codificar en caliente un marco de datos de forma automática es usar esta función:

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


Una codificación activa con pandas es muy fácil:

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

EDITAR:

Otra forma de one_hot usando LabelBinarizer de 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)


Usé esto en mi modelo acústico: probablemente esto ayude en su modelo.

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


pandas como tiene la función incorporada "get_dummies" para obtener una codificación activa de esa columna / s en particular.

un código de línea para una codificación en caliente:

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


Enfoque 1: puede usar get_dummies en el marco de datos de pandas.

Ejemplo 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

Ejemplo 2

Lo siguiente transformará una columna dada en una caliente. Usa el prefijo para tener varios dummies.

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

Enfoque 2: use Scikit-learn

Dado un conjunto de datos con tres características y cuatro muestras, dejamos que el codificador encuentre el valor máximo por característica y transforme los datos en una codificación binaria de un solo 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.]])

Aquí está el enlace para este ejemplo: http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html