Datos categóricos en aprendizaje profundo: tres formas de codificarlas

0
How to Encode Categorical Data for Deep Learning in Keras

Los modelos de machine learning y deep learning (aprendizaje profundo), como los de Keras, requieren que todas las variables de entrada y salida sean numéricas.

Esto significa que si sus datos contienen datos categóricos, debes codificarlo a números antes de que puedas ajustar y evaluar un modelo.

Las dos técnicas más populares son una codificación de enteros y una una codificación en caliente, aunque una técnica más nueva llamada inclusión aprendida puede proporcionar un punto medio útil entre estos dos métodos.

En este tutorial, descubrirá cómo codificar datos categóricos en aprendizaje profundo al desarrollar modelos de redes neuronales en Keras.

Después de completar este tutorial usted sabrá:

  • El desafío de trabajar con datos categóricos cuando se utilizan modelos de machine learning y deep learning.
  • Cómo codificar enteros y una codificación en caliente de variables categóricas para modelar.
  • Cómo aprender una representacíon distribuida incrustada como parte de una red neuronal para variables categóricas en aprendizaje profundo.

Descripción general del tutorial

Este tutorial se divide en cinco partes:

  1. El desafío con datos categóricos.
  2. Conjunto de datos categóricos de cáncer de mama.
  3. Cómo codificar datos categóricos ordinarios.
  4. Cómo codificar datos categóricos en caliente.
  5. Cómo utilizar una incrustación aprendida para datos categóricos en aprendizaje profundo.

El desafío con los datos categóricos en aprendizaje profundo

Una variable categórica es una variable cuyos valores toman el valor de las etiquetas.

Por ejemplo, la variable puede ser “ color ” y puede tomar los valores “ rojo “, “ verde ” y “ azul “.

A veces, los datos categóricos pueden tener una relación ordenada entre las categorías, como “ primero “, “ segundo ” y “ tercero “. Este tipo de datos categóricos se conoce como ordinal y la información de pedido adicional puede ser útil.

Los algoritmos de machine learning y las redes neuronales de deep learning requieren esa entrada y las variables de salida son números.Esto significa que los datos categóricos en aprendizaje profundo deben codificarse en números antes de que podamos usarlos para ajustar y evaluar un modelo.

Hay muchas formas de codificar variables categóricas en aprendizaje profundo para el modelado, aunque las tres más comunes son los siguientes:

  1. Codificación entera: donde cada etiqueta única se asigna a un entero.
  2. Una codificación activa: donde cada etiqueta se asigna a un vector binario.
  3. Incrustación aprendida : donde se aprende una representación distribuida de las categorías.

Veremos más de cerca cómo codificar datos categóricos para entrenar una red neuronal de deep learning en Keras usando cada uno de estos métodos.

Conjunto de datos categóricos de cáncer de mama

Como base de este tutorial, utilizaremos el llamado conjunto de datos “ Cáncer de mama ” que ha sido ampliamente estudiado en machine learning desde la década de 1980.

El conjunto de datos clasifica el cáncer de mama er datos del paciente como recurrencia o no recurrencia de cáncer. Hay 286 ejemplos y nueve variables de entrada. Es un problema de clasificación binaria.

Una puntuación de precisión de clasificación razonable en este conjunto de datos es entre 68% y 73%. Apuntaremos a esta región, pero tenga en cuenta que los modelos en este tutorial no están optimizados: están diseñados para demostrar esquemas de codificación .

Puede descargar el conjunto de datos y guardar el archivo como “ breast-cancer.csv “en su directorio de trabajo actual.

Mirando los datos, podemos ver que las nueves variables de entrada son categóricos.

Específicamente, todas las variables son cadenas citadas; algunos son ordinales y otros no.

