Usando pesos de regresión cuando

8

Supongamos que observamos datos Y,X y me gustaría ajustar un modelo de regresión para E[Y|X]. Desafortunadamente,Y a veces se mide con errores cuya media es distinta de cero.

Dejar Z{unbiased,biased} clima indicado Yse mide con errores medios clásicos cero o errores medios distintos de cero, respectivamente. Nos gustaría estimarE[Y|X,Z=unbiased]. Desafortunadamente,Z generalmente no se observa, y E[Y|X,Z=unbiased]E[Y|X]. Si ajustamos una regresión deY en X, obtendremos predicciones sesgadas.

Supongamos que generalmente no podemos observar Z, pero tener acceso a un modelo para Pr[Z|X,Y](porque aprendimos manualmente Z en un pequeño conjunto de entrenamiento y ajustamos un modelo de clasificación con Z como la variable objetivo). ¿Ajustar una regresión de Y en X usando Pr[Z=unbiased|X,Y] como pesos de regresión produce una estimación imparcial de E[Y|X,Z=unbiased] (o, en su defecto, una estimación menos sesgada de la que obtendríamos sin usar pesos)? ¿Se utiliza este método en la práctica y tiene un nombre?

Aclaración: el objetivo es ajustar un modelo que minimice el error cuadrático medio en datos no vistos (datos de prueba) donde . El predictor óptimo para ese objetivo es , por lo que esa es la función que estamos tratando de estimar. Los métodos para resolver este problema deben clasificarse en términos de cuán bien logran ese objetivo.Z=unbiasedE[Y|X,Z=unbiased]


Pequeño ejemplo en R con df$y_is_unbiasedel papel de y el papel de :Zdf$y_observedY

library(ggplot2)
library(randomForest)

set.seed(12345)

get_df <- function(n_obs, constant, beta, sd_epsilon, mismeasurement) {
    df <- data.frame(x1=rnorm(n_obs), x2=rnorm(n_obs), epsilon=rnorm(n_obs, sd=sd_epsilon))

    ## Value of Y if measured correctly
    df$y_unbiased <- constant + as.matrix(df[c("x1", "x2")]) %*% beta + df$epsilon

    ## Value of Y if measured incorrectly
    df$y_biased <- df$y_unbiased + sample(mismeasurement, size=n_obs, replace=TRUE)

    ## Y is equally likely to be measured correctly or incorrectly
    df$y_is_unbiased<- sample(c(TRUE, FALSE), size=n_obs, replace=TRUE)
    df$y_observed <- ifelse(df$y_is_unbiased, df$y_unbiased, df$y_biased)

    return(df)
}

## True coefficients
constant <- 5
beta <- c(1, 5)

df <- get_df(n_obs=2000, constant=constant, beta=beta, sd_epsilon=1.0, mismeasurement=c(-10.0, 5.0))

ggplot(df, aes(x=x1, y=y_observed, color=y_is_unbiased)) + geom_point() + scale_color_manual(values=c("#ff7f00", "#377eb8"))

## For facet_wrap title
df$string_y_is_unbiased <- paste0("y_is_unbiased: ", df$y_is_unbiased)

## Notice that Pr[Y | Z = biased] differs from Pr[Y | Z = unbiased]
ggplot(df, aes(x=y_observed)) + geom_histogram(color="black", fill="grey", binwidth=0.5) + facet_wrap(~ string_y_is_unbiased, ncol=1)

## Recover true constant and beta (plus noise) when using y_unbiased
summary(lm(y_unbiased ~ x1 + x2, data=df))

## Biased estimates when using y_biased (constant is biased downward)
summary(lm(y_biased ~ x1 + x2, data=df))

## Also get biased estimates when using y_observed (constant is biased downward)
summary(lm(y_observed ~ x1 + x2, data=df))

## Now image that we "rate" subset of the data (manually check/research whether y was measured with or without bias)
n_rated <- 1000
df_rated <- df[1:n_rated, ]

## Use a factor so that randomForest does classification instead of regression
df_rated$y_is_unbiased <- factor(df_rated$y_is_unbiased)

model_pr_unbiased <- randomForest(formula=y_is_unbiased ~ y_observed + x1 + x2, data=df_rated, mtry=2)

## Examine OOB confusion matrix (error rate < 5%)
print(model_pr_unbiased)

