Como simular dados artificiais para regressão logística?

45

Sei que estou perdendo algo no meu entendimento da regressão logística e realmente aprecio qualquer ajuda.

Pelo que entendi, a regressão logística pressupõe que a probabilidade de um resultado '1' dado os insumos seja uma combinação linear dos insumos passados ​​por uma função de logística inversa. Isso é exemplificado no seguinte código R:

#create data:
x1 = rnorm(1000)           # some continuous variables 
x2 = rnorm(1000)
z = 1 + 2*x1 + 3*x2        # linear combination with a bias
pr = 1/(1+exp(-z))         # pass through an inv-logit function
y = pr > 0.5               # take as '1' if probability > 0.5

#now feed it to glm:
df = data.frame(y=y,x1=x1,x2=x2)
glm =glm( y~x1+x2,data=df,family="binomial")

e recebo a seguinte mensagem de erro:

Mensagens de aviso: 1: glm.fit: o algoritmo não convergeu 2: glm.fit: probabilidades ajustadas numericamente 0 ou 1 ocorreu

Eu trabalho com R há algum tempo; o suficiente para saber que provavelmente eu sou o culpado .. o que está acontecendo aqui?

zorbar
fonte
2
A maneira como você simula seus dados me parece estranha. Se desejar, para uma maneira alternativa mais padrão, você pode dar uma olhada aqui: stats.stackexchange.com/questions/12857/…
ocram
@ram: você está certo; esta é uma pergunta duplicada!
user603
2
Fiz uma simulação errada, como @ Stéphane Laurent explicou. No entanto, o problema era a separação perfeita na regressão logística , um problema que eu não conhecia e que me surpreendeu bastante ao saber disso.
Zorbar 26/12/12
@ zorbar: foi na minha resposta à sua pergunta (agora excluída).
user603
1
@ user603: provavelmente perdi sua resposta; Obrigado de qualquer forma
zorbar

Respostas:

63

Não. A variável de resposta é uma variável aleatória de Bernoulli, assumindo o valor com probabilidade . 1 p r ( i )yi1pr(i)

> set.seed(666)
> x1 = rnorm(1000)           # some continuous variables 
> x2 = rnorm(1000)
> z = 1 + 2*x1 + 3*x2        # linear combination with a bias
> pr = 1/(1+exp(-z))         # pass through an inv-logit function
> y = rbinom(1000,1,pr)      # bernoulli response variable
> 
> #now feed it to glm:
> df = data.frame(y=y,x1=x1,x2=x2)
> glm( y~x1+x2,data=df,family="binomial")

Call:  glm(formula = y ~ x1 + x2, family = "binomial", data = df)

Coefficients:
(Intercept)           x1           x2  
     0.9915       2.2731       3.1853  

Degrees of Freedom: 999 Total (i.e. Null);  997 Residual
Null Deviance:      1355 
Residual Deviance: 582.9        AIC: 588.9 
Stéphane Laurent
fonte
Você está certo - eu perdi esta etapa. Muito obrigado por sua ajuda!
Zorbar 25/12/12
1
Eu tive uma pergunta sobre a maneira como você simula dados. Quando simulamos dados para regressão linear, também simulamos um ruído (\ epsilon). Entendo que a função logística é uma função da expectativa que, por si só, cancela o ruído. É por isso que você não tem nenhum ruído no seu z?
Sam
5
A regressão linear @Sepehr assume uma distribuição gaussiana. O "ruído" é apenas uma interpretação da variabilidade em torno da média, mas não é um ruído adicionado à resposta: a resposta é escrita como , é apenas uma interpretação. A regressão logística assume que a resposta tem uma distribuição binomial e, da mesma forma, não há ruído adicionado à resposta. mean response+noise
Stéphane Laurent
@ StéphaneLaurent, exatamente. Eu entendo completamente. Muito obrigado pela sua resposta.
Sam
2

LogisticRegression é adequado para ajuste se probabilidades ou proporções forem fornecidas como metas, não apenas resultados de 1/1.

import numpy as np
import pandas as pd
def logistic(x, b, noise=None):
    L = x.T.dot(b)
    if noise is not None:
        L = L+noise
    return 1/(1+np.exp(-L))

x = np.arange(-10., 10, 0.05)
bias = np.ones(len(x))
X = np.vstack([x,bias]) # Add intercept
B =  [1., 1.] # Sigmoid params for X

# True mean
p = logistic(X, B)
# Noisy mean
pnoisy = logistic(X, B, noise=np.random.normal(loc=0., scale=1., size=len(x)))
# dichotomize pnoisy -- sample 0/1 with probability pnoisy
dichot = np.random.binomial(1., pnoisy)

pd.Series(p, index=x).plot(style='-')
pd.Series(pnoisy, index=x).plot(style='.')
pd.Series(dichot, index=x).plot(style='.')

Aqui temos três alvos em potencial para a regressão logística. pqual é a proporção / probabilidade verdadeira / alvo, pnoisyque é p com ruído normal adicionado na escala de probabilidades de log e dichotque é tratado como um parâmetro no PDF binomial e amostrado a partir disso. Você deve testar todos os 3 - eu achei que algumas implementações de código aberto de LR não se encaixam p.

Dependendo da sua aplicação, você pode preferir fazer xixi.

Na prática, você também deve considerar como é provável que o ruído seja moldado no aplicativo de destino e tentar imitar isso.

user48956
fonte