'40-49','premeno','15-19','0-2','yes','3','right','left_up','no','recurrence-events'
'50-59','ge40','15-19','0-2','no','1','right','central','no','no-recurrence-events'
'50-59','ge40','35-39','0-2','no','2','left','left_low','no','recurrence-events'
'40-49','premeno','35-39','0-2','yes','3','right','left_low','yes','no-recurrence-events'
'40-49','premeno','30-34','3-5','yes','2','left','right_up','no','recurrence-events'

Podemos cargar este conjunto de datos en la memoria usando la biblioteca Pandas.

 # load the dataset as a pandas DataFrame
data = read_csv(filename, header=None)
# retrieve numpy array
dataset = data.values

 

Una vez cargados, podemos dividir las columnas en entrada ( X ) y salida ( y ) para modelar.

# split into input (X) and output (y) variables
X = dataset[:, :-1]
y = dataset[:,-1]

Finalmente, podemos forzar que todos los campos en los datos de entrada sean cadenas, en caso de que Pandas intente asignar algunos automáticamente a los números (lo intenta).

También podemos cambiar la forma de la salida variable para ser una columna (por ejemplo, una forma 2D).

# format all fields as string
X = X.astype(str)
# reshape target to be a 2d array
y = y.reshape((len(y), 1))

Podemos vincular todo esto en una función útil que podemos reutilizar más tarde:

 # load the dataset
def load_dataset(filename):
	# load the dataset as a pandas DataFrame
	data = read_csv(filename, header=None)
	# retrieve numpy array
	dataset = data.values
	# split into input (X) and output (y) variables
	X = dataset[:, :-1]
	y = dataset[:,-1]
	# format all fields as string
	X = X.astype(str)
	# reshape target to be a 2d array
	y = y.reshape((len(y), 1))
	return X, y

Una vez cargados, podemos dividir los datos en conjuntos de entrenamiento y prueba para que podamos ajustar y evaluar un modelo de deep learning.

Usaremos la función train_test_split () de scikit-learn y usa el 67% de los datos para el entrenamiento y el 33% para las pruebas.

# load the dataset
X, y = load_dataset('breast-cancer.csv')
# split into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)

Vinculando todos estos elementos, el ejemplo completo de cargar, dividir y resumir el conjunto de datos categórico sin procesar se enumera a continuación.

# load and summarize the dataset
from pandas import read_csv
from sklearn.model_selection import train_test_split
 
# load the dataset
def load_dataset(filename):
	# load the dataset as a pandas DataFrame
	data = read_csv(filename, header=None)
	# retrieve numpy array
	dataset = data.values
	# split into input (X) and output (y) variables
	X = dataset[:, :-1]
	y = dataset[:,-1]
	# format all fields as string
	X = X.astype(str)
	# reshape target to be a 2d array
	y = y.reshape((len(y), 1))
	return X, y
 
# load the dataset
X, y = load_dataset('breast-cancer.csv')
# split into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)
# summarize
print('Train', X_train.shape, y_train.shape)
print('Test', X_test.shape, y_test.shape)

Ejecutar el ejemplo informa el tamaño de los elementos de entrada y salida del tren y los conjuntos de prueba.

Podemos ver que tenemos 191 ejemplos para entrenamiento y 95 para pruebas.

Train (191, 9) (191, 1)
Test (95, 9) (95, 1)

Ahora que estamos familiarizados con el conjunto de datos, veamos cómo podemos codificarlo para el modelado.

Cómo codificar ordinariamente datos categóricos en aprendizaje profundo

Una codificación ordinal implica mapeando cada etiqueta única a un valor entero.

Como tal, a veces se la denomina simplemente como una codificación entera.

Este tipo de codificación solo es apropiado si existe una relación conocida entre las categorías.

Esta relación existe para algunas de las variables en el conjunto de datos, e idealmente, esto debería aprovecharse al preparar los datos.

En este caso, ignoraremos cualquier posible relación ordinal existente y asumiremos que todas las variables son categóricas. Todavía puede ser útil usar una codificación ordinal, al menos como punto de referencia con otros esquemas de codificación.

