<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Entrenamiento y test
Para evaluar que tal generalizan nuestros modelos supervisados, podemos dividir los datos en un conjunto de entrenamiento y otro de test
Step1:  Si pensamos la forma en que normalmente se aplica el aprendizaje automático, la idea de una partición de entrenamiento y test tiene sentido. Los sistemas del mundo real se entrenan utilizando los datos de los que se dispone y, conforme otros datos llegan (de nuevos clientes, de otros sensores o de otras fuentes), el modelo que fue previamente entrenado debe predecir nuevos datos. Podemos simular esto durante el aprendizaje mediante una partición train/test -- los datos de test serán una simulación de "datos futuros" que vendrán al sistema en la etapa de producción.
Específicamente para iris, las 150 etiquetas están ordenadas, lo que significa que si dividimos los datos de forma directa y proporcional, alteraremos la distribución de las clases. Por ejemplo, si realizaremos una partición bastante común consistente en 2/3 para entrenamiento y 1/3 para test, nuestros datos de entrenamiento solo tendrían flores de las clases 0 y 1 (Setosa and Versicolor), y nuestros datos de test solo tendrían flores de la clase 2 (Virginica).
Bajo la suposición de que todos los ejemplos son independientes entre si (que no puede hacerse con datos de series temporales), sería necesario barajar aleatoriamente el dataset antes de dividirlo.
Ahora tenemos que hacer la partición. Afortunadamente, esto es bastante común en aprendizaje automático y scikit-learn tiene una función ya implementada para dividir en entrenamiento y test. Vamos a utilizar el 50% de los datos para entrenamiento y el 50% restante para test. Un 80% y un 20% es otra opción bastante común, aunque realmente depende mucho de los problemas tratados. Lo más importante para realizar una evaluación justa es que la evaluación se haga utilizando datos que no han sido utilizados para el entrenamiento.
Step2:  Consejo
Step3:  Para conseguir realizar una partición estratificada, tenemos que incluir el array de etiquetas cuando invocamos a la función train_test_split
Step4:  Si evaluamos el rendimiento de nuestro clasificador con datos que se han empleado para el entrenamiento, podríamos llegar a unos resultados demasiado optimistas. En el peor caso, el modelo puede simplemente memorizar los datos de entrenamiento, pero fallar estrepitosamente cuando tenga que clasificar nuevos datos similares - nunca querríamos tener un sistema así en producción.
En lugar de usar el mismo dataset para entrenamiento y test (lo que se conoce como "evaluación por resubstitución"), es mucho mejor usar una partición de entrenamiento y test para así estimar como de bien se comporta el modelo entrenado con datos nuevos.
Step5:  Podemos visualizar los aciertos y los fallos
<ASSISTANT_TASK:>
Python Code:
from sklearn.datasets import load_iris
from sklearn.neighbors import KNeighborsClassifier
iris = load_iris()
X, y = iris.data, iris.target
classifier = KNeighborsClassifier()
Explanation: Entrenamiento y test
Para evaluar que tal generalizan nuestros modelos supervisados, podemos dividir los datos en un conjunto de entrenamiento y otro de test:
<img src="figures/train_test_split_matrix.svg" width="100%">
End of explanation
y
from sklearn.model_selection import train_test_split
train_X, test_X, train_y, test_y = train_test_split(X, y, 
                                                    train_size=0.5,
                                                    test_size=0.5,
                                                    random_state=123)
