Introducción
Mi anterior postes Miró el árbol de decisión estándar y la maravilla de un bosque aleatorio. Ahora, para completar el triplete, ¡exploraré visualmente!
Hay un montón de bibliotecas de árboles impulsadas por el gradiente, que incluyen xgboost, catboost y lightgbm. Sin embargo, para esto voy a usar Sklearn’s One. ¿Por qué? Simplemente porque, en comparación con los demás, me permitió visualizar más fácilmente. En la práctica, tiendo a usar las otras bibliotecas más que la de Sklearn One; Sin embargo, este proyecto trata sobre el aprendizaje visual, no el rendimiento puro.
Fundamentalmente, un GBT es una combinación de árboles que Solo trabajan juntos. Mientras que un solo árbol de decisión (incluido uno extraído de un bosque aleatorio) puede hacer una predicción decente por sí misma, es poco probable que tome un árbol individual de un GBT que le dé algo utilizable.
Más allá de esto, como siempre, sin teoría, sin matemáticas, solo tramas e hiperparametros. Como antes, usaré el conjunto de datos de viviendas de California a través de Scikit-Learn (CC-by), el mismo proceso general que se describe en mis publicaciones anteriores, el código está en https://github.com/jamesdeluk/data-projects/tree/main/visualising-treesy todas las imágenes a continuación son creadas por mí (aparte del gif, que es de Tenor).
Un árbol de gradiente básico impulsado
Comenzando con un GBT básico: gb = GradientBoostingRegressor(random_state=42). Similar a otros tipos de árboles, la configuración predeterminada para min_samples_split, min_samples_leaf, max_leaf_nodes son 2, 1, None respectivamente. Curiosamente, el incumplimiento max_depth es 3, no None como está con los árboles de decisión/bosques aleatorios. Hiperparámetros notables, que analizaré más tarde, incluiré learning_rate (Qué tan empinado es el gradiente, predeterminado 0.1), y n_estimators (Similar al bosque aleatorio: el número de árboles).
El ajuste tomó 2.2s, predecir tomó 0.005s y los resultados:
| Métrico | max_depth = ninguno |
|---|---|
| Mae | 0.369 |
| Mape | 0.216 |
| MSE | 0.289 |
| RMSE | 0.538 |
| R² | 0.779 |
Entonces, más rápido que el bosque aleatorio predeterminado, pero un rendimiento ligeramente peor. Para mi bloque elegido, predijo 0.803 (0.894 real).
Visualizante
Por eso estás aquí, ¿verdad?
El árbol
Similar a antes, podemos trazar un solo árbol. Este es el primero, accedido con gb.estimators_[0, 0]:
Los he explicado en las publicaciones anteriores, así que no lo volveré a hacer aquí. Sin embargo, una cosa que le llamaré: ¡observe cuán terribles son los valores! Tres de las hojas incluso tienen valores negativos, que sabemos que no puede ser el caso. Esta es la razón por la cual un GBT solo funciona como un conjunto combinado, no como árboles independientes como en un bosque aleatorio.
Predicciones y errores
Mi forma favorita de visualizar GBTS es con las gráficas de predicción frente a la iteración, usando gb.staged_predict. Para mi bloque elegido:
¿Recuerdas que el modelo predeterminado tiene 100 estimadores? Bueno, aquí están. La predicción inicial estaba muy lejos: ¡2! Pero cada vez que aprendía (recuerda learning_rate?), y se acercó al valor real. Por supuesto, se capacitó en los datos de capacitación, no en estos datos específicos, por lo que el valor final estaba apagado (0.803, por lo que aproximadamente un 10% de descuento), pero puede ver claramente el proceso.
En este caso, alcanzó un estado bastante estable después de aproximadamente 50 iteraciones. Más tarde veremos cómo dejar de iterar en esta etapa, para evitar perder tiempo y dinero.
Del mismo modo, el error (es decir, la predicción menos el valor verdadero) se puede trazar. Por supuesto, esto nos da la misma trama, simplemente con diferentes valores del eje Y:
¡Llegemos esto un paso más allá! Los datos de prueba tienen más de 5000 bloques para predecir; ¡Podemos recorrer cada uno y predecirlos a todos, para cada iteración!
Amo esta trama.
Todos comienzan alrededor de 2, pero explotan a través de las iteraciones. Sabemos que todos los valores verdaderos varían de 0.15 a 5, con una media de 2.1 (verifique mi primera publicación), por lo que esta propagación de predicciones (de ~ 0.3 a ~ 5.5) es como se esperaba.
También podemos trazar los errores:
A primera vista, parece un poco extraño: esperaríamos que comiencen, digamos, ± 2, y convergen en 0. Sin embargo, mirando cuidadosamente, esto sucede para la mayoría, se puede ver en el lado izquierdo de la trama, las primeras 10 iteraciones más o menos. El problema es que, con más de 5000 líneas en esta trama, hay muchos superpuestos, lo que hace que los valores atípicos se destaquen más. ¿Quizás hay una mejor manera de visualizarlos? ¿Qué tal …
El error mediano es 0.05, ¡lo cual es muy bueno! El IQR es inferior a 0.5, lo cual también es decente. Entonces, si bien hay algunas predicciones terribles, la mayoría son decentes.
Ajuste de hiperparameter
Hiperparámetros del árbol de decisión
Igual que antes, comparemos cómo se exploran los hiperparámetros en la publicación del árbol de decisión original se aplican a GBTS, con los hiperparámetros predeterminados de learning_rate = 0.1, n_estimators = 100. El min_samples_leaf, min_samples_splity max_leaf_nodes uno también tiene max_depth = 10para que sea una comparación justa con publicaciones anteriores y entre sí.
| Modelo | max_depth = ninguno | max_depth = 10 | min_samples_leaf = 10 | min_samples_split = 10 | max_leaf_nodes = 100 |
|---|---|---|---|---|---|
| Tiempo (s) de ajuste | 10.889 | 7.009 | 7.101 | 7.015 | 6.167 |
| Predecir el tiempo (s) | 0.089 | 0.019 | 0.015 | 0.018 | 0.013 |
| Mae | 0.454 | 0.304 | 0.301 | 0.302 | 0.301 |
| Mape | 0.253 | 0.177 | 0.174 | 0.174 | 0.175 |
| MSE | 0.496 | 0.222 | 0.212 | 0.217 | 0.210 |
| RMSE | 0.704 | 0.471 | 0.46 | 0.466 | 0.458 |
| R² | 0.621 | 0.830 | 0.838 | 0.834 | 0.840 |
| Predicción elegida | 0.885 | 0.906 | 0.962 | 0.918 | 0.923 |
| Error elegido | 0.009 | 0.012 | 0.068 | 0.024 | 0.029 |
A diferencia de los árboles de decisión y los bosques aleatorios, ¡el árbol más profundo funcionó mucho peor! Y tardó más en encajar. Sin embargo, aumentar la profundidad de 3 (el valor predeterminado) a 10 ha mejorado los puntajes. Las otras restricciones dieron como resultado mejoras adicionales, nuevamente mostrando cómo todos los hiperparámetros pueden desempeñar un papel.
aprendizaje_rate
Los GBT operan ajustando las predicciones después de cada iteración en función del error. Cuanto mayor sea el ajuste (también conocido como el gradiente, también conocido como la tasa de aprendizaje), más cambia la predicción entre iteraciones.
Hay una clara compensación por la tasa de aprendizaje. Comparación de tasas de aprendizaje de 0.01 (lento), 0.1 (incumplimiento) y 0.5 (rápido), más de 100 iteraciones:
Las tasas de aprendizaje más rápidas pueden llegar al valor correcto más rápido, pero es más probable que corrigan en exceso y salte del verdadero valor (piense en cola de pez en un automóvil) y puede conducir a oscilaciones. Las tasas de aprendizaje lentas pueden nunca alcanzar el valor correcto (piense … no girar el volante lo suficiente y conducir directamente a un árbol). En cuanto a las estadísticas:
| Modelo | Por defecto | Rápido | Lento |
|---|---|---|---|
| Tiempo (s) de ajuste | 2.159 | 2.288 | 2.166 |
| Predecir el tiempo (s) | 0.005 | 0.004 | 0.015 |
| Mae | 0.370 | 0.338 | 0.629 |
| Mape | 0.216 | 0.197 | 0.427 |
| MSE | 0.289 | 0.247 | 0.661 |
| RMSE | 0.538 | 0.497 | 0.813 |
| R² | 0.779 | 0.811 | 0.495 |
| Predicción elegida | 0.803 | 0.949 | 1.44 |
| Error elegido | 0.091 | 0.055 | 0.546 |
Como era de esperar, el modelo de aprendizaje lento fue terrible. Para este bloque, Fast fue ligeramente mejor que el valor predeterminado en general. Sin embargo, podemos ver en la trama cómo, al menos para el bloque elegido, fueron las últimas 90 iteraciones las que hicieron que el modelo rápido fuera más preciso que el predeterminado, si hubiéramos detenido en 40 iteraciones, al menos para el bloque elegido, el modelo predeterminado habría sido mucho mejor. ¡Las alegrías de la visualización!
n_estimadores
Como se mencionó anteriormente, el número de estimadores va de la mano con la tasa de aprendizaje. En generalcuantos más estimadores, mejor, ya que da más iteraciones para medir y ajustar el error, aunque esto tiene un costo de tiempo adicional.
Como se vio anteriormente, un número suficientemente alto de estimadores es especialmente importante para una baja tasa de aprendizaje, para garantizar que se alcance el valor correcto. Aumentando el número de estimadores a 500:
Con suficientes iteraciones, el GBT de aprendizaje lento alcanzó el verdadero valor. De hecho, todos terminaron mucho más cerca. Las estadísticas confirman esto:
| Modelo | Fausilmore | Fastmore | Slowmore |
|---|---|---|---|
| Tiempo (s) de ajuste | 12.254 | 12.489 | 11.918 |
| Predecir el tiempo (s) | 0.018 | 0.014 | 0.022 |
| Mae | 0.323 | 0.319 | 0.410 |
| Mape | 0.187 | 0.185 | 0.248 |
| MSE | 0.232 | 0.228 | 0.338 |
| RMSE | 0.482 | 0.477 | 0.581 |
| R² | 0.823 | 0.826 | 0.742 |
| Predicción elegida | 0.841 | 0.921 | 0.858 |
| Error elegido | 0.053 | 0.027 | 0.036 |
Como era de esperar, aumentar el número de estimadores de cinco veces aumentó el tiempo para adaptarse significativamente (en este caso en seis veces, pero eso puede ser solo). Sin embargo, todavía no hemos superado los puntajes de los árboles restringidos anteriores. Creo que tendremos que hacer una búsqueda de hiperparameter para ver si podemos vencerlos. Además, para el bloque elegido, como se puede ver en la trama, después de aproximadamente 300 iteraciones, ninguno de los modelos realmente mejoró. Si esto es consistente en todos los datos, entonces las 700 iteraciones adicionales eran innecesarias. Mencioné anteriormente sobre cómo es posible evitar perder el tiempo iterando sin mejorar; Ahora es el momento de investigar eso.
n_iter_no_change, validation_fraction y tol
Es posible que las iteraciones adicionales no mejoren el resultado final, pero aún lleva tiempo ejecutarlas. Aquí es donde entra en la parada temprana.
Hay tres hiperparámetros relevantes. La primera, n_iter_no_changees cuántas iteraciones para “no hay cambio” antes de no hacer más iteraciones. tol[erance] es qué tan grande debe ser el cambio en la puntuación de validación para clasificarse como “sin cambio”. Y validation_fraction es cuánto de los datos de entrenamiento se utilizarán como un conjunto de validación para generar la puntuación de validación (tenga en cuenta que esto es separado de los datos de prueba).
Comparación de un GBT de 1000 alestimadores con uno con una parada temprana bastante agresiva- n_iter_no_change=5, validation_fraction=0.1, tol=0.005 – El último se detuvo después de solo 61 estimadores (y, por lo tanto, solo tomó el 5 ~ 6% del tiempo en encajar):
Sin embargo, como se esperaba, los resultados fueron peores:
| Modelo | Por defecto | Parada temprana |
|---|---|---|
| Tiempo (s) de ajuste | 24.843 | 1.304 |
| Predecir el tiempo (s) | 0.042 | 0.003 |
| Mae | 0.313 | 0.396 |
| Mape | 0.181 | 0.236 |
| MSE | 0.222 | 0.321 |
| RMSE | 0.471 | 0.566 |
| R² | 0.830 | 0.755 |
| Predicción elegida | 0.837 | 0.805 |
| Error elegido | 0.057 | 0.089 |
Pero como siempre, la pregunta que debe hacer: ¿vale la pena invertir 20 veces el tiempo para mejorar el R² en un 10%, o reducir el error en un 20%?
Bayes Búsqueda
Probablemente esperabas esto. Los espacios de búsqueda:
search_spaces = {
'learning_rate': (0.01, 0.5),
'max_depth': (1, 100),
'max_features': (0.1, 1.0, 'uniform'),
'max_leaf_nodes': (2, 20000),
'min_samples_leaf': (1, 100),
'min_samples_split': (2, 100),
'n_estimators': (50, 1000),
}
La mayoría son similares a mis publicaciones anteriores; El único hiperparámetro adicional es learning_rate.
Tomó más tiempo hasta ahora, a los 96 minutos (~ 50% más que el bosque aleatorio!) Los mejores hiperparametros son:
best_parameters = OrderedDict({
'learning_rate': 0.04345459461297153,
'max_depth': 13,
'max_features': 0.4993693929975871,
'max_leaf_nodes': 20000,
'min_samples_leaf': 1,
'min_samples_split': 83,
'n_estimators': 325,
})
max_features, max_leaf_nodesy min_samples_leafson muy similares al bosque aleatorio sintonizado. n_estimators es también, y se alinea con lo que sugirió la gráfica de bloque elegida anteriormente: las 700 iteraciones adicionales eran en su mayoría innecesarias. Sin embargo, en comparación con el bosque aleatorio sintonizado, los árboles son solo un tercio tan profundo y min_samples_split es mucho más alto de lo que hemos visto hasta ahora. El valor de learning_rate No fue demasiado sorprendente según lo que vimos anteriormente.
Y los puntajes validados cruzados:
| Métrico | Significar | Std |
|---|---|---|
| Mae | -0.289 | 0.005 |
| Mape | -0.161 | 0.004 |
| MSE | -0.200 | 0.008 |
| RMSE | -0.448 | 0.009 |
| R² | 0.849 | 0.006 |
¡De todos los modelos hasta ahora, este es el mejor, con errores más pequeños, r² más altos y variaciones más bajas!
Finalmente, nuestro viejo amigo, la caja traza:
Conclusión
Y así llegamos al final de mi miniserie en los tres tipos más comunes de modelos basados en árboles.
Espero que, al ver diferentes formas de visualizar árboles, ahora (a) comprenda mejor cómo funcionan los diferentes modelos, sin tener que mirar las ecuaciones, y (b) puede usar sus propias gráficas para sintonizar sus propios modelos. También puede ayudar con la gestión de las partes interesadas: los ejecutivos prefieren imágenes bonitas a tablas de números, por lo que mostrarles una parcela de árbol puede ayudarlos a comprender por qué lo que le piden que haga es imposible.
Según este conjunto de datos, y estos modelos, el gradiente impulsado fue ligeramente superior al bosque aleatorio, y ambos fueron muy superiores a un árbol de decisión solitario. Sin embargo, esto puede haber sido porque el GBT tuvo un 50% más de tiempo para buscar mejores hiperparámetros (generalmente son más costosos computacionalmente, después de todo, era el mismo número de iteraciones). También vale la pena señalar que los GBT tienen una mayor tendencia a enlazarse que los bosques aleatorios. Y aunque el árbol de decisión tuvo un peor rendimiento, es lejos Más rápido, y en algunos casos de uso, esto es más importante. Además, como se mencionó, hay otras bibliotecas, con pros y contras, por ejemplo, Catboost maneja datos categóricos fuera del cuadro, mientras que otras bibliotecas GBT generalmente requieren que los datos categóricos se preprocesen (por ejemplo, una codificación o etiqueta de etiqueta). O, si te sientes realmente valiente, ¿qué tal apilar los diferentes tipos de árboles en un conjunto para un rendimiento aún mejor …
De todos modos, ¡hasta la próxima vez!