Podemos usar el OrdinalEncoder () de scikit-learn para codificar cada variable en enteros. Esta es una clase flexible y permite especificar el orden de las categorías como argumentos si se conoce dicho orden.

Nota : lo dejaré como un ejercicio para que actualice el ejemplo a continuación para intentar especificar el orden de las variables que tienen un orden natural y ver si tiene un impacto en el rendimiento del modelo.

La mejor práctica al codificar variables es ajustar la codificación en el conjunto de datos de entrenamiento, luego aplicarla al tren y conjuntos de datos de prueba.

La siguiente función, denominada prepare_inputs () toma los datos de entrada para el tren y los conjuntos de prueba y los codifica utilizando una codificación ordinal.

# prepare input data
def prepare_inputs(X_train, X_test):
	oe = OrdinalEncoder()
	oe.fit(X_train)
	X_train_enc = oe.transform(X_train)
	X_test_enc = oe.transform(X_test)
	return X_train_enc, X_test_enc

También necesitamos preparar la variable objetivo.

Es un problema de clasificación binaria, por lo que debemos asignar las dos etiquetas de clase a 0 y 1.

Este es un tipo de codificación ordinal , y scikit-learn proporciona la clase LabelEncoder específicamente diseñada para este propósito. Podríamos utilizar con la misma facilidad el OrdinalEncoder y lograr el mismo resultado, aunque el LabelEncoder está diseñado para codificar una sola variable.

El prepare_targets () entero codifica los datos de salida para el tren y los conjuntos de prueba.

# prepare target
def prepare_targets(y_train, y_test):
	le = LabelEncoder()
	le.fit(y_train)
	y_train_enc = le.transform(y_train)
	y_test_enc = le.transform(y_test)
	return y_train_enc, y_test_enc

Podemos llamar a estas funciones para preparar nuestros datos.

# prepare input data
X_train_enc, X_test_enc = prepare_inputs(X_train, X_test)
# prepare output data
y_train_enc, y_test_enc = prepare_targets(y_train, y_test)

Ahora podemos definir un modelo de red neuronal.

Utilizaremos el mismo modelo general en todos estos ejemplos. Específicamente, una red neuronal de Perceptrón Multicapa (MLP) con una capa oculta con 10 nodos y un nodo en la capa de salida para realizar clasificaciones binarias.

Sin entrar en demasiados detalles, el código a continuación define el modelo, se ajusta el conjunto de datos de entrenamiento y luego lo evalúa en el conjunto de datos de prueba:

# define the model
model = Sequential()
model.add(Dense(10, input_dim=X_train_enc.shape[1], activation='relu', kernel_initializer='he_normal'))
model.add(Dense(1, activation='sigmoid'))
# compile the keras model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
# fit the keras model on the dataset
model.fit(X_train_enc, y_train_enc, epochs=100, batch_size=16, verbose=2)
# evaluate the keras model
_, accuracy = model.evaluate(X_test_enc, y_test_enc, verbose=0)
print('Accuracy: %.2f' % (accuracy*100))

Al unir todo esto, el ejemplo completo de preparación de los datos con una codificación ordinal y ajuste y evaluación de una red neuronal en los datos se enumera a continuación:

# example of ordinal encoding for a neural network
from pandas import read_csv
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OrdinalEncoder
from keras.models import Sequential
from keras.layers import Dense
 
# load the dataset
def load_dataset(filename):
	# load the dataset as a pandas DataFrame
	data = read_csv(filename, header=None)
	# retrieve numpy array
	dataset = data.values
	# split into input (X) and output (y) variables
	X = dataset[:, :-1]
	y = dataset[:,-1]
	# format all fields as string
	X = X.astype(str)
	# reshape target to be a 2d array
	y = y.reshape((len(y), 1))
	return X, y
 
# prepare input data
def prepare_inputs(X_train, X_test):
	oe = OrdinalEncoder()
	oe.fit(X_train)
	X_train_enc = oe.transform(X_train)
	X_test_enc = oe.transform(X_test)
	return X_train_enc, X_test_enc
 