print("Etiquetas para los datos de entrenamiento y test")
print(train_y)
print(test_y)
Explanation: Si pensamos la forma en que normalmente se aplica el aprendizaje automático, la idea de una partición de entrenamiento y test tiene sentido. Los sistemas del mundo real se entrenan utilizando los datos de los que se dispone y, conforme otros datos llegan (de nuevos clientes, de otros sensores o de otras fuentes), el modelo que fue previamente entrenado debe predecir nuevos datos. Podemos simular esto durante el aprendizaje mediante una partición train/test -- los datos de test serán una simulación de "datos futuros" que vendrán al sistema en la etapa de producción.
Específicamente para iris, las 150 etiquetas están ordenadas, lo que significa que si dividimos los datos de forma directa y proporcional, alteraremos la distribución de las clases. Por ejemplo, si realizaremos una partición bastante común consistente en 2/3 para entrenamiento y 1/3 para test, nuestros datos de entrenamiento solo tendrían flores de las clases 0 y 1 (Setosa and Versicolor), y nuestros datos de test solo tendrían flores de la clase 2 (Virginica).
Bajo la suposición de que todos los ejemplos son independientes entre si (que no puede hacerse con datos de series temporales), sería necesario barajar aleatoriamente el dataset antes de dividirlo.
Ahora tenemos que hacer la partición. Afortunadamente, esto es bastante común en aprendizaje automático y scikit-learn tiene una función ya implementada para dividir en entrenamiento y test. Vamos a utilizar el 50% de los datos para entrenamiento y el 50% restante para test. Un 80% y un 20% es otra opción bastante común, aunque realmente depende mucho de los problemas tratados. Lo más importante para realizar una evaluación justa es que la evaluación se haga utilizando datos que no han sido utilizados para el entrenamiento.
End of explanation
print('Todos:', np.bincount(y) / float(len(y)) * 100.0)
print('Entrenamiento:', np.bincount(train_y) / float(len(train_y)) * 100.0)
print('Test:', np.bincount(test_y) / float(len(test_y)) * 100.0)
Explanation: Consejo: partición estratificada
Especialmente cuando tratamos conjuntos de datos relativamente pequeños, es mejor estratificar la partición. La estratificación significa que mantenemos la proporción de datos por clase que había originalmente en los subconjuntos generados. Por ejemplo, después de dividir aleatoriamente el dataset como hicimos en el ejemplo anterior, podemos comprobar que tenemos las siguientes proporciones por clase:
End of explanation
train_X, test_X, train_y, test_y = train_test_split(X, y, 
                                                    train_size=0.5,
                                                    test_size=0.5,
                                                    random_state=123,
                                                    stratify=y)
print('Todos:', np.bincount(y) / float(len(y)) * 100.0)
print('Entrenamiento:', np.bincount(train_y) / float(len(train_y)) * 100.0)
print('Test:', np.bincount(test_y) / float(len(test_y)) * 100.0)
Explanation: Para conseguir realizar una partición estratificada, tenemos que incluir el array de etiquetas cuando invocamos a la función train_test_split:
End of explanation
classifier.fit(train_X, train_y)
pred_y = classifier.predict(test_X)
print("CCR [Accuracy]:")
print(np.mean(pred_y == test_y))
Explanation: Si evaluamos el rendimiento de nuestro clasificador con datos que se han empleado para el entrenamiento, podríamos llegar a unos resultados demasiado optimistas. En el peor caso, el modelo puede simplemente memorizar los datos de entrenamiento, pero fallar estrepitosamente cuando tenga que clasificar nuevos datos similares - nunca querríamos tener un sistema así en producción.
En lugar de usar el mismo dataset para entrenamiento y test (lo que se conoce como "evaluación por resubstitución"), es mucho mejor usar una partición de entrenamiento y test para así estimar como de bien se comporta el modelo entrenado con datos nuevos.
End of explanation
print('Ejemplos correctamente clasificados:')
correct_idx = np.where(pred_y == test_y)[0]
print(correct_idx)
print('\nEjemplos incorrectamente clasificados:')
incorrect_idx = np.where(pred_y != test_y)[0]
print(incorrect_idx)
# Representar en 2D
colors = ["darkblue", "darkgreen", "gray"]
for n, color in enumerate(colors):
    idx = np.where(test_y == n)[0]
    plt.scatter(test_X[idx, 1], test_X[idx, 2], color=color, label="Clase %s" % str(n))
plt.scatter(test_X[incorrect_idx, 1], test_X[incorrect_idx, 2], color="darkred")
plt.xlabel('sepal width [cm]')
plt.ylabel('petal length [cm]')
plt.legend(loc=3)
plt.title("Resultados de clasificación en iris con KNN")
plt.show()
Explanation: Podemos visualizar los aciertos y los fallos:
End of explanation
<END_TASK>