Un sesgo sutil que podría afectar sus árboles de decisión y bosques aleatorios

Eso se puede eliminar fácilmente

Un árbol de decisión artística generado por Dall-E

Existe la posibilidad de que sus árboles de decisión y bosques aleatorios sufran un pequeño sesgo, que puede eliminarse con facilidad y prácticamente sin costo alguno. Esto es lo que exploramos en esta publicación.

Descargo de responsabilidad: la publicación analiza una investigación reciente realizada por el autor.

Introducción

Los árboles de decisión y los bosques aleatorios son técnicas de clasificación y regresión ampliamente adoptadas en el aprendizaje automático. Los árboles de decisión se ven favorecidos por su interpretabilidad, mientras que los bosques aleatorios se destacan como técnicas de última generación altamente competitivas y de propósito general. Implementaciones CART de uso común, como las del paquete Python aprender y los paquetes R árbol y signo de intercalación, suponga que todas las características son continuas. A pesar de esta suposición silenciosa de continuidad, ambas técnicas se aplican habitualmente a conjuntos de datos con diversos tipos de características.

En un artículo reciente, investigamos las implicaciones prácticas de violar el supuesto de continuidad y descubrimos que conduce a un sesgo. Es importante destacar que estos supuestos casi siempre se violan en la práctica. En este artículo, presentamos y discutimos nuestros hallazgos, ilustramos y explicamos los antecedentes y proponemos algunas técnicas simples para mitigar el sesgo.

Un ejemplo motivador

Saltemos a ello con un ejemplo usando el rendimiento de la CPU conjunto de datos del repositorio de la UCI. Lo importaremos a través del conjuntos de datos comunes paquete, para simplificar el preprocesamiento y evitar la necesidad de codificación de características y la imputación de datos faltantes.

import numpy as np

from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import RepeatedKFold, cross_validate
from scipy.stats import wilcoxon

from common_datasets.regression import load_cpu_performance

dataset = load_cpu_performance()
X = dataset['data']
y = dataset['target']

# a cross-validation wrapper to simplify the code
def cv_rf(X, y, regressor=RandomForestRegressor):
return cross_validate(
estimator=regressor(max_depth=11),
X=X, y=y,
cv=RepeatedKFold(n_splits=5, n_repeats=400, random_state=5),
scoring='r2'
)['test_score']

r2_original = cv_rf(X, y)
r2_mirrored = cv_rf(-X, y)

En el experimento, evaluamos el rendimiento del regresor de bosque aleatorio tanto en los datos originales como en su versión reflejada (cada característica multiplicada por -1). El hiperparámetro para el regresor (max_profundidad = 11) se eligió en un paso de selección de modelo dedicado, maximizando la puntuación r2 en un rango razonable de profundidades. La validación cruzada empleada para la evaluación es significativamente más completa que la que se utiliza normalmente en el aprendizaje automático y abarca un total de 2000 pliegues.

print(f'original r2: {np.mean(r2_original):.4f}')
print(f'mirrored r2: {np.mean(r2_mirrored):.4f}')
print(f'p-value: {wilcoxon(r2_original, r2_mirrored, zero_method="zsplit").pvalue:.4e}')
# original r2: 0.8611
# mirrored r2: 0.8595
# p-value: 6.2667e-04

En términos de puntuaciones de r2, observamos un deterioro de 0,2 puntos porcentuales cuando se reflejan los atributos. Además, la diferencia es estadísticamente significativa a niveles convencionales (p << 0,01).

Los resultados son algo sorprendentes y contrarios a la intuición. Las técnicas de aprendizaje automático suelen ser invariante a ciertos tipos de transformaciones. Por ejemplo, k Vecinos más cercanos es invariante para cualquier transformación ortogonal (como la rotación), y las técnicas lineales suelen ser invariantes para la escala de atributos. Dado que la partición del espacio en los árboles de decisión está alineada con los ejes, no se puede esperar que sea invariante con las rotaciones. Sin embargo, es invariante al escalado: aplicar cualquier multiplicador positivo a cualquier característica dará como resultado exactamente el mismo árbol. Por lo tanto, algo debe estar sucediendo con la simetría de los ejes.

Surge una pregunta intrigante: ¿qué pasaría si reflejar los ejes condujera a mejores resultados? ¿Deberíamos considerar otro grado de libertad (multiplicar por -1) en la selección del modelo más allá de determinar la profundidad óptima? Bueno, en el resto de la publicación descubriremos qué está pasando aquí.

Inducción e inferencia del árbol de decisión binaria

Ahora, repasemos brevemente algunas características importantes de la construcción y la realización de inferencias con árboles binarios de clasificación y regresión (CART), que se utilizan en la mayoría de las implementaciones. Una diferencia notable en comparación con otras técnicas de inducción de árboles como ID3 y C4.5 es que los árboles CART no tratan las características categóricas de ninguna manera especial. Los árboles CART asumen que todas las características son continuas.