# prepare target
def prepare_targets(y_train, y_test):
	le = LabelEncoder()
	le.fit(y_train)
	y_train_enc = le.transform(y_train)
	y_test_enc = le.transform(y_test)
	return y_train_enc, y_test_enc
 
# load the dataset
X, y = load_dataset('breast-cancer.csv')
# split into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)
# prepare input data
X_train_enc, X_test_enc = prepare_inputs(X_train, X_test)
# prepare output data
y_train_enc, y_test_enc = prepare_targets(y_train, y_test)
# define the  model
model = Sequential()
model.add(Dense(10, input_dim=X_train_enc.shape[1], activation='relu', kernel_initializer='he_normal'))
model.add(Dense(1, activation='sigmoid'))
# compile the keras model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
# fit the keras model on the dataset
model.fit(X_train_enc, y_train_enc, epochs=100, batch_size=16, verbose=2)
# evaluate the keras model
_, accuracy = model.evaluate(X_test_enc, y_test_enc, verbose=0)
print('Accuracy: %.2f' % (accuracy*100))

La ejecución del ejemplo se ajustará al modelo en solo unos segundos en cualquier hardware moderno (no se requiere GPU).

La pérdida y la precisión de el modelo se informa al final de cada época de entrenamiento y, finalmente, se informa la precisión del modelo en el conjunto de datos de prueba.

Sus resultados específicos variarán dada la naturaleza estocástica del algoritmo de aprendizaje. Intente ejecutar el ejemplo varias veces.

En este caso, podemos ver que el modelo alcanzó una precisión de aproximadamente el 70% en el conjunto de datos de prueba.

No está mal, dado que solo existe una relación ordinal para algunos de los variables de entrada, y para aquellos donde lo hace, no fue respetado en la codificación.

Epoch 95/100
 - 0s - loss: 0.5349 - acc: 0.7696
Epoch 96/100
 - 0s - loss: 0.5330 - acc: 0.7539
Epoch 97/100
 - 0s - loss: 0.5316 - acc: 0.7592
Epoch 98/100
 - 0s - loss: 0.5302 - acc: 0.7696
Epoch 99/100
 - 0s - loss: 0.5291 - acc: 0.7644
Epoch 100/100
 - 0s - loss: 0.5277 - acc: 0.7644
 
Accuracy: 70.53

Esto proporciona un buen punto de partida cuando se trabaja con datos categóricos.

Un enfoque mejor y más general es utilizar una codificación activa.

Cómo codificar datos categóricos en caliente

La codificación activa es apropiada para datos categóricos donde no existe una relación entre categorías.

Implica representar cada variable categórica con un vector binario que tiene un elemento para cada etiqueta única y marcar la etiqueta de clase con un 1 y todos los demás elementos 0. [19659005] Por ejemplo, si nuestra variable era “ color ” y las etiquetas eran “ rojo ,” “ verde ,” y “ azul “, Codificaríamos cada una de estas etiquetas como un vector binario de tres elementos de la siguiente manera:

  • Rojo: [1, 0, 0]
  • Verde: [0, 1, 0]
  • Azul: [0, 0, 1]

Luego, cada etiqueta en el conjunto de datos se reemplazaría con un vector (una columna se convierte en tres). Esto se hace para todas las variables categóricas en aprendizaje profundo, de modo que nuestras nueve variables o columnas de entrada se conviertan en 43 en el caso del conjunto de datos sobre cáncer de mama.

La biblioteca scikit-learn proporciona el OneHotEncoder para codificar automáticamente uno o uno más variables.

La función prepare_inputs () a continuación proporciona una función de sustitución directa para el ejemplo de la sección anterior. En lugar de utilizar un OrdinalEncoder utiliza un OneHotEncoder .

# prepare input data
def prepare_inputs(X_train, X_test):
	ohe = OneHotEncoder()
	ohe.fit(X_train)
	X_train_enc = ohe.transform(X_train)
	X_test_enc = ohe.transform(X_test)
	return X_train_enc, X_test_enc