## Use the model to get Pr[Y is unbiased | X, observed Y] on unrated data
df_unrated <- df[(n_rated+1):nrow(df), ]
df_unrated$pr_unbiased <- as.vector(predict(model_pr_unbiased, newdata=df_unrated, type="prob")[, "TRUE"])

## Train a model on unrated data, using pr_unbiased as regression weights -- is this unbiased?
summary(lm(y_observed ~ x1 + x2, data=df_unrated, weights=df_unrated$pr_unbiased))

En este ejemplo, el modelo es un bosque aleatorio con . Si este modelo fuera perfectamente preciso, generaría pesos de 1.0 donde es imparcial, 0.0 donde está sesgado, y la regresión ponderada sería claramente imparcial. ¿Qué sucede cuando el modelo para tiene precisión de prueba y recuerda que no son perfectos (<100% de precisión)? ¿Se garantiza que la regresión ponderada sea menos sesgada que una regresión no ponderada de en ?Pr[Z=unbiased|X,Y]formula=y_is_unbiased ~ y_observed + x1 + x2YYPr[Z=unbiased|X,Y]YX


Ejemplo ligeramente más complejo en el que varía con (a diferencia del ejemplo más simple que publiqué anteriormente, donde ):Pr[Z=unbiased|X]XPr[Z=unbiased|X]=12X

library(ggplot2)
library(randomForest)

set.seed(12345)

logistic <- function(x) {
    return(1 / (1 + exp(-x)))
}

pr_y_is_unbiased <- function(x1, x2) {
    ## This function returns Pr[ Z = unbiased | X ]
    return(logistic(x1 + 2*x2))
}

get_df <- function(n_obs, constant, beta, sd_epsilon, mismeasurement) {
    df <- data.frame(x1=rnorm(n_obs), x2=rnorm(n_obs), epsilon=rnorm(n_obs, sd=sd_epsilon))

    ## Value of Y if measured correctly
    df$y_unbiased <- constant + as.matrix(df[c("x1", "x2")]) %*% beta + df$epsilon

    ## Value of Y if measured incorrectly
    df$y_biased <- df$y_unbiased + sample(mismeasurement, size=n_obs, replace=TRUE)

    ## Note: in this example, Pr[ Z = biased | X ] varies with X
    ## In the first (simpler) example I posted, Pr[ Z = biased | X ] = 1/2 was constant with respect to X
    df$y_is_unbiased <- runif(n_obs) < pr_y_is_unbiased(df$x1, df$x2)

    df$y_observed <- ifelse(df$y_is_unbiased, df$y_unbiased, df$y_biased)

    return(df)
}

## True coefficients
constant <- 5
beta <- c(1, 5)

df <- get_df(n_obs=2000, constant=constant, beta=beta, sd_epsilon=1.0, mismeasurement=c(-10.0, 5.0))

ggplot(df, aes(x=x1, y=y_observed, color=y_is_unbiased)) + geom_point() + scale_color_manual(values=c("#ff7f00", "#377eb8"))

## For facet_wrap title
df$string_y_is_unbiased <- paste0("y_is_unbiased: ", df$y_is_unbiased)

## Notice that Pr[Y | Z = biased] differs from Pr[Y | Z = unbiased]
ggplot(df, aes(x=y_observed)) + geom_histogram(color="black", fill="grey", binwidth=0.5) + facet_wrap(~ string_y_is_unbiased, ncol=1)

## Recover true constant and beta (plus noise) when using y_unbiased
summary(lm(y_unbiased ~ x1 + x2, data=df))

## Biased estimates when using y_biased (constant is biased downward)
summary(lm(y_biased ~ x1 + x2, data=df))

## Also get biased estimates when using y_observed
## Note: the constant is biased downward _and_ the coefficient on x2 is biased upward!
summary(lm(y_observed ~ x1 + x2, data=df))

## Now image that we "rate" subset of the data (manually check/research whether y was measured with or without bias)
n_rated <- 1000
df_rated <- df[1:n_rated, ]

## Use a factor so that randomForest does classification instead of regression
df_rated$y_is_unbiased <- factor(df_rated$y_is_unbiased)

model_pr_unbiased <- randomForest(formula=y_is_unbiased ~ y_observed + x1 + x2, data=df_rated, mtry=2)

## Examine OOB confusion matrix (error rate < 5%)
print(model_pr_unbiased)