Dado un conjunto de entrenamiento (clasificación o regresión), los árboles de decisión se inducen dividiendo recursivamente el conjunto de entrenamiento junto con el espacio de características utilizando condiciones como característica o alternativamente, características <= umbral. La elección del condicionamiento suele ser una propiedad intrínseca de las implementaciones.. Por ejemplo, el paquete Python aprender utiliza condiciones de la forma característica <= umbralmientras que el paquete R árbol usos característica . Tenga en cuenta que estas condiciones están alineadas con la presunción de que todas las características son continuas.

Sin embargo, la presunción de características continuas no es una limitación. Aún se pueden introducir características enteras, características de categorías a través de alguna codificación o características binarias en estos árboles. Examinemos un árbol de ejemplo en un escenario hipotético de aprobación de préstamo (un problema de clasificación binaria), basado en tres atributos:

  • graduado (binario): 0 si el solicitante no se graduó, 1 si el solicitante se graduó;
  • ingresos (flotantes): los ingresos brutos anuales del solicitante;
  • dependientes (int): el número de dependientes;

y la variable objetivo es binaria: si el solicitante incumple (1) o paga (0).

Un árbol de decisiones creado para un escenario hipotético de aprobación de un préstamo.

La estructura del árbol, así como las condiciones en los nodos (qué umbral en qué característica), se infieren a partir de los datos de entrenamiento. Para obtener más detalles sobre la inducción de árboles, consulte aprendizaje del árbol de decisiones en Wikipedia.

Dado un árbol como este, la inferencia para un nuevo registro se realiza comenzando desde el nodo hoja, aplicando recursivamente las condiciones y enrutando el registro a la rama correspondiente a la salida de la condición. Cuando se encuentra un nodo hoja, la etiqueta (o eventualmente la distribución) registrada en el nodo hoja se devuelve como predicción.

El condicionamiento y el umbral