Al unir esto, el ejemplo completo de una codificación activa del conjunto de datos categórico del cáncer de mama y su modelado con una red neuronal se enumera a continuación.

# example of one hot encoding for a neural network
from pandas import read_csv
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder
from keras.models import Sequential
from keras.layers import Dense
 
# load the dataset
def load_dataset(filename):
	# load the dataset as a pandas DataFrame
	data = read_csv(filename, header=None)
	# retrieve numpy array
	dataset = data.values
	# split into input (X) and output (y) variables
	X = dataset[:, :-1]
	y = dataset[:,-1]
	# format all fields as string
	X = X.astype(str)
	# reshape target to be a 2d array
	y = y.reshape((len(y), 1))
	return X, y
 
# prepare input data
def prepare_inputs(X_train, X_test):
	ohe = OneHotEncoder()
	ohe.fit(X_train)
	X_train_enc = ohe.transform(X_train)
	X_test_enc = ohe.transform(X_test)
	return X_train_enc, X_test_enc
 
# prepare target
def prepare_targets(y_train, y_test):
	le = LabelEncoder()
	le.fit(y_train)
	y_train_enc = le.transform(y_train)
	y_test_enc = le.transform(y_test)
	return y_train_enc, y_test_enc
 
# load the dataset
X, y = load_dataset('breast-cancer.csv')
# split into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)
# prepare input data
X_train_enc, X_test_enc = prepare_inputs(X_train, X_test)
# prepare output data
y_train_enc, y_test_enc = prepare_targets(y_train, y_test)
# define the  model
model = Sequential()
model.add(Dense(10, input_dim=X_train_enc.shape[1], activation='relu', kernel_initializer='he_normal'))
model.add(Dense(1, activation='sigmoid'))
# compile the keras model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
# fit the keras model on the dataset
model.fit(X_train_enc, y_train_enc, epochs=100, batch_size=16, verbose=2)
# evaluate the keras model
_, accuracy = model.evaluate(X_test_enc, y_test_enc, verbose=0)
print('Accuracy: %.2f' % (accuracy*100))

El ejemplo uno codifica los datos categóricos de entrada, y también la etiqueta codifica la variable objetivo como lo hicimos en la sección anterior. El mismo modelo de red neuronal se ajusta al conjunto de datos preparado.

Sus resultados específicos variarán dada la naturaleza estocástica del algoritmo de aprendizaje. Intente ejecutar el ejemplo varias veces.

En este caso, el modelo funciona razonablemente bien, logrando una precisión de aproximadamente el 72%, cerca de lo que se vio en la sección anterior.

Una comparación más justa sería ejecutar cada configuración 10 o 30 veces y compare el rendimiento utilizando la precisión media. Recuerde que estamos más centrados en cómo codificar datos categóricos en aprendizaje profundo en este tutorial en lugar de obtener la mejor puntuación en este conjunto de datos específico.

Epoch 95/100
 - 0s - loss: 0.3837 - acc: 0.8272
Epoch 96/100
 - 0s - loss: 0.3823 - acc: 0.8325
Epoch 97/100
 - 0s - loss: 0.3814 - acc: 0.8325
Epoch 98/100
 - 0s - loss: 0.3795 - acc: 0.8325
Epoch 99/100
 - 0s - loss: 0.3788 - acc: 0.8325
Epoch 100/100
 - 0s - loss: 0.3773 - acc: 0.8325
 
Accuracy: 72.63

La codificación ordinaria y una en caliente son quizás los dos métodos más populares.

Una técnica más nueva es similar a una codificación en caliente y fue diseñada para su uso con redes neuronales, llamada incrustación aprendida.

Cómo Utilice una incrustación aprendida para datos categóricos