## Use the model to get Pr[Y is unbiased | X, observed Y] on unrated data
df_unrated <- df[(n_rated+1):nrow(df), ]
df_unrated$pr_unbiased <- as.vector(predict(model_pr_unbiased, newdata=df_unrated, type="prob")[, "TRUE"])

## Train a model on unrated data, using pr_unbiased as regression weights -- is this unbiased? If not, is it _less_ biased than the unweighted model?
summary(lm(y_observed ~ x1 + x2, data=df_unrated, weights=df_unrated$pr_unbiased))

## What happens if we use pr_unbiased as a feature (aka predictor) in the regression, rather than a weight?
## In this case the weighted regression seems to do better, but neither is perfect
## Note: copied from shabbychef's answer
summary(lm(formula = y_observed ~ x1 + x2 + I(1 - pr_unbiased), data = df_unrated))

En este ejemplo, la regresión ponderada de en parece menos sesgada que la regresión no ponderada. ¿Es eso cierto en general? También probé la sugerencia de shabbychef (ver la respuesta a continuación) en este ejemplo, y parece que es peor que la regresión ponderada.YX


Para aquellos que prefieren Python a R, aquí está la segunda simulación en Python:

import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LinearRegression

def logistic(x):
    return 1 / (1 + np.exp(-x))

def pr_y_is_unbiased(x1, x2):
    # This function returns Pr[ Z = unbiased | X ]
    return logistic(x1 + 2*x2)

def get_df(n_obs, constant, beta, sd_epsilon, mismeasurement):
    df = pd.DataFrame({
        'x1': np.random.normal(size=n_obs),
        'x2': np.random.normal(size=n_obs),
        'epsilon': np.random.normal(size=n_obs, scale=sd_epsilon),
    })

    df['y_unbiased'] = constant + np.dot(np.array(df[['x1', 'x2']]), beta) + df['epsilon']

    # Note: df['y_biased'].mean() will differ from df['y_unbiased'].mean() if the mismeasurements have a nonzero mean
    df['y_biased'] = df['y_unbiased'] + np.random.choice(mismeasurement, size=n_obs)

    df['y_is_unbiased'] =  np.random.uniform(size=n_obs) < pr_y_is_unbiased(df['x1'], df['x2'])

    df['y_observed'] = df.apply(lambda row: row['y_unbiased'] if row['y_is_unbiased'] else row['y_biased'], axis=1)

    return df


constant = 5
beta = np.array([1, 5])
print(f'true coefficients:\n constant = {constant}, beta = {beta}')

n_obs = 2000

# Note: the mean of the possible mismeasurements is nonzero (this is the source of the bias)
df = get_df(n_obs=n_obs, constant=constant, beta=beta, sd_epsilon=1.0, mismeasurement=[-10.0, 5.0])

lr = LinearRegression()
lr.fit(X=df[['x1', 'x2']], y=df['y_observed'])

print(f'estimates from unweighted regression of Y on X ({df.shape[0]} obs):\n constant = {lr.intercept_}, beta = {lr.coef_}')

# Note: pretend that we only observe y_is_unbiased on a "rated" subset of the data
n_rated = n_obs // 2
df_rated = df.iloc[:n_rated].copy()
df_unrated = df.iloc[n_rated:].copy()

rf = RandomForestClassifier(n_estimators=500, max_features=2, oob_score=True)
rf_predictors = ['y_observed', 'x1', 'x2']

rf.fit(X=df_rated[rf_predictors], y=df_rated['y_is_unbiased'])

print(f'random forest classifier OOB accuracy (for predicting whether Y is unbiased): {rf.oob_score_}')

df_unrated['pr_y_is_unbiased'] = rf.predict_proba(df_unrated[rf_predictors])[:, 1]