Un conjunto finito de registros de entrenamiento no puede implicar una partición única del espacio de características. Por ejemplo, el árbol de la figura anterior podría inducirse a partir de datos donde no hay ningún registro con graduación = 0 e ingresos en el rango ]60k, 80k[. The tree induction method identifies that a split should be made between the income values 60k and 80k. In the absence of further information, the midpoint of the interval (70k) is used as the threshold. Generally, it could be 65k or 85k as well. Using the midpoints of the unlabeled intervals is a common practice and a reasonable choice: in line with the assumption of continuous features, 50% of the unlabeled interval is assigned to the left and 50% to the right branches.

Due to the use of midpoints as thresholds, the tree induction is completely independent of the choice of the conditioning operator: using both <= and < leads to the same tree structure, with the same thresholds, except for the conditioning operator.

However, inference does depend on the conditioning operator. In the example, if a record representing an applicant with a 70k income is to be inferred, then in the depicted setup, it will be routed to the left branch. However, using the operator <, it will be routed to the right branch. With truly continuous features, there is a negligible chance for a record with exactly 70k income to be inferred. However, in reality, the income might be quoted in units of 1k, 5k, or eventually 10k, which makes it probable that the choice of the conditioning operator has a notable impact on predictions.

The relation of conditioning and mirroring

Why do we talk about the conditioning when the problem we observed is about the mirroring of features? The two are basically the same. A condition “feature < threshold” is equivalent to the condition “-feature <= -threshold” in the sense that they lead to the same, but mirrored partitioning of the real axis. Namely, in both cases, if the feature value equals the threshold, that value is in the same partition where the feature values greater than the threshold are. For example, compare the two trees below, the one we used for illustration earlier, except all conditioning operators are changed to <, and another tree where the operator is kept, but the tree is mirrored: one can readily see that for any record they lead to the same predictions.

The previous tree with the conditioning operator <
The tree built on the mirrored data (still using the conditioning operator ≤)

Since tree induction is independent of the choice of conditioning, building a tree on mirrored data and then predicting mirrored vectors is equivalent to using the non-default conditioning operator (<) for inference on non-mirrored records. When the trees of the forest were fitted to the mirrored data, even though sklearn uses the ‘<=’ operator for conditioning, it worked as if it used the ‘<’ operator. Consequently, the performance deterioration we discovered with mirroring is due to thresholds coinciding with feature values, leading to different predictions during the evaluation of the test sets.

For the sake of completeness, we note that the randomization in certain steps of tree induction might lead to slightly different trees when fitted to the mirrored data. However, these differences smooth out in random forests, especially in 2k folds of evaluation. The observed performance deterioration is a consequence of the systematic effect of thresholds coinciding with feature values.

When can this happen?

Primarily, two circumstances increase the likelihood of the phenomenon:

  • When a feature domain contains highly probable equidistant values: This sets the stage for a threshold (being the mid-point of two observations) to coincide with a feature value with high probability.
  • Relatively deep trees are built: Generally, as a tree gets deeper, the training data becomes sparser at the nodes. When certain observations are absent at greater depths, thresholds might fall on those values.

Interestingly, features taking a handful of equidistant values are very common in numerous domains. For example:

  • The age feature in medical datasets.
  • Rounded decimals (observed to the, say, 2nd digit will form a lattice).
  • Monetary figures quoted in units of millions or billions in financial datasets.

Additionally, almost 97% of features in the toy regression and classification datasets in sklearn.datasets are of this kind. Therefore, it is not an over-exaggeration to say that features taking equidistant values with high probability are present everywhere. Consequently, as a rule of thumb, the deeper trees or forests one builds, the more likely it becomes that thresholds interfere with feature values.

It is a bias, model selection cannot help!

We have seen that the two conditioning operators (the non-default one imitated by the mirroring of data) can lead to different prediction results with statistical significance. The two predictions cannot be unbiased at the same time. Therefore, we consider the use of either form of conditioning introducing a bias when thresholds coincide with feature values.

Alternatively, it is tempting to consider one form of conditioning to be luckily aligned with the data and improving the performance. Thus, model selection could be used to select the most suitable form of conditioning (or whether the data should be mirrored). However, in a particular model selection scenario, using some k-fold cross-validation scheme, we can only test which operator is typically favorable if, say, 20% of the data is removed (5-fold) from training and then used for evaluation. When a model is trained on all data, other thresholds might interfere with feature values, and we have no information on which conditioning would improve the performance.

Mitigating the bias in random forests

A natural way to eliminate the bias is to integrate out the effect of the choice of conditioning operators. This involves carrying out predictions with both operators and averaging the results.

In practice, with random forests, exploiting the equivalence of data mirroring and changing the conditioning operator, this can be approximated for basically no cost. Instead of using a forest of N_e estimators, one can build two forests of half the size, fit one to the original data, the other to the mirrored data, and take the average of the results. Note that this approach is applicable with any random forest implementation, and has only marginal additional cost (like multiplying the data by -1 and averaging the results).

For example, we implement this strategy in Python below, aiming to integrate out the bias from the sklearn random forest.

from sklearn.base import RegressorMixin

class UnbiasedRandomForestRegressor(RegressorMixin):

def __init__(self, **kwargs):
# determining the number of estimators used in the
# two subforests (with the same overall number of trees)
self.n_estimators = kwargs.get('n_estimators', 100)

n_leq = int(self.n_estimators / 2)
n_l = self.n_estimators - n_estimators_leq

# instantiating the subforests
self.rf_leq = RandomForestRegressor(**(kwargs | {'n_estimators': n_leq}))
self.rf_l = RandomForestRegressor(**(kwargs | {'n_estimators': n_l}))

def fit(self, X, y, sample_weight=None):
# fitting both subforests
self.rf_leq.fit(X, y, sample_weight)
self.rf_l.fit(-X, y, sample_weight)

return self

def predict(self, X):
# taking the average of the predictions
return np.mean([self.rf_leq.predict(X), self.rf_l.predict(-X)]eje=0)

def get_params(self, profundo=Falso):
# devolver los parámetros
devolver self.rf_leq.get_params(profundo) | {'n_estimators': self.n_estimators}

A continuación, podemos ejecutar los mismos experimentos que antes, usando exactamente los mismos pliegues:

r2_unbiased = cv_rf(X, y, UnbiasedRandomForestRegressor)

¡Comparemos los resultados!

print(f'original r2: {np.mean(r2_original):.4f}')
print(f'mirrored r2: {np.mean(r2_mirrored):.4f}')
print(f'unbiased r2: {np.mean(r2_unbiased):.4f}')
# original r2: 0.8611
# mirrored r2: 0.8595
# unbiased r2: 0.8608

Según las expectativas, la puntuación r2 del bosque imparcial se sitúa entre las puntuaciones obtenidas por el bosque original con y sin duplicación de los datos. Podría parecer que eliminar el sesgo es perjudicial para el desempeño; sin embargo, enfatizamos nuevamente que una vez que el bosque se ajusta con todos los datos, las relaciones podrían invertirse y el modelo original podría conducir a peores predicciones que el modelo reflejado. Eliminar el sesgo mediante la integración de la dependencia del operador de condicionamiento elimina el riesgo de un deterioro del rendimiento debido a depender del operador de condicionamiento predeterminado.

Conclusión

Se ha establecido y demostrado la presencia de un sesgo relacionado con la interacción de la elección del condicionamiento y las características que toman valores equidistantes. Dada la ocurrencia común de características de este tipo, es probable que el sesgo esté presente en árboles de decisión suficientemente profundos y bosques aleatorios. El efecto potencialmente perjudicial puede eliminarse promediando las predicciones realizadas por los dos operadores condicionantes. Curiosamente, en el caso de bosques aleatorios, esto se puede hacer básicamente sin costo alguno. En el ejemplo que utilizamos, la mejora alcanzó el nivel de 0,1 a 0,2 puntos porcentuales de las puntuaciones r2. Finalmente, enfatizamos que los resultados se generalizan a problemas de clasificación y árboles de decisión únicos también (ver preimpresión).

Otras lecturas

Para más detalles recomiendo:

Si estás interesado en más contenido como este, ¡no olvides suscribirte! También puedes encontrarme en LinkedIn!


Un sesgo sutil que podría afectar sus árboles de decisión y bosques aleatorios fue publicado originalmente en Hacia la ciencia de datos en Medium, donde las personas continúan la conversación resaltando y respondiendo a esta historia.