Una incrustación aprendida, o simplemente una incrustación [ ”es una representación distribuida para datos categóricos.

Cada categoría se asigna a un vector distinto y las propiedades del vector se adaptan o aprenden mientras se entrena una red neuronal. El espacio vectorial proporciona una proyección de las categorías, lo que permite que las categorías cercanas o relacionadas con el clúster se agrupen naturalmente.

Esto proporciona los beneficios de una relación ordinal al permitir que tales relaciones se aprendan de los datos, y una codificación al proporcionar una representación vectorial para cada categoría. A diferencia de una codificación activa, los vectores de entrada no son escasos (no tienen muchos ceros). La desventaja es que requiere el aprendizaje como parte del modelo y la creación de muchas más variables de entrada (columnas).

La técnica se desarrolló originalmente para proporcionar una representación distribuida de palabras, p. permitiendo que palabras similares tengan representaciones vectoriales similares. Como tal, la técnica a menudo se denomina incrustación de palabras y, en el caso de los datos de texto, se han desarrollado algoritmos para aprender una representación independiente de una red neuronal. }

Un beneficio adicional de usar una incrustación es que los vectores aprendidos a los que se asigna cada categoría se pueden ajustar en un modelo que tiene una habilidad modesta, pero los vectores se pueden extraer y usar generalmente como entrada para la categoría en una gama de diferentes modelos y aplicaciones. Es decir, se pueden aprender y reutilizar.

Las incrustaciones se pueden usar en Keras a través de la capa Incrustación.

Se requiere una capa de incrustación para cada variable categórica, y la incrustación espera que las categorías se codifiquen ordinalmente, aunque no hay relación entre las categorías se supone.

Cada incrustación también requiere el número de dimensiones a utilizar para la representación distribuida (espacio vectorial). Es común en las aplicaciones de lenguaje natural usar 50, 100 o 300 dimensiones. Para nuestro pequeño ejemplo, fijaremos el número de dimensiones en 10, pero esto es arbitrario; debe experimentar con otros valores.

Primero, podemos preparar los datos de entrada utilizando una codificación ordinal.

El modelo que desarrollaremos tendrá una incrustación separada para cada variable de entrada. Por lo tanto, el modelo tomará nueve conjuntos de datos de entrada diferentes. Como tal, dividiremos las variables de entrada y la codificación ordinal (codificación entera) cada una por separado usando el LabelEncoder y devolveremos una lista de conjuntos de datos de entrada de prueba y tren preparados por separado.

El prepare_inputs () la siguiente función implementa esto, enumerando cada variable de entrada, codificando cada número correctamente usando las mejores prácticas y devolviendo listas de variables de prueba y tren codificadas (o conjuntos de datos de una variable) que pueden usarse como entrada para nuestro modelo más adelante.

# prepare input data
def prepare_inputs(X_train, X_test):
	X_train_enc, X_test_enc = list(), list()
	# label encode each column
	for i in range(X_train.shape[1]):
		le = LabelEncoder()
		le.fit(X_train[:, i])
		# encode
		train_enc = le.transform(X_train[:, i])
		test_enc = le.transform(X_test[:, i])
		# store
		X_train_enc.append(train_enc)
		X_test_enc.append(test_enc)
	return X_train_enc, X_test_enc

Ahora podemos construir el modelo.

Debemos construir el modelo de manera diferente en este caso porque tendremos nueve capas de entrada, con nueve incrustaciones cuyas salidas (los nueve vectores diferentes de 10 elementos) es necesario concatenarlo en un vector largo antes de pasarlo como entrada a las capas densas.

Podemos lograr esto usando la API funcional de Keras. Si es nuevo en la API funcional de Keras, consulte la publicación:

Primero, podemos enumerar cada variable y construir una capa de entrada y conectar a una capa de incrustación y almacene ambas capas en listas. Necesitamos una referencia a todas las capas de entrada al definir el modelo, y necesitamos una referencia a cada capa de incrustación para concentrarlas con una capa de fusión.