lr.fit(X=df_unrated[['x1', 'x2']], y=df_unrated['y_observed'], sample_weight=df_unrated['pr_y_is_unbiased'])
print(f'estimates from weighted regression of Y on X ({df_unrated.shape[0]} obs):\n constant = {lr.intercept_}, beta = {lr.coef_}')
Adrian
fuente
1
Esto casi suena como "Variables instrumentales", donde observa algunas variables que están correlacionadas con el error en su regresión. Sin embargo, me temo que eso no ayuda demasiado.
shabbychef
@shabbychef Es cierto, pero no hay instrumentos disponibles en esta configuración.
Adrian
1
Con su problema actualizado, el sesgo ahora es una función de , y deberíamos esperar que los coeficientes de regresión cambien. Es decir, el término 'sesgo' es donde . Expandiría con una expansión de Taylor para mostrar que hay una dependencia lineal adicional de en y . Volviendo a su pregunta original, el término de sesgo que ve y la variable que observa, no cambia la varianza de ninguna manera, pero sí cambia el valor esperado. Por lo tanto, deberían ser pirateados en la especificación lineal, creo, y no en los pesos. xi0.25pp=logistic(x1+2x2)pyx1x2z
shabbychef

Respuestas:

2

Usaría la 'probabilidad de sesgo' como una variable ficticia en la regresión; posiblemente puede 'absorber' el sesgo presente en el caso sesgado. Usando su ejemplo, (pero llamando set.seed(1234)antes de la llamada a get_df), intenté

summary(lm(y_observed ~ x1 + x2 + I(1-pr_unbiased), data=df_unrated))

y consiguió:

Call:
lm(formula = y_observed ~ x1 + x2 + I(1 - pr_unbiased), data = df_unrated)

Residuals:
   Min     1Q Median     3Q    Max 
-9.771 -2.722 -0.386  2.474 11.238 

Coefficients:
                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)           5.515      0.250   22.07   <2e-16 ***
x1                    1.108      0.169    6.54    1e-10 ***
x2                    4.917      0.168   29.26   <2e-16 ***
I(1 - pr_unbiased)   -3.727      0.383   -9.72   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 5.25 on 996 degrees of freedom
Multiple R-squared:  0.514,     Adjusted R-squared:  0.513 
F-statistic:  351 on 3 and 996 DF,  p-value: <2e-16

El coeficiente para el término 1-pr_unbiaseddebe ser el tamaño del sesgo.

shabbychef
fuente
Idea interesante (+1)! Actualicé mi publicación con un segundo ejemplo, un poco más complejo, en el que varía con lugar de ser constante. En este caso, tanto la constante como el coeficiente en x2 están sesgados cuando regresas en , y no creo que tu método funcione tan bien (ya que solo elimina el sesgo de la constante). ¡Echa un vistazo y hazme saber lo que piensas! Pr[Z=unbiased|X]XYX
Adrian
2

Este es un problema de variable omitida en el que tiene una variable indicadora que no se observa, pero que tiene una relación con la variable de respuesta. Dado que "sesgo" es una propiedad de un estimador, no una variable de regresión, voy a replantear su pregunta como una en la que desea encontrar la verdadera función de regresión condicional en utilizando datos de regresión que no incluyen esta variable, y un conjunto separado de datos de entrenamiento de regresión que se usa para estimar las probabilidades .ZZ=0p0(x,y)P(Z=0|X=x,Y=y)

Supongamos que denota la densidad condicional de la variable de respuesta en el problema de regresión con la variable de respuesta y la variable explicativa (pero excluyendo ). A partir de las reglas de probabilidad condicional, la distribución de interés objetivo puede escribirse como:pY|XYXZ

p(Y=y|X=x,Z=0)=p(Y=y,Z=0|X=x)p(Z=0|X=x)=p0(x,y)pY|X(y|x)Rp0(x,y)pY|X(y|x) dyyp0(x,y)pY|X(y|x).

Por lo tanto, podemos ver que es suficiente poder estimar la función de regresión en el modelo de regresión con omitida, y también estimar la función de probabilidad que tiene como estimador separado de sus datos de entrenamiento. El primero se puede estimar usando la estimación OLS sin imponer ningún peso. La "ponderación" ocurre después de la estimación de esta función, por sustitución en la ecuación anterior.pY|XZp0

Podemos ver que no es necesario (o conveniente) para utilizar cualquier peso en la regresión de en , ya que es suficiente para estimar la densidad condicional sin consideración de . La estimación OLS de los coeficientes de esta regresión da un estimador , y dado que también tiene un estimador separado , entonces tiene:YXpY|XZp^Y|Xp^0

p^(Y=y|X=x,Z=0)p^0(x,y)p^Y|X(y|x).

Una vez que haya sustituido estos estimadores, todo lo que queda es tratar de determinar la constante de escala que produce una función de densidad adecuada. Esto puede hacerse mediante una variedad de métodos de integración numérica (por ejemplo, la regla de Simpson, la cuadratura, Metropolis-Hastings, etc.).

Ben - Restablece a Monica
fuente
1
Gracias por esta respuesta detallada (+1), la leeré detenidamente y te responderé. Estoy de acuerdo en que una descripción más correcta del problema podría ser "Y a veces se mide con un error medio cero", en lugar de "Y está sesgado".
Adrian
¡Interesante! Un detalle negativo / complicado aquí es que esto requiere estimar la distribución completa de , en lugar de solo la media condicional. La normalidad es una suposición común, pero eso puede no ser válido en mi aplicación. Y|X
Adrian
Sí, pero eso no debería ser realmente complicado. Cualquier modelo de regresión que use tendrá una forma de modelo clara que determina esta distribución condicional.
Ben - Restablece a Monica
1
Ben, ¿estás seguro de que eso es cierto en un entorno de aprendizaje automático / predicción? Ajustar una regresión lineal para minimizar el error cuadrático medio en los datos de la prueba no requiere hacer suposiciones sobre la normalidad de los residuos (siempre que no esté haciendo pruebas de hipótesis de muestra finita, no le interesen los intervalos de predicción, no le importa si su estimador es un estimador de máxima verosimilitud, etc.). Estoy interesado en la estimación de la media condicional (de dado ) y no han hecho suposiciones sobre la distribución de . YXY
Adrian
1
No creo que Adrian esté necesariamente interesado en la distribución completa de (Y | X, Z = 0), simplemente en su media. Si se quiere conocer la distribución completa de Y | X, Z = 0, entonces, por supuesto, las distribuciones exactas de Y y X son muy relevantes, pero si solo se desea estimar E [Y | X, Z = 0], entonces esto es no es necesario: la ley de los grandes números funciona para distribuciones arbitrarias.
user1111929
1

Su idea no dará una estimación imparcial, a menos que siempre pueda estar 100% seguro de si está sesgada o no. Tan pronto como un ejemplo sesgado pueda ser parte de su conjunto de entrenamiento con probabilidad distinta de cero, habrá sesgo, ya que no tiene nada para cancelar ese sesgo. En la práctica, su sesgo simplemente se multiplicará por un factor , donde es la probabilidad de que se detecte un ejemplo sesgado como tal.α<1α

Suponiendo que tiene suficientes datos, un mejor enfoque es calcular para cada muestra, y luego eliminar todas las muestras del conjunto de entrenamiento donde esta probabilidad excede un cierto umbral. Por ejemplo, si es factible que entrene su conjunto de datos solo en las muestras para las que , y su conjunto de datos disminuye de sesgado y imparcial a sesgado y ejemplos imparciales, y el sesgo se multiplicará por un factor . Como típicamente será mucho más bajo que , será mucho más pequeño queP(Z=biased|X,Y)P(Z=biased|X,Y)<0.01NMnmf=n(N+M)N(n+m)nNmMf1, resultando en una mejora significativa.

Tenga en cuenta que ambas técnicas se pueden combinar: las filas con salen (para alguna opción de , anteriormente usé ), y las filas que permanecen en obtenga un peso , que en realidad debería darle lo mejor de ambos mundos.p=P(Z=biased|X,Y)>βββ=0.01(1pβ)2

usuario1111929
fuente
Estoy de acuerdo en que la regresión ponderada generalmente no producirá estimaciones imparciales a menos que el clasificador sea 100% exacto. ¿Se garantiza reducir el sesgo? ¿Su enfoque de corte es necesariamente mejor, o depende de los tamaños de muestra y la precisión del clasificador?
Adrian
No es realmente la precisión del clasificador, principalmente la cantidad resultante de filas, ya que para conjuntos de datos muy pequeños a veces uno no puede permitirse descartar una gran cantidad de filas. Pero dada la información suficiente, no veo ninguna razón para dudar: su enfoque pesa las filas con un 50% de posibilidades de sesgo, la mitad de relevante que las filas con un 0% de posibilidades de sesgo. Personalmente, nunca haría eso, preferiría 1000 filas limpias garantizadas en lugar de 2000 filas, cada una con un 50% de posibilidades de sesgo. Tenga en cuenta que también puede combinar ambos enfoques, para aplicar un sistema más gradual que un corte simple, he actualizado mi respuesta para ampliar esto.
user1111929