Llevo unos días buscando un dataset para probar un algoritmo de clasificación. No encuentro ninguno que me convenza al 100%, así que he decidio construirme uno.
Ya hice algo parecido en mi post Cómo entrenar a tu perceptrón, utilizando para ello la función make_blobs, incluida en la librería de machine learning de Python scikit-learn.
La función make_blobs no es la única. El módulo datasets de scikit-learn, nos ofrece un montón de funciones que incluyen, además de cargar un dataset predeterminado, poder generar un dataset completamente nuevo.
Sin embargo, yo estaba buscando algo más…personalizado.
No veo por qué hay que ceñirse a ciertas librerías, siempre puedes encontrar tu propia solución si no te convence el resultado.
Así que me he hecho una funcioncita de forma rápida, que me permite crear un dataset con n características y una variable de respuesta que puede pertenecer a dos clases.
El código es el siguiente:
def genDataset(n_features = 4, n_samples = 1000, low = 0, high = 10, weights = [0.25, 0.25, 0.25, 0.25], threshold = 5): """ The function generates a random dataset with n predictor features and the result. The result can take two values, zero and one. The result depends on the threshold. :param n_features: Number of features. :param n_samples: Number of samples. :param low: The lowest value for the range of random values. :param high: The highest value for the range of random values. :param weight: List of the weights for each feature. There must be a weight for each feature. :param threshold: It is the value that marks the limit to assign zero or one to the result. :return: Dataframe """ import pandas as pd import numpy as np if len(weights) == n_features: randomData = np.random.randint(low = low, high = high , size=(n_samples, n_features)) weights_m = np.asarray([weights]*n_samples) p = np.array([1 if sum(row) >= threshold else 0 for row in randomData * weights_m]) res = pd.DataFrame(data=np.column_stack((randomData, p)), columns = ['feat_%s_%s' %(str(i), str(w)) for i, w in enumerate(weights)]+['result_thr_%s'%threshold]) if sum(weights) != 1.0: print ("Beware. The sum of the weights is different from 1.0: %f" %sum(weights)) return res else: print ("There must be a weight for each feature. Please, check the weights matrix.")
El corazón de genDataset es la función randint incluida en el módulo random de Numpy. Ésta función nos permite generar números aleatorios, a partir de una distribución uniforme de valores discretos, proporcionándole como argumentos el valor mínimo y el valor máximo de un intervalo. Además te permite crear arrays de varias dimensiones a través del argumento size.
Como argumentos, la función genDataset toma el número de variables explicativas que queremos generar (n_features), el número de muestras (n_samples) y el valor mínimo y el máximo anteriormente comentados.
Para crear la columna que etiquete con una clase a la muestra correspondiente, simplemente he añadido a la función otros dos argumento: weights y threshold.
Weights tendría el formato de una lista, con el peso correspondiente a cada variable explicativa. Y threshold, pues eso, es un límite. ¿Para qué sirven?. Para cada muestra se realiza la operación de multiplicar cada variable por su peso correspondiente, y se obtiene su suma. Si éste valor es mayor, o igual, que el threshold, la muestra se etiqueta como 1, y si no, como 0. Así obtenemos la columna para la variable etiqueta.
Vamos a probarla.
Voy a pedirle a la función que me genere un sample se 100000 muestras, entre el 0 y el 10, con 4 variables explicativas y unos pesos [0.125, 0.375, 0.375, 0.125], y un valor para el threshold de 6.
data = genDataset(n_features = 4, n_samples = 100000, low = 0, high = 10, weights = [0.125, 0.375, 0.375, 0.125], threshold = 6)
Podemos examinar un poco los datos.
data.head() feat_0_0.125 feat_1_0.375 feat_2_0.375 feat_3_0.125 result_thr_6 0 4 9 7 9 1 1 6 7 7 4 1 2 1 3 5 8 0 3 4 3 3 6 0 4 7 9 9 9 1
data.describe() feat_0_0.125 feat_1_0.375 feat_2_0.375 feat_3_0.125 \ count 100000.000000 100000.000000 100000.000000 100000.00000 mean 4.495400 4.492530 4.500230 4.48148 std 2.880813 2.870834 2.866284 2.86885 min 0.000000 0.000000 0.000000 0.00000 25% 2.000000 2.000000 2.000000 2.00000 50% 4.000000 5.000000 5.000000 4.00000 75% 7.000000 7.000000 7.000000 7.00000 max 9.000000 9.000000 9.000000 9.00000 result_thr_6 count 100000.000000 mean 0.197610 std 0.398198 min 0.000000 25% 0.000000 50% 0.000000 75% 0.000000 max 1.000000
data.groupby('result_thr_6').size() result_thr_6 0 80239 1 19761 dtype: int64
one_p = data.groupby('result_thr_6').size()[1]/data.groupby('result_thr_6').size()[0] * 100 one_p 24.627674821470855
sns.countplot(x='result_thr_6', data=data, palette = 'RdBu_r')
¡Ahora ya podemos utilizar estos datos para practicar con algún modelo de Machine Learning!.