# prepare each input head
in_layers = list()
em_layers = list()
for i in range(len(X_train_enc)):
	# calculate the number of unique inputs
	n_labels = len(unique(X_train_enc[i]))
	# define input layer
	in_layer = Input(shape=(1,))
	# define embedding layer
	em_layer = Embedding(n_labels, 10)(in_layer)
	# store layers
	in_layers.append(in_layer)
	em_layers.append(em_layer)

Luego podemos fusionar todas las capas de incrustación, definir la capa oculta y la capa de salida, luego definir el modelo.

# concat all embeddings
merge = concatenate(em_layers)
dense = Dense(10, activation='relu', kernel_initializer='he_normal')(merge)
output = Dense(1, activation='sigmoid')(dense)
model = Model(inputs=in_layers, outputs=output)

Al usar un modelo con múltiples entradas, necesitaremos especificar una lista que tenga un conjunto de datos para cada entrada, p. Una lista de nueve matrices, cada una con una columna en el caso de nuestro conjunto de datos. Afortunadamente, este es el formato que devolvimos de nuestra función prepare_inputs () .

Por lo tanto, ajustar y evaluar el modelo se ve como en la sección anterior.

Además, trazaremos el modelo llamando a la función plot_model () y guárdelo en el archivo. Esto requiere que pygraphviz y pydot estén instalados, lo que puede ser un problema en algunos sistemas. Si tiene problemas simplemente comente la declaración de importación y llame al plot_model () .

# compile the keras model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
# plot graph
plot_model(model, show_shapes=True, to_file='embeddings.png')
# fit the keras model on the dataset
model.fit(X_train_enc, y_train_enc, epochs=20, batch_size=16, verbose=2)
# evaluate the keras model
_, accuracy = model.evaluate(X_test_enc, y_test_enc, verbose=0)
print('Accuracy: %.2f' % (accuracy*100))

Al unir todo esto, el ejemplo completo de usar una incrustación separada para cada variable de entrada categórica en un modelo de capa de entrada múltiple se enumera a continuación:

# example of learned embedding encoding for a neural network
from numpy import unique
from pandas import read_csv
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from keras.models import Model
from keras.layers import Input
from keras.layers import Dense
from keras.layers import Embedding
from keras.layers.merge import concatenate
from keras.utils import plot_model
 
# load the dataset
def load_dataset(filename):
	# load the dataset as a pandas DataFrame
	data = read_csv(filename, header=None)
	# retrieve numpy array
	dataset = data.values
	# split into input (X) and output (y) variables
	X = dataset[:, :-1]
	y = dataset[:,-1]
	# format all fields as string
	X = X.astype(str)
	# reshape target to be a 2d array
	y = y.reshape((len(y), 1))
	return X, y
 
# prepare input data
def prepare_inputs(X_train, X_test):
	X_train_enc, X_test_enc = list(), list()
	# label encode each column
	for i in range(X_train.shape[1]):
		le = LabelEncoder()
		le.fit(X_train[:, i])
		# encode
		train_enc = le.transform(X_train[:, i])
		test_enc = le.transform(X_test[:, i])
		# store
		X_train_enc.append(train_enc)
		X_test_enc.append(test_enc)
	return X_train_enc, X_test_enc
 
# prepare target
def prepare_targets(y_train, y_test):
	le = LabelEncoder()
	le.fit(y_train)
	y_train_enc = le.transform(y_train)
	y_test_enc = le.transform(y_test)
	return y_train_enc, y_test_enc
 
# load the dataset
X, y = load_dataset('breast-cancer.csv')
# split into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)
# prepare input data
X_train_enc, X_test_enc = prepare_inputs(X_train, X_test)
# prepare output data
y_train_enc, y_test_enc = prepare_targets(y_train, y_test)
# make output 3d
y_train_enc = y_train_enc.reshape((len(y_train_enc), 1, 1))
y_test_enc = y_test_enc.reshape((len(y_test_enc), 1, 1))
# prepare each input head
in_layers = list()
em_layers = list()
for i in range(len(X_train_enc)):
	# calculate the number of unique inputs
	n_labels = len(unique(X_train_enc[i]))
	# define input layer
	in_layer = Input(shape=(1,))
	# define embedding layer
	em_layer = Embedding(n_labels, 10)(in_layer)
	# store layers
	in_layers.append(in_layer)
	em_layers.append(em_layer)
