sábado, 14 de noviembre de 2020

Crear un set de pruebas para Machine Learning

En teoría es simple, consiste en tomar algunos registros aleatoriamente de nuestros datos. Típicamente un 20% de nuestro set de datos, o menos incluso si tenemos muchos datos.
El objeto Datos es el set de datos creado en el post anterior con los datos de nuestro archivo csv retiro.csv.

set de pruebas para Machine Learning


import numpy as np

# Para enseñanza solo NO UTILIZAR EN CASOS REALES. Sklearn tiene su propia definición de train_test_split()
def split_train_test(datos, test_ratio):
    shuffled_indices = np.random.permutation(len(datos))
    test_set_size = int(len(datos) * test_ratio)
    test_indices = shuffled_indices[:test_set_size]
    train_indices = shuffled_indices[test_set_size:]
    return datos.iloc[train_indices], datos.iloc[test_indices]


Utilizamos esta función para crear nuestro set de datos con el 20% de ellos

train_set, test_set = split_train_test(datos, 0.2)
len(train_set)

Para elegir un set de pruebas en función del Id de una columna podemos utilizar esta función.

from zlib import crc32

def test_set_check(identifier, test_ratio):
    return crc32(np.int64(identifier)) & 0xffffffff < test_ratio * 2**32

def split_train_test_by_id(datos, test_ratio, id_column):
    ids = datos[id_column]
    in_test_set = ids.apply(lambda id_: test_set_check(id_, test_ratio))
    return datos.loc[~in_test_set], datos.loc[in_test_set]

Si nuestro conjunto de datos no dispone de una columna identificadora, podemos utilizar el índice de las filas como ID.

datos_con_id = datos.reset_index()   # añade una columa de índice
train_set, test_set = split_train_test_by_id(datos_con_id, 0.2, "index")

Si vamos a utilizar este índice como identificador único de nuestro conjunto de datos, debemos asegurarnos de que los nuevos datos sean añadidos siempre al final de nuestro conjunto de datos y no debemos eliminar ninguna fila de este conjunto. Si esto no fuera posible debemos utilizar una columna con las características más estables posibles para construir un identificador único. Por ejemplo en nuestro conjunto de datos, el año es la ideal.

datos_con_id["id"] = datos["Año"]
train_set, test_set = split_train_test_by_id(datos_con_id, 0.2, "id")
test_set.head()

Scikit-Learn provee varias funciones para cortar sets de datos, la más simple es  train_test_split() Se le pasa como parámetro el set de datos, el tamaño del test y la semilla aleatoria.

from sklearn.model_selection import train_test_split
train_set, test_set = train_test_split(datos, test_size=0.2, random_state=42)
test_set.head()

Si estamos encuestando gente por teléfono, es mala idea llamar a la gente de una página de la guía telefónica, pues seguramente viva todos en la misma ciudad o el mismo barrio, para ello interesa seguir un patrón más aleatorio que sea representativo de cada estrato social. Para ello existe una función llamada StratifiedShuffleSplit que nos permite obtener diferentes sets de datos de diferentes estratos de los datos.

from sklearn.model_selection import StratifiedShuffleSplit

split = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=42)
for train_index, test_index in split.split(datos, datos["FEB"]):
    strat_train_set = datos.loc[train_index]
    strat_test_set = datos.loc[test_index]

Para ver las diferentes proporciones de cada categoría en nuestro set de datos podemos hacer

strat_test_set["FEB"].value_counts() / len(strat_test_set)

Estas funciones no funcionarán con un set de datos pequeño, pues necesitan datos suficientes para ser operativas.

Aquí se puede ver otro ejemplo de conjunto de datos

No hay comentarios:

Publicar un comentario