{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Boosting en Machine Learning con Python" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*Esta notebook fue creada originalmente como un blog post por [Raúl E. López Briega](http://relopezbriega.com.ar/) en [Matemáticas, Analisis de datos y Python](http://relopezbriega.github.io). El contenido esta bajo la licencia BSD.*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> \"La opinión de toda una multitud es siempre más creíble que la de una minoría.\"\n", "\n", "**[Miguel de Unamuno](https://es.wikipedia.org/wiki/Miguel_de_Unamuno)**\n", "\n", "## Introducción\n", "\n", "La meta de construir sistemas que puedan adaptarse a sus entornos y aprender de su experiencia ha atraído a investigadores de muchos campos, como la [Informática](https://es.wikipedia.org/wiki/Inform%C3%A1tica),\n", "[Matemáticas](https://es.wikipedia.org/wiki/Matem%C3%A1ticas), [Física](https://es.wikipedia.org/wiki/F%C3%ADsica), [Neurociencia](https://es.wikipedia.org/wiki/Neurociencia) y la [Ciencia cognitiva](https://es.wikipedia.org/wiki/Ciencia_cognitiva). Intuitivamente, para que un *algoritmo de aprendizaje* sea efectivo y preciso en sus predicciones, debería reunir tres condiciones básicas: \n", "\n", "1. Debería ser entrenado con *suficientes* datos de entrenamiento.\n", "2. Sus resultados deberían *ajustarse* bastante bien a los ejemplos de entrenamiento (lo que significaría tener una tasa de error baja).\n", "3. Debería ser lo suficientemente \"simple\". Esta última condición, que las reglas más simples suelen ser las mejores, se conoce a menudo con el nombre de \"[La navaja de Occam](https://es.wikipedia.org/wiki/Navaja_de_Ockham)\".\n", "\n", "Muchos algoritmos se han creado y existen aún muchos por descubrir; pero unos de los que ha ganado mucha atracción en los últimos años por su simpleza y su gran éxito en competencias como [kraggle](https://www.kaggle.com/), son los algoritmos de [Boosting](https://es.wikipedia.org/wiki/Boosting). \n", "\n", "## ¿Qué es Boosting?\n", "\n", "[Boosting](https://es.wikipedia.org/wiki/Boosting) es un **enfoque de [Machine Learning](http://relopezbriega.github.io/category/machine-learning.html) basado en la idea de crear una regla de predicción altamente precisa combinando muchas reglas relativamente débiles e imprecisas**. Una teoría notablemente rica ha evolucionado en torno al [Boosting](https://es.wikipedia.org/wiki/Boosting), con conexiones a una amplia gama de ramas de la ciencia, incluyendo [estadísticas](http://relopezbriega.github.io/category/pobabilidad-y-estadistica.html), [teoría de juegos](https://es.wikipedia.org/wiki/Teor%C3%ADa_de_juegos), [optimización convexa](http://relopezbriega.github.io/blog/2017/01/18/problemas-de-optimizacion-con-python/) y [geometría de la información](https://es.wikipedia.org/wiki/Geometr%C3%ADa_de_la_informaci%C3%B3n). Los algoritmos de [Boosting](https://es.wikipedia.org/wiki/Boosting) han tenido éxito práctico con aplicaciones, por ejemplo, en [biología](https://es.wikipedia.org/wiki/Biolog%C3%ADa), [visión](https://es.wikipedia.org/wiki/Visi%C3%B3n_artificial) y [procesamiento del lenguaje natural](https://es.wikipedia.org/wiki/Procesamiento_de_lenguajes_naturales). En varios momentos de su historia, el [Boosting](https://es.wikipedia.org/wiki/Boosting) ha sido objeto de controversia por el misterio y la paradoja que parece presentar. El [Boosting](https://es.wikipedia.org/wiki/Boosting) asume la disponibilidad de un *algoritmo de aprendizaje base o débil* que, dado ejemplos de entrenamiento etiquetados, produce un *clasificador base o débil*. El objetivo de [Boosting](https://es.wikipedia.org/wiki/Boosting) es el de mejorar el rendimiento del *algoritmo de aprendizaje* al tratarlo como una \"caja negra\" que se puede llamar repetidamente, como una subrutina. Si bien el *algoritmo de aprendizaje base* puede ser rudimentario y moderadamente inexacto, no es del todo trivial ni poco informativo y debe obtener resultados mejores a los que se podrían obtener en forma aleatoria. La idea fundamental detrás de [Boosting](https://es.wikipedia.org/wiki/Boosting) es elegir *conjuntos de entrenamiento* para el *algoritmo de aprendizaje base* de tal manera que lo obligue a *inferir* algo nuevo sobre los datos cada vez que se lo llame. Uno de los primeros algoritmos de [Boosting](https://es.wikipedia.org/wiki/Boosting) en tener éxito en problemas de clasificación binaria fue [AdaBoost](https://en.wikipedia.org/wiki/AdaBoost).\n", "\n", "## AdaBoost\n", "\n", "[AdaBoost](https://en.wikipedia.org/wiki/AdaBoost) es la abreviatura de *adaptive boosting*, es un algoritmo que puede ser utilizado junto con otros *algoritmos de aprendizaje* para mejorar su rendimiento. \n", "[AdaBoost](https://en.wikipedia.org/wiki/AdaBoost) funciona eligiendo un *algoritmo base* (por ejemplo [árboles de decisión](https://es.wikipedia.org/wiki/%C3%81rbol_de_decisi%C3%B3n)) y mejorándolo iterativamente al tomar en cuenta los casos incorrectamente clasificados en el conjunto de entrenamiento. \n", "\n", "En [AdaBoost](https://en.wikipedia.org/wiki/AdaBoost) asignamos *pesos* iguales a todos los ejemplos de entrenamiento y elegimos un *algoritmo base*. En cada paso de iteración, aplicamos el *algoritmo base* al conjunto de entrenamiento y aumentamos los pesos de los ejemplos incorrectamente clasificados. Iteramos n veces, cada vez aplicando el *algoritmo base* en el conjunto de entrenamiento con *pesos* actualizados. El modelo final es la suma ponderada de los resultados de los n *algoritmos base*.\n", "[AdaBoost](https://en.wikipedia.org/wiki/AdaBoost) en conjunto con [árboles de decisión](https://es.wikipedia.org/wiki/%C3%81rbol_de_decisi%C3%B3n) se ha mostrado sumamente efectivo en varios problemas de [Machine Learning](http://relopezbriega.github.io/category/machine-learning.html). Veamos un ejemplo en [Python](https://www.python.org/)." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# \n", "# Importando las librerías que vamos a utilizar\n", "import pandas as pd\n", "import numpy as np \n", "import matplotlib.pyplot as plt \n", "import seaborn as sns \n", "from sklearn.model_selection import train_test_split\n", "from sklearn.ensemble import GradientBoostingClassifier\n", "from sklearn.ensemble import AdaBoostClassifier\n", "from sklearn.metrics import accuracy_score\n", "from sklearn.tree import DecisionTreeClassifier\n", "from sklearn.tree import export_graphviz\n", "from sklearn.datasets import load_breast_cancer\n", "from sklearn.preprocessing import LabelEncoder\n", "from sklearn.preprocessing import OneHotEncoder\n", "import graphviz\n", "import xgboost as xgb\n", "\n", "# graficos incrustados\n", "%matplotlib inline\n", "\n", "# parametros esteticos de seaborn\n", "sns.set_palette(\"deep\", desat=.6)\n", "sns.set_context(rc={\"figure.figsize\": (8, 4)})" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " | mean radius | \n", "mean texture | \n", "mean perimeter | \n", "mean area | \n", "mean smoothness | \n", "mean compactness | \n", "mean concavity | \n", "mean concave points | \n", "mean symmetry | \n", "mean fractal dimension | \n", "... | \n", "worst radius | \n", "worst texture | \n", "worst perimeter | \n", "worst area | \n", "worst smoothness | \n", "worst compactness | \n", "worst concavity | \n", "worst concave points | \n", "worst symmetry | \n", "worst fractal dimension | \n", "
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | \n", "17.99 | \n", "10.38 | \n", "122.80 | \n", "1001.0 | \n", "0.11840 | \n", "0.27760 | \n", "0.3001 | \n", "0.14710 | \n", "0.2419 | \n", "0.07871 | \n", "... | \n", "25.38 | \n", "17.33 | \n", "184.60 | \n", "2019.0 | \n", "0.1622 | \n", "0.6656 | \n", "0.7119 | \n", "0.2654 | \n", "0.4601 | \n", "0.11890 | \n", "
1 | \n", "20.57 | \n", "17.77 | \n", "132.90 | \n", "1326.0 | \n", "0.08474 | \n", "0.07864 | \n", "0.0869 | \n", "0.07017 | \n", "0.1812 | \n", "0.05667 | \n", "... | \n", "24.99 | \n", "23.41 | \n", "158.80 | \n", "1956.0 | \n", "0.1238 | \n", "0.1866 | \n", "0.2416 | \n", "0.1860 | \n", "0.2750 | \n", "0.08902 | \n", "
2 | \n", "19.69 | \n", "21.25 | \n", "130.00 | \n", "1203.0 | \n", "0.10960 | \n", "0.15990 | \n", "0.1974 | \n", "0.12790 | \n", "0.2069 | \n", "0.05999 | \n", "... | \n", "23.57 | \n", "25.53 | \n", "152.50 | \n", "1709.0 | \n", "0.1444 | \n", "0.4245 | \n", "0.4504 | \n", "0.2430 | \n", "0.3613 | \n", "0.08758 | \n", "
3 | \n", "11.42 | \n", "20.38 | \n", "77.58 | \n", "386.1 | \n", "0.14250 | \n", "0.28390 | \n", "0.2414 | \n", "0.10520 | \n", "0.2597 | \n", "0.09744 | \n", "... | \n", "14.91 | \n", "26.50 | \n", "98.87 | \n", "567.7 | \n", "0.2098 | \n", "0.8663 | \n", "0.6869 | \n", "0.2575 | \n", "0.6638 | \n", "0.17300 | \n", "
4 | \n", "20.29 | \n", "14.34 | \n", "135.10 | \n", "1297.0 | \n", "0.10030 | \n", "0.13280 | \n", "0.1980 | \n", "0.10430 | \n", "0.1809 | \n", "0.05883 | \n", "... | \n", "22.54 | \n", "16.67 | \n", "152.20 | \n", "1575.0 | \n", "0.1374 | \n", "0.2050 | \n", "0.4000 | \n", "0.1625 | \n", "0.2364 | \n", "0.07678 | \n", "
5 rows × 30 columns
\n", "\n", " | Unnamed: 0 | \n", "age | \n", "menopause | \n", "tumor-size | \n", "inv-nodes | \n", "node-caps | \n", "deg-malig | \n", "breast | \n", "breast-quad | \n", "irradiat | \n", "Class | \n", "
---|---|---|---|---|---|---|---|---|---|---|---|
0 | \n", "0 | \n", "'40-49' | \n", "'premeno' | \n", "'15-19' | \n", "'0-2' | \n", "'yes' | \n", "'3' | \n", "'right' | \n", "'left_up' | \n", "'no' | \n", "'recurrence-events' | \n", "
1 | \n", "1 | \n", "'50-59' | \n", "'ge40' | \n", "'15-19' | \n", "'0-2' | \n", "'no' | \n", "'1' | \n", "'right' | \n", "'central' | \n", "'no' | \n", "'no-recurrence-events' | \n", "
2 | \n", "2 | \n", "'50-59' | \n", "'ge40' | \n", "'35-39' | \n", "'0-2' | \n", "'no' | \n", "'2' | \n", "'left' | \n", "'left_low' | \n", "'no' | \n", "'recurrence-events' | \n", "
3 | \n", "3 | \n", "'40-49' | \n", "'premeno' | \n", "'35-39' | \n", "'0-2' | \n", "'yes' | \n", "'3' | \n", "'right' | \n", "'left_low' | \n", "'yes' | \n", "'no-recurrence-events' | \n", "
4 | \n", "4 | \n", "'40-49' | \n", "'premeno' | \n", "'30-34' | \n", "'3-5' | \n", "'yes' | \n", "'2' | \n", "'left' | \n", "'right_up' | \n", "'no' | \n", "'recurrence-events' | \n", "