# concat all embeddings
merge = concatenate(em_layers)
dense = Dense(10, activation='relu', kernel_initializer='he_normal')(merge)
output = Dense(1, activation='sigmoid')(dense)
model = Model(inputs=in_layers, outputs=output)
# compile the keras model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
# plot graph
plot_model(model, show_shapes=True, to_file='embeddings.png')
# fit the keras model on the dataset
model.fit(X_train_enc, y_train_enc, epochs=20, batch_size=16, verbose=2)
# evaluate the keras model
_, accuracy = model.evaluate(X_test_enc, y_test_enc, verbose=0)
print('Accuracy: %.2f' % (accuracy*100))

Ejecutar el ejemplo prepara los datos como se describió anteriormente, se ajusta al modelo e informa el rendimiento.

Sus resultados específicos variarán dada la naturaleza estocástica del algoritmo de aprendizaje. Intente ejecutar el ejemplo varias veces.

En este caso, el modelo funciona razonablemente bien, coincidiendo con lo que vimos para la codificación activa en la sección anterior.

Como los vectores aprendidos fueron entrenados en un modelo experto, es posible guardarlos y usarlos como una representación general de estas variables en otros modelos que operan con los mismos datos. Una razón útil y convincente para explorar esta codificación.

Epoch 15/20
 - 0s - loss: 0.4891 - acc: 0.7696
Epoch 16/20
 - 0s - loss: 0.4845 - acc: 0.7749
Epoch 17/20
 - 0s - loss: 0.4783 - acc: 0.7749
Epoch 18/20
 - 0s - loss: 0.4763 - acc: 0.7906
Epoch 19/20
 - 0s - loss: 0.4696 - acc: 0.7906
Epoch 20/20
 - 0s - loss: 0.4660 - acc: 0.7958
 
Accuracy: 72.63

Para confirmar nuestra comprensión del modelo, se crea un gráfico y se guarda en el archivo embeddings.png en el directorio de trabajo actual.

El gráfico muestra las nueve entradas asignadas a un vector de 10 elementos, lo que significa que la entrada real al modelo es un vector de 90 elementos.

Nota : Haga clic en la imagen para ver la versión grande.

 Gráfico de la arquitectura del modelo con entradas e incrustaciones separadas para cada categórico Variable

Gráfico de la arquitectura del modelo con entradas e incorporaciones separadas para cada variable categórica
Haga clic para ampliar.

Preguntas comunes

Esta sección enumera algunas preguntas y respuestas comunes al codificar datos categóricos.

¿Qué sucede si tengo una mezcla de datos numéricos y categóricos?

O, ¿qué sucede si tengo una mezcla de datos categóricos y ordinales?

Deberá preparar o codificar cada variable (columna) en su conjunto de datos por separado, luego concatene todas las variables preparadas nuevamente en una sola matriz para ajustar o evaluar el modelo.

¿Qué sucede si tengo cientos de categorías?

O, ¿qué sucede si concateno muchos vectores codificados en caliente para crear un vector de entrada de miles de elementos?

Puede usar una codificación activa de hasta miles y decenas de miles de categorías . Además, tener vectores grandes como entrada suena intimidante, pero los modelos generalmente pueden manejarlo.

Pruebe una incrustación; it offers the benefit of a smaller vector space (a projection) and the representation can have more meaning.

¿Qué técnica de codificación es la mejor?

Esto no se puede saber.

Pruebe cada técnica (y más) en su conjunto de datos con su modelo elegido y descubra qué funciona mejor para su caso.

APIs

Datasets

 

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *