Utilizzando i pesi di regressione quando


8

Supponiamo di osservare i dati e che vorremmo adattare un modello di regressione per . Sfortunatamente, è talvolta misurato con errori la cui media è diversa da zero.Y,XE[Y|X]Y

Consenti a indicare se viene misurato rispettivamente con errori di media zero classici o con errori non zero. Vorremmo stimare . Sfortunatamente, generalmente non viene osservato e . Se adattiamo una regressione di su , otterremo previsioni distorte.Z{unbiased,biased}YE[Y|X,Z=unbiased]ZE[Y|X,Z=unbiased]E[Y|X]YX

Supponiamo di non poter generalmente osservare , ma di avere accesso a un modello per (perché abbiamo imparato manualmente Z su un piccolo set di allenamento e adattiamo un modello di classificazione con Z come variabile target) . Adattare una regressione di Y su X usando \ Pr [Z = \ text {imparziale} \, | \, X, Y] come pesi di regressione produce una stima imparziale di \ mathbf {E} [Y \, | \, X, Z = \ text {imparziale}] (o, in mancanza, una stima meno distorta di quella che otterremmo senza usare pesi)? Questo metodo è utilizzato in pratica e ha un nome?ZPr[Z|X,Y]ZZYXPr[Z=unbiased|X,Y]E[Y|X,Z=unbiased]

Chiarimento: l'obiettivo è quello di adattare un modello che minimizza l'errore quadratico medio su dati invisibili (dati di test) dove Z=unbiased . Il predittore ottimale per tale obiettivo è E[Y|X,Z=unbiased] , quindi questa è la funzione che stiamo cercando di stimare. I metodi per risolvere questo problema dovrebbero essere classificati in base al modo in cui raggiungono tale obiettivo.


Piccolo esempio in R con df$y_is_unbiasedil ruolo di Z e df$y_observedil ruolo di Y :

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))

In questo esempio, il modello è una foresta casuale con . Se questo modello fosse perfettamente preciso, genererebbe pesi di 1.0 dove è imparziale, 0.0 dove è distorto e la regressione ponderata sarebbe chiaramente imparziale. Cosa succede quando il modello per ha una precisione di test e richiami non perfetti (<100% di precisione)? La regressione ponderata è garantita essere meno distorta di una regressione non ponderata di su ?Pr[Z=unbiased|X,Y]formula=y_is_unbiased ~ y_observed + x1 + x2YYPr[Z=unbiased|X,Y]YX


Esempio leggermente più complesso in cui varia con (al contrario dell'esempio più semplice che ho pubblicato sopra, dove ):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))

In questo esempio, la regressione ponderata di su sembra meno distorta rispetto alla regressione non ponderata. È vero in generale? Ho anche provato il suggerimento di Shabbychef (vedi risposta sotto) su questo esempio e sembra fare peggio della regressione ponderata.YX


Per coloro che preferiscono Python a R, ecco la seconda simulazione in 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_}')

1
Sembra quasi "Variabili strumentali", in cui si osservano alcune variabili correlate all'errore nella regressione. Temo che non sia di grande aiuto, però.
Shabbychef,

@shabbychef Vero, ma non ci sono strumenti disponibili in questa configurazione.
Adrian,

1
Con il tuo problema aggiornato, il bias ora è una funzione di e dovremmo aspettarci che i coefficienti di regressione cambino. Cioè, il termine 'bias' è dove . Espanderò con un'espansione di Taylor per mostrare che esiste una dipendenza lineare extra di su e . Tornando alla domanda originale, il termine di bias che vedi e la variabile che osservi non cambiano in alcun modo la varianza, ma cambiano il valore atteso. Quindi dovrebbero essere incisi nelle specifiche lineari, penso, e non nei pesi. xi0.25pp=logistic(x1+2x2)pyx1x2z
shabbychef

Risposte:


2

Userei la "probabilità di polarizzazione" come variabile fittizia nella regressione; può eventualmente "assorbire" la distorsione presente nel caso distorto. Usando il tuo esempio (ma chiamando set.seed(1234)prima della chiamata a get_df), ho provato

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

e ottenuto:

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

Il coefficiente per il termine 1-pr_unbiaseddovrebbe essere la dimensione della distorsione.


Idea interessante (+1)! Ho aggiornato il mio post con un secondo esempio leggermente più complesso in cui varia con invece di essere costante. In questo caso, sia la costante che il coefficiente su x2 sono distorti quando si regredisce su , e non penso che anche il tuo metodo funzioni (poiché rimuove solo la distorsione dalla costante). Dai un'occhiata e fammi sapere cosa ne pensi! Pr[Z=unbiased|X]XYX
Adrian,

2

Questo è un problema di variabile omessa in cui si ha una variabile indicatore non osservata, ma che ha una relazione con la variabile di risposta. Poiché "il bias" è una proprietà di uno stimatore, non una variabile di regressione, ho intenzione di riformulare la tua domanda come una in cui vuoi trovare la vera funzione di regressione condizionata su usando i dati di regressione che non includono questa variabile un insieme separato di dati di addestramento alla regressione che viene utilizzato per stimare le probabilità .ZZ=0p0(x,y)P(Z=0|X=x,Y=y)

Sia denota la densità condizionale della variabile di risposta nel problema di regressione con la variabile di risposta e la variabile esplicativa (ma esclusa ). Dalle regole della probabilità condizionale, la distribuzione target dell'interesse può essere scritta come: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).

Quindi, possiamo vedere che è sufficiente essere in grado di stimare la funzione di regressione nel modello di regressione con omessa, e anche stimare la funzione di probabilità che hai come stimatore separato dai tuoi dati di allenamento. Il primo può essere stimato utilizzando la stima OLS senza imporre pesi. La "ponderazione" si verifica dopo la stima di questa funzione, sostituendo l'equazione sopra.pY|XZp0

Possiamo vedere che non è necessario (o desiderabile) per utilizzare i pesi nella regressione di su , dato che è sufficiente per stimare la densità condizionata senza considerare . La stima OLS dei coefficienti di questa regressione fornisce uno stimatore , e poiché hai anche uno stimatore separato hai quindi:YXpY|XZp^Y|Xp^0

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

Dopo aver sostituito questi stimatori, tutto ciò che rimane è cercare di determinare la costante di ridimensionamento che produce una funzione di densità adeguata. Questo può essere fatto con una serie di metodi di integrazione numerica (ad es. Regola di Simpson, quadratura, Metropolis-Hastings, ecc.).


1
Grazie per questa risposta dettagliata (+1), la leggerò attentamente e ti ricontatterò. Concordo sul fatto che una descrizione più corretta del problema potrebbe essere "Y è talvolta misurato con errore non zero", piuttosto che "Y è distorto".
Adrian,

Interessante! Un aspetto negativo / dettaglio complicato qui è che ciò richiede di stimare la distribuzione completa di , piuttosto che solo la media condizionale. La normalità è un presupposto comune, ma potrebbe non valere nella mia applicazione. Y|X
Adrian,

Sì, ma non dovrebbe essere davvero complicato. Qualunque sia il modello di regressione che utilizzerai avrà una forma di modello chiara che determina questa distribuzione condizionale.
Ben - Ripristina Monica il

1
Ben, sei sicuro che sia vero in un'impostazione di apprendimento / previsione automatica? Montare una regressione lineare per ridurre al minimo l'errore al quadrato medio sui dati del test non richiede di fare ipotesi sulla normalità dei residui (purché non si eseguano test di ipotesi a campione finito, non siano interessati a intervalli di previsione, non importa se lo stimatore è uno stimatore della massima verosimiglianza, ecc.). Mi interessa stimare una media condizionata (di in ) e non hanno fatto ipotesi circa la distribuzione di . YXY
Adrian,

1
Non penso che Adrian sia necessariamente interessato alla distribuzione completa di (Y | X, Z = 0), semplicemente nella sua media. Se si vuole conoscere la distribuzione completa di Y | X, Z = 0, ovviamente le esatte distribuzioni di Y e X sono molto rilevanti, ma se si vuole solo stimare E [Y | X, Z = 0], allora questo è non necessario: la legge dei grandi numeri funziona per distribuzioni arbitrarie.
user1111929,

1

La tua idea non fornirà una stima imparziale, a meno che tu non possa sempre essere sicuro al 100% se è distorta o meno. Non appena un esempio distorto può far parte del tuo set di allenamento con probabilità diversa da zero, ci sarà un pregiudizio, poiché non hai nulla per annullare tale pregiudizio. In pratica, il tuo bias verrà semplicemente moltiplicato per un fattore , dove è la probabilità che un esempio distorto venga rilevato come tale.α<1α

Supponendo di disporre di dati sufficienti, un approccio migliore è calcolare per ciascun campione, quindi rimuovere tutti i campioni dal set di addestramento in cui questa probabilità supera una determinata soglia. Ad esempio, se è possibile addestrare il tuo set di dati solo sui campioni per i quali e il tuo set di dati diminuisce da distorto e imparziale a distorto e imparziale, e il bias si moltiplicherà per un fattore . Poiché in genere sarà molto più basso di , sarà molto più piccolo diP(Z=Bioun'Sed|X,Y)P(Z=Bioun'Sed|X,Y)<0.01NMnmf=n(N+M)N(n+m)nNmMf1, con un conseguente miglioramento significativo.

Si noti che entrambe le tecniche possono essere combinate: le righe con escono (per una scelta di , sopra ho usato ) e le righe che rimangono in ottenere un peso , che in realtà dovrebbe darti il ​​meglio di entrambi i mondi.p=P(Z=Bioun'Sed|X,Y)>βββ=0.01(1-pβ)2


Concordo sul fatto che la regressione ponderata generalmente non produrrà stime imparziali a meno che il classificatore non sia preciso al 100%. È garantito per ridurre la distorsione? Il tuo approccio di cutoff è necessariamente migliore o dipende dalle dimensioni del campione e dalla precisione del classificatore?
Adrian,

Non proprio la precisione del classificatore, soprattutto la quantità risultante di righe è importante, poiché per set di dati molto piccoli a volte non è possibile scartare un numero elevato di righe. Ma dato un numero sufficiente di dati non vedo motivo di dubitare: il tuo approccio pesa le righe con il 50% di probabilità di errore pari alla metà rispetto alle righe con lo 0% di probabilità di errore. Personalmente, non lo farei mai, preferirei vivamente 1000 file pulite garantite su 2000 file che hanno ciascuna il 50% di probabilità di distorsione. Nota che puoi anche combinare entrambi gli approcci, per applicare un sistema più graduale di un semplice taglio, ho aggiornato la mia risposta per approfondire questo.
user1111929,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.