Comment simuler des données artificielles pour une régression logistique?

45

Je sais que quelque chose me manque dans ma compréhension de la régression logistique et apprécierais vraiment toute aide.

Autant que je sache, la régression logistique suppose que la probabilité d'un résultat '1' compte tenu des entrées est une combinaison linéaire des entrées, passant par une fonction de logistique inverse. Ceci est illustré dans le code R suivant:

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

et j'obtiens le message d'erreur suivant:

Messages d'avertissement: 1: glm.fit: l'algorithme n'a pas convergé 2: glm.fit: probabilités ajustées numériquement égales à 0 ou 1

J'ai travaillé avec R pendant un certain temps maintenant; assez pour savoir que probablement je suis le seul à blâmer .. que se passe-t-il ici?

zorbar
la source
2
La façon dont vous simulez vos données me semble étrange. Si vous voulez, pour une alternative plus standard, vous pouvez jeter un oeil ici: stats.stackexchange.com/questions/12857/…
ocram
@ ocram: vous avez raison; C'est une question en double!
user603
2
J'ai fait une simulation erronée, comme @ Stéphane Laurent l'a expliqué. Cependant, le problème était la séparation parfaite dans la régression logistique , un problème que je ne connaissais pas et que j'étais plutôt surpris d'apprendre.
Zorbar
@zorbar: c'était dans ma réponse à votre question (maintenant supprimée).
user603
1
@ user603: J'ai probablement manqué votre réponse; Merci quand même
zorbar

Réponses:

63

La variable de réponse est une variable aléatoire de Bernoulli prenant la valeur avec une probabilité . 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
la source
Vous avez raison - j'ai raté cette étape. Merci beaucoup pour votre aide!
Zorbar
1
J'avais une question concernant la façon dont vous simulez les données. Lorsque nous simulons des données pour une régression linéaire, nous simulons également un bruit (\ epsilon). Je comprends que la fonction logistique est une fonction de l’attente qui annule à elle seule le bruit. Est-ce la raison pour laquelle vous n'avez pas de bruit dans votre z?
Sam
5
@Sepehr La régression linéaire suppose une distribution gaussienne. Le "bruit" est simplement une interprétation de la variabilité autour de la moyenne, mais ce n'est pas un bruit ajouté à la réponse: la réponse est écrite sous la forme , il ne s'agit que d'une interprétation. La régression logistique suppose que la réponse a une distribution binomiale et que, de même, aucun bruit n’a été ajouté à la réponse. mean response+noise
Stéphane Laurent
@ StéphaneLaurent, justement. Je comprends complètement. Merci beaucoup pour votre réponse.
Sam
2

LogisticRegression convient pour l’ajustement si des probabilités ou des proportions sont fournies comme cibles, et pas seulement des résultats 0/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='.')

Nous avons ici trois cibles potentielles pour la régression logistique. pqui est la proportion / probabilité vraie / cible, pnoisyqui est p avec le bruit normal ajouté dans l'échelle de cotes du journal, et dichotqui est traité comme un paramètre du PDF binomial et échantillonné à partir de celui-ci. Vous devriez tester les 3 - j'ai constaté que certaines implémentations de source ouverte en LR ne pouvaient pas convenir p.

En fonction de votre application, vous préférerez peut-être pnoisy.

En pratique, vous devez également prendre en compte la manière dont le bruit est susceptible de se former dans votre application cible et essayer de l'imiter.

utilisateur48956
la source