La biblioteca de Python para el aprendizaje automático ofrece un conjunto de transformaciones de datos para cambiar la escala y la distribución de los datos de entrada, así como para eliminar las características de entrada (columnas).
Hay muchas operaciones sencillas de limpieza de datos, como la eliminación de valores atípicos y la eliminación de columnas con pocas observaciones, que a menudo se realizan manualmente a los datos, lo que requiere un código personalizado.
La biblioteca de aprendizaje de ciencias proporciona una forma de envolver estos los datos personalizados se transforman de una manera estándar para que puedan ser usadas como cualquier otra transformación, ya sea en datos directamente o como parte de una tubería de modelación.
En este tutorial, descubrirá cómo definir y utilizar las transformaciones de datos personalizados para el aprendizaje de la ciencia.
Después de completar este tutorial, lo sabrás:
- Esos transformadores de datos personalizados pueden ser creados para el aprendizaje de la ciencia usando la clase FunctionTransformer.
- Cómo desarrollar y aplicar una transformación personalizada para eliminar columnas con pocos valores únicos.
- Cómo desarrollar y aplicar una transformación personalizada que reemplace los valores atípicos de cada columna.
Descubre la limpieza de datos, la selección de características, la transformación de datos, la reducción de la dimensionalidad y mucho más en mi nuevo libro, con 30 tutoriales paso a paso y el código fuente completo en Python.
Empecemos.
Resumen del Tutorial
Este tutorial está dividido en cuatro partes; son:
- Los datos personalizados se transforman en Scikit-Learn
- Conjunto de datos sobre el derrame de petróleo
- Transformación personalizada para eliminar las columnas
- Transformación personalizada para reemplazar los valores atípicos
Los datos personalizados se transforman en Scikit-Learn
La preparación de datos se refiere a cambiar los datos en bruto de alguna manera que los haga más apropiados para el modelado predictivo con algoritmos de aprendizaje automático.
La biblioteca de aprendizaje de la máquina Python de aprendizaje científico ofrece directamente muchas técnicas diferentes de preparación de datos, como las técnicas para escalar las variables de entrada numérica y cambiar la distribución de probabilidad de las variables.
Estas transformaciones pueden ajustarse y luego aplicarse en un conjunto de datos o utilizarse como parte de un proceso de modelización predictiva, lo que permite aplicar correctamente una secuencia de transformaciones sin fugas de datos al evaluar el rendimiento del modelo con técnicas de muestreo de datos, como la validación cruzada de pliegues k.
Si bien las técnicas de preparación de datos disponibles en Scikit-learn son extensas, puede haber pasos adicionales de preparación de datos que se requieran.
Típicamente, estos pasos adicionales se realizan manualmente antes del modelado y requieren la escritura de un código personalizado. El riesgo es que estos pasos de preparación de datos se realicen de manera inconsistente.
La solución es crear un transformador de datos personalizado en scikit-learn usando la clase FunctionTransformer.
Esta clase permite especificar una función que se llama para transformar los datos. Puede definir la función y realizar cualquier cambio válido, como modificar valores o eliminar columnas de datos (no eliminar filas).
La clase puede utilizarse entonces como cualquier otra transformación de datos en scikit-learn, por ejemplo, para transformar datos directamente, o utilizarse en un conducto de modelización.
El truco es que la transformación es apátridalo que significa que no se puede mantener ningún estado.
Esto significa que la transformación no puede utilizarse para calcular estadísticas sobre el conjunto de datos de entrenamiento que luego se utilizan para transformar el tren y los conjuntos de datos de prueba.
Además de las operaciones de escalado personalizadas, esto puede ser útil para las operaciones de limpieza de datos estándar, como la identificación y eliminación de columnas con pocos valores únicos y la identificación y eliminación de valores atípicos relativos.
Exploraremos ambos casos, pero primero, definamos un conjunto de datos que podamos usar como base para la exploración.
Conjunto de datos sobre el derrame de petróleo
El llamado conjunto de datos de «derrame de petróleo» es un conjunto de datos estándar de aprendizaje de máquinas.
La tarea consiste en predecir si un parche contiene o no un derrame de petróleo, por ejemplo, del vertido ilegal o accidental de petróleo en el océano, dado un vector que describe el contenido de un parche de una imagen satelital.
Hay 937 casos. Cada caso se compone de 48 características numéricas derivadas de la visión computarizada, un número de parche y una etiqueta de clase.
El caso normal es que a ningún derrame de petróleo se le asigne la etiqueta de clase 0, mientras que un derrame de petróleo se indica con la etiqueta de clase 1. Hay 896 casos de no derrame de petróleo y 41 casos de derrame de petróleo.
Puedes acceder a todo el conjunto de datos aquí:
Revise el contenido del archivo.
Las primeras líneas del archivo deben verse como sigue:
1,2558,1506.09,456.63,90,6395000,40.88,7.89,29780,0.19,214.7,0.21,0.26,0.49,0.1,0.4,99.59,32.19,1.84,0.16,0.2,87.65,0,0.47,132.78,-0.01,3.78,0.22,3.2,-3.71,-0.18,2.19,0,2.19,310,16110,0,138.68,89,69,2850,1000,763.16,135.46,3.73,0,33243.19,65.74,7.95,1 2,22325,79.11,841.03,180,55812500,51.11,1.21,61900,0.02,901.7,0.02,0.03,0.11,0.01,0.11,6058.23,4061.15,2.3,0.02,0.02,87.65,0,0.58,132.78,-0.01,3.78,0.84,7.09,-2.21,0,0,0,0,704,40140,0,68.65,89,69,5750,11500,9593.48,1648.8,0.6,0,51572.04,65.73,6.26,0 3,115,1449.85,608.43,88,287500,40.42,7.34,3340,0.18,86.1,0.21,0.32,0.5,0.17,0.34,71.2,16.73,1.82,0.19,0.29,87.65,0,0.46,132.78,-0.01,3.78,0.7,4.79,-3.36,-0.23,1.95,0,1.95,29,1530,0.01,38.8,89,69,1400,250,150,45.13,9.33,1,31692.84,65.81,7.84,1 4,1201,1562.53,295.65,66,3002500,42.4,7.97,18030,0.19,166.5,0.21,0.26,0.48,0.1,0.38,120.22,33.47,1.91,0.16,0.21,87.65,0,0.48,132.78,-0.01,3.78,0.84,6.78,-3.54,-0.33,2.2,0,2.2,183,10080,0,108.27,89,69,6041.52,761.58,453.21,144.97,13.33,1,37696.21,65.67,8.07,1 5,312,950.27,440.86,37,780000,41.43,7.03,3350,0.17,232.8,0.15,0.19,0.35,0.09,0.26,289.19,48.68,1.86,0.13,0.16,87.65,0,0.47,132.78,-0.01,3.78,0.02,2.28,-3.44,-0.44,2.19,0,2.19,45,2340,0,14.39,89,69,1320.04,710.63,512.54,109.16,2.58,0,29038.17,65.66,7.35,0 … |
Podemos ver que la primera columna contiene números enteros para el número de parche. También podemos ver que los rasgos derivados de la visión por ordenador se valoran con escalas diferentes, como miles en la segunda columna y fracciones en otras columnas.
Este conjunto de datos contiene columnas con muy pocos valores únicos y columnas con valores atípicos que proporcionan una buena base para la limpieza de los datos.
El ejemplo que figura a continuación descarga el conjunto de datos y lo carga como una matriz numPy y resume el número de filas y columnas.
# Cargar el conjunto de datos del petróleo de la importación de pandas read_csv # Definir la ubicación del conjunto de datos path=»https://raw.githubusercontent.com/jbrownlee/Datasets/master/oil-spill.csv» # Cargar el conjunto de datos df = read_csv(path, header=None) # Dividir los datos en entradas y salidas datos = df.values X = datos[:, :-1] y = datos[:, -1] impresión (forma X, forma Y) |
Ejecutando el ejemplo se carga el conjunto de datos y se confirma el número esperado de filas y columnas.
Ahora que tenemos un conjunto de datos que podemos usar como base para las transformaciones de datos, veamos cómo podemos definir algunas transformaciones de limpieza de datos personalizadas usando el Transformador de funciones clase.
Transformación personalizada para eliminar las columnas
Las columnas que tienen pocos valores únicos probablemente no aportan nada útil para predecir el valor del objetivo.
Esto no es absolutamente cierto, pero es lo suficientemente cierto como para que usted deba probar el rendimiento del ajuste de su modelo en un conjunto de datos con las columnas de este tipo eliminadas.
Se trata de un tipo de limpieza de datos, y existe una transformación de datos proporcionada en scikit-learn llamada VarianceThreshold que intenta abordar esto utilizando la varianza de cada columna.
Otro enfoque consiste en eliminar las columnas que tienen menos de un número determinado de valores únicos, como 1.
Podemos desarrollar una función que aplique esta transformación y utilizar el número mínimo de valores únicos como argumento predeterminado configurable. También añadiremos alguna depuración para confirmar que funciona como esperamos.
En primer lugar, se puede calcular el número de valores únicos para cada columna. Se pueden identificar diez columnas con un número igual o inferior al número mínimo de valores únicos. Finalmente, esas columnas identificadas pueden ser eliminadas del conjunto de datos.
El cust_transform() La función de abajo implementa esto.
# Eliminar las columnas con pocos valores únicos def cust_transform(X, min_valores=1, verboso=Verdadero): # Obtener el número de valores únicos para cada columna cuenta = [[len(único(X[[:, i])) para i en rango(X.forma[[1])] si verboso: imprimir(«Valores únicos: %s % cuenta) # Seleccionar las columnas a eliminar to_del = [[i para i,v en enumerar(cuenta) si v <= min_valores] si verboso: imprimir(«Borrar: %s % to_del) si len(to_del) es 0: volver X # Seleccionar todas las columnas excepto las que están siendo eliminadas ix = [[i para i en rango(X.forma[[1]) si i no en to_del] resultado = X[[:, ix] volver resultado |
Podemos usar esta función en el Transformador de Funciones.
Una limitación de esta transformación es que selecciona las columnas a eliminar en base a los datos proporcionados. Esto significa que si un tren y un conjunto de datos de prueba difieren enormemente, entonces es posible que se eliminen diferentes columnas de cada uno, lo que dificulta la evaluación del modelo (inestable!?). Por lo tanto, es mejor mantener el número mínimo de valores únicos pequeños, como 1.
Podemos usar esta transformación en el conjunto de datos del derrame de petróleo. El ejemplo completo se muestra a continuación.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# Transformación de datos personalizados para eliminar columnas con pocos valores únicos de numpy importación único de pandas importación read_csv de sklearn.preprocesamiento importación Transformador de funciones de sklearn.preprocesamiento importación LabelEncoder # Cargar un conjunto de datos def load_dataset(camino): # Cargar el conjunto de datos df = read_csv(camino, encabezado=Ninguno) datos = df.valores # Dividir los datos en entradas y salidas X, y = datos[[:, :–1], datos[[:, –1] # Preparar mínimamente el conjunto de datos X = X.astype(«flotar) y = LabelEncoder().fit_transform(y.astype(«str)) volver X, y # Eliminar las columnas con pocos valores únicos def cust_transform(X, min_valores=1, verboso=Verdadero): # Obtener el número de valores únicos para cada columna cuenta = [[len(único(X[[:, i])) para i en rango(X.forma[[1])] si verboso: imprimir(«Valores únicos: %s % cuenta) # Seleccionar las columnas a eliminar to_del = [[i para i,v en enumerar(cuenta) si v <= min_valores] si verboso: imprimir(«Borrar: %s % to_del) si len(to_del) es 0: volver X # Seleccionar todas las columnas excepto las que están siendo eliminadas ix = [[i para i en rango(X.forma[[1]) si i no en to_del] resultado = X[[:, ix] volver resultado # Definir la ubicación del conjunto de datos url = «https://raw.githubusercontent.com/jbrownlee/Datasets/master/oil-spill.csv # Cargar el conjunto de datos X, y = load_dataset(url) imprimir(X.forma, y.forma) # definir el transformador trans = Transformador de funciones(cust_transform) # Aplicar la transformación X = trans.fit_transform(X) # resumir la nueva forma imprimir(X.forma) |
Ejecutando el ejemplo primero se reporta el número de filas y columnas en el conjunto de datos en bruto.
A continuación, se imprime una lista que muestra el número de valores únicos observados para cada columna del conjunto de datos. Podemos ver que muchas columnas tienen muy pocos valores únicos.
Las columnas con uno (o menos) valores únicos son entonces identificadas y reportadas. En este caso, el índice de la columna es el 22. Esta columna se elimina del conjunto de datos.
Por último, se informa de la forma del conjunto de datos transformados, que muestra 48 en lugar de 49 columnas, lo que confirma que se ha eliminado la columna con un único valor.
(937, 49) (937,) Valores únicos: [238, 297, 927, 933, 179, 375, 820, 618, 561, 57, 577, 59, 73, 107, 53, 91, 893, 810, 170, 53, 68, 9, 1, 92, 9, 8, 9, 308, 447, 392, 107, 42, 4, 45, 141, 110, 3, 758, 9, 9, 388, 220, 644, 649, 499, 2, 937, 169, 286] Borrando: [22] (937, 48) |
Hay muchas extensiones que podrías explorar para esta transformación, como:
- Asegúrate de que sólo se aplica a las variables de entrada numérica.
- Experimentar con un número mínimo diferente de valores únicos.
- Utilice un porcentaje en lugar de un número absoluto de valores únicos.
Si exploras alguna de estas extensiones, házmelo saber en los comentarios de abajo.
A continuación, veamos una transformación que reemplaza los valores en el conjunto de datos.
Transformación personalizada para reemplazar los valores atípicos
Los valores atípicos son observaciones que son diferentes o distintas de las otras observaciones.
Si consideramos una variable a la vez, un valor atípico sería un valor que está lejos del centro de masa (el resto de los valores), lo que significa que es raro o tiene una baja probabilidad de ser observado.
Existen formas estándar de identificar los valores atípicos para las distribuciones de probabilidad comunes. En el caso de los datos gausianos, podemos identificar los valores atípicos como observaciones que tienen tres o más desviaciones estándar de la media.
Esta puede ser o no una forma deseable de identificar valores atípicos para datos que tienen muchas variables de entrada, aunque puede ser eficaz en algunos casos.
Podemos identificar los valores atípicos de esta manera y reemplazar su valor con una corrección, como la media.
Cada columna se considera una a la vez y se calculan las estadísticas de la media y la desviación estándar. Usando estas estadísticas, los límites superiores e inferiores de «normal«se definen los valores, entonces todos los valores que caen fuera de estos límites pueden ser identificados. Si se identifican uno o más valores atípicos, sus valores se sustituyen por el valor medio ya calculado.
El cust_transform() La función que figura a continuación lo implementa como una función aplicada al conjunto de datos, donde se parametriza el número de desviaciones estándar de la media y si se mostrará o no la información de depuración.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# Reemplazar los valores atípicos def cust_transform(X, n_stdev=3, verboso=Verdadero): # Copia la matriz resultado = X.copia() # enumerar cada columna para i en rango(resultado.forma[[1]): # Recuperar los valores de la columna col = X[[:, i] # Calcular las estadísticas mu, sigma = significa(col), std(col) # Definir los límites más bajo, superior = mu–(sigma*n_stdev), mu+(sigma*n_stdev) # Seleccionar los índices que están fuera de los límites ix = donde(lógica_o(col < más bajo, col > superior))[[0] si verboso y len(ix) > 0: imprimir(‘>col=%d, valores atípicos=%d’ % (i, len(ix))) # Reemplazar los valores resultado[[ix, i] = mu volver resultado |
Podemos usar esta función en el Transformador de Funciones.
El método de detección de valores atípicos supone una distribución de probabilidad gaussiana y se aplica a cada variable de forma independiente, y ambos son supuestos sólidos.
Una limitación adicional de esta aplicación es que las estadísticas de la media y la desviación estándar se calculan sobre el conjunto de datos proporcionados, lo que significa que la definición de un valor atípico y su valor de sustitución son ambos relativos al conjunto de datos. Esto significa que podrían utilizarse diferentes definiciones de valores atípicos y diferentes valores de sustitución si la transformación se utiliza en el tren y en los conjuntos de pruebas.
Podemos usar esta transformación en el conjunto de datos del derrame de petróleo. El ejemplo completo se muestra a continuación.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# Transformación de datos personalizados para reemplazar los valores atípicos de numpy importación significa de numpy importación std de numpy importación donde de numpy importación lógica_o de pandas importación read_csv de sklearn.preprocesamiento importación Transformador de funciones de sklearn.preprocesamiento importación LabelEncoder # Cargar un conjunto de datos def load_dataset(camino): # Cargar el conjunto de datos df = read_csv(camino, encabezado=Ninguno) datos = df.valores # Dividir los datos en entradas y salidas X, y = datos[[:, :–1], datos[[:, –1] # Preparar mínimamente el conjunto de datos X = X.astype(«flotar) y = LabelEncoder().fit_transform(y.astype(«str)) volver X, y # Reemplazar los valores atípicos def cust_transform(X, n_stdev=3, verboso=Verdadero): # Copia la matriz resultado = X.copia() # enumerar cada columna para i en rango(resultado.forma[[1]): # Recuperar los valores de la columna col = X[[:, i] # Calcular las estadísticas mu, sigma = significa(col), std(col) # Definir los límites más bajo, superior = mu–(sigma*n_stdev), mu+(sigma*n_stdev) # Seleccionar los índices que están fuera de los límites ix = donde(lógica_o(col < más bajo, col > superior))[[0] si verboso y len(ix) > 0: imprimir(‘>col=%d, valores atípicos=%d’ % (i, len(ix))) # Reemplazar los valores resultado[[ix, i] = mu volver resultado # Definir la ubicación del conjunto de datos url = «https://raw.githubusercontent.com/jbrownlee/Datasets/master/oil-spill.csv # Cargar el conjunto de datos X, y = load_dataset(url) imprimir(X.forma, y.forma) # definir el transformador trans = Transformador de funciones(cust_transform) # Aplicar la transformación X = trans.fit_transform(X) # resumir la nueva forma imprimir(X.forma) |
Ejecutando el ejemplo primero reporta la forma del conjunto de datos antes de cualquier cambio.
A continuación, se calcula el número de valores atípicos de cada columna y sólo se incluyen en el resultado las columnas con uno o más valores atípicos. Podemos ver que un total de 32 columnas en el conjunto de datos tienen uno o más valores atípicos.
A continuación se eliminan los valores atípicos y se informa de la forma del conjunto de datos resultante, confirmando que no se ha producido ningún cambio en el número de filas o columnas.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
(937, 49) (937,) >col=0, valores atípicos=10 >col=1, valores atípicos=8 >col=3, valores atípicos=8 >col=5, valores atípicos=7 >col=6, valores atípicos=1 >col=7, valores atípicos=12 >col=8, valores atípicos=15 >col=9, valores atípicos=14 >col=10, valores atípicos=19 >col=11, valores atípicos=17 >col=12, valores atípicos=22 >col=13, valores atípicos=2 >col=14, valores atípicos=16 >col=15, valores atípicos=8 >col=16, valores atípicos=8 >col=17, valores atípicos=6 >col=19, valores atípicos=12 >col=20, valores atípicos=20 >col=27, valores atípicos=14 >col=28, valores atípicos=18 >col=29, valores atípicos=2 >col=30, valores atípicos=13 >col=32, valores atípicos=3 >col=34, valores atípicos=14 >col=35, valores atípicos=15 >col=37, valores atípicos=13 >col=40, valores atípicos=18 >col=41, valores atípicos=13 >col=42, valores atípicos=12 >col=43, valores atípicos=12 >col=44, valores atípicos=19 >col=46, valores atípicos=21 (937, 49) |
Hay muchas extensiones que podrías explorar para esta transformación, como:
- Asegúrate de que sólo se aplica a las variables de entrada numérica.
- Experimente con un número diferente de desviaciones estándar de la media, como 2 o 4.
- Usar una definición diferente de los valores atípicos, como el IQR o un modelo.
Si exploras alguna de estas extensiones, házmelo saber en los comentarios de abajo.