El aprendizaje automático trata de ajustar modelos a los datos; por esta razón, empezaremos discutiendo como los datos pueden ser representados para ser accesibles por el ordenador. Además de esto, nos basaremos en los ejemplos de matplotlib de la sección anterior para usarlos para representar datos.
Los datos en scikit-learn, salvo algunas excepciones, suelen estar almacenados en
arrays de 2 dimensiones, con forma [n_samples, n_features]
. Muchos algoritmos aceptan también matrices scipy.sparse
con la misma forma.
El número de características debe ser fijado de antemano. Sin embargo, puede ser extremadamente alto (por ejemplo, millones de características), siendo cero en la mayoría de casos. En este tipo de datos, es buena idea usar matrices scipy.sparse
que manejan mucho mejor la memoria.
Como ya comentamos en la sección anterior, representamos los ejemplos (puntos o instancias) como filas en el array de datos y almacenamos las características correspondientes, las "dimensiones", como columnas.
Como ejemplo de un dataset simple, vamos a echar un vistazo al conjunto iris almacenado en scikit-learn. Los datos consisten en medidas de tres especies de flores iris distintas:
Iris Setosa
Iris Versicolor
Iris Virginica
Asumamos que estamos interesados en categorizar nuevos ejemplos; queremos predecir si una flor nueva va a ser Iris-Setosa, Iris-Versicolor, o Iris-Virginica. Basándonos en lo discutido en secciones anteriores, ¿cómo construiríamos este dataset?
Recuerda: necesitamos un array 2D con forma (shape) [n_samples x n_features]
.
n_samples
?n_features
?
Recuerda que debe haber un número fijo de características por cada ejemplo, y cada característica j debe ser el mismo tipo de cantidad para cada ejemplo.Para futuros experimentos con algoritmos de aprendizaje automático, te recomendamos que añadas a favoritos el Repositorio UCI, que aloja muchos de los datasets que se utilizan para probar los algoritmos de aprendizaje automático. Además, algunos de estos datasets ya están incluidos en scikit-learn, pudiendo así evitar tener que descargar, leer, convertir y limpiar los ficheros de texto o CSV. El listado de datasets ya disponibles en scikit learn puede consultarse aquí.
Por ejemplo, scikit-learn contiene el dataset iris. Los datos consisten en:
(Image: "Petal-sepal". Licensed under CC BY-SA 3.0 via Wikimedia Commons - https://commons.wikimedia.org/wiki/File:Petal-sepal.jpg#/media/File:Petal-sepal.jpg)
scikit-learn
incluye una copia del archivo CSV de iris junto con una función que lo lee a arrays de numpy:
In [ ]:
from sklearn.datasets import load_iris
iris = load_iris()
El dataset es un objeto Bunch
. Puedes ver que contiene utilizando el método keys()
:
In [ ]:
iris.keys()
Las características de cada flor se encuentra en el atributo data
del dataset:
In [ ]:
n_samples, n_features = iris.data.shape
print('Número de ejemplos:', n_samples)
print('Número de características:', n_features)
# sepal length, sepal width, petal length y petal width del primer ejemplo (primera flor)
print(iris.data[0])
La información sobre la clase de cada ejemplo se encuentra en el atributo target
del dataset:
In [ ]:
print(iris.data.shape)
print(iris.target.shape)
In [ ]:
print(iris.target)
In [ ]:
import numpy as np
np.bincount(iris.target)
La función de numpy llamada bincount
(arriba) nos permite ver que las clases se distribuyen de forma uniforme en este conjunto de datos (50 flores de cada especie), donde:
Los nombres de las clases se almacenan en target_names
:
In [ ]:
print(iris.target_names)
Estos datos tienen cuatro dimensiones, pero podemos visualizar una o dos de las dimensiones usando un histograma o un scatter. Primero, activamos el matplotlib inline mode:
In [ ]:
%matplotlib inline
import matplotlib.pyplot as plt
In [ ]:
x_index = 3
colors = ['blue', 'red', 'green']
for label, color in zip(range(len(iris.target_names)), colors):
plt.hist(iris.data[iris.target==label, x_index],
label=iris.target_names[label],
color=color)
plt.xlabel(iris.feature_names[x_index])
plt.legend(loc='upper right')
plt.show()
In [ ]:
x_index = 3
y_index = 0
colors = ['blue', 'red', 'green']
for label, color in zip(range(len(iris.target_names)), colors):
plt.scatter(iris.data[iris.target==label, x_index],
iris.data[iris.target==label, y_index],
label=iris.target_names[label],
c=color)
plt.xlabel(iris.feature_names[x_index])
plt.ylabel(iris.feature_names[y_index])
plt.legend(loc='upper left')
plt.show()
En lugar de realizar los plots por separado, una herramienta común que utilizan los analistas son las matrices scatterplot.
Estas matrices muestran los scatter plots entre todas las características del dataset, así como los histogramas para ver la distribución de cada característica.
In [ ]:
import pandas as pd
iris_df = pd.DataFrame(iris.data, columns=iris.feature_names)
pd.plotting.scatter_matrix(iris_df, c=iris.target, figsize=(8, 8));
Scikit-learn pone a disposición de la comunidad una gran cantidad de datasets. Vienen en tres modos:
sklearn.datasets.load_*
sklearn.datasets.fetch_*
sklearn.datasets.make_*
Puedes explorar las herramientas de datasets de scikit-learn usando la funcionalidad de autocompletado que tiene IPython. Tras importar el paquete datasets
de sklearn
, teclea
datasets.load_<TAB>
o
datasets.fetch_<TAB>
o
datasets.make_<TAB>
para ver una lista de las funciones disponibles
In [ ]:
from sklearn import datasets
Advertencia: muchos de estos datasets son bastante grandes y puede llevar bastante tiempo descargarlos.
Si comienzas una descarga con un libro de IPython y luego quieres detenerla, puedes utilizar la opción "kernel interrupt" accesible por el menú o con Ctrl-m i
.
Puedes presionar Ctrl-m h
para una lista de todos los atajos ipython
.
Ahora vamos a ver otro dataset, donde podemos estudiar mejor como representar los datos. Podemos explorar los datos de la siguiente forma:
In [ ]:
from sklearn.datasets import load_digits
digits = load_digits()
In [ ]:
digits.keys()
In [ ]:
n_samples, n_features = digits.data.shape
print((n_samples, n_features))
In [ ]:
print(digits.data[0])
print(digits.data[-1])
print(digits.target)
Aquí la etiqueta es directamente el dígito que representa cada ejemplo. Los datos consisten en un array de longitud 64... pero, ¿qué significan estos datos?
Una pista viene dada por el hecho de que tenemos dos versiones de los datos:
data
y images
. Vamos a echar un vistazo a ambas:
In [ ]:
print(digits.data.shape)
print(digits.images.shape)
Podemos ver que son lo mismo, mediante un simple reshaping:
In [ ]:
import numpy as np
print(np.all(digits.images.reshape((1797, 64)) == digits.data))
Vamos a visualizar los datos. Es un poco más complejo que el scatter plot que hicimos anteriormente.
In [ ]:
# Configurar la figura
fig = plt.figure(figsize=(6, 6)) # tamaño en pulgadas
fig.subplots_adjust(left=0, right=1, bottom=0, top=1, hspace=0.05, wspace=0.05)
# mostrar algunos dígitos: cada imagen es de 8x8
for i in range(64):
ax = fig.add_subplot(8, 8, i + 1, xticks=[], yticks=[])
ax.imshow(digits.images[i], cmap=plt.cm.binary, interpolation='nearest')
# Etiquetar la imagen con el valor objetivo
ax.text(0, 7, str(digits.target[i]))
Ahora podemos saber que significan las características. Cada característica es una cantidad real que representa la oscuridad de un píxel en una imagen 8x8 de un dígito manuscrito.
Aunque cada ejemplo tiene datos que son inherentemente de dos dimensiones, la matriz de datos incluye estos datos 2D en un solo vector, contenido en cada fila de la misma.
In [ ]:
from sklearn.datasets import fetch_olivetti_faces
In [ ]:
# descarga el dataset faces
In [ ]:
# Utiliza el script anterior para representar las caras
# Pista: plt.cm.bone es un buen colormap para este dataset