2016-09-16 3 views
-1

J'ai un modèle lm dans R que j'ai formé et sérialisé. A l'intérieur d'une fonction, où je passe en entrée le modèle et un vecteur caractéristique (un seul tableau), j'ai:Modèle linéaire R (lm) prédire la fonction avec un seul tableau

CREATE OR REPLACE FUNCTION lm_predict(
    feat_vec float[], 
    model bytea 
) 
RETURNS float 
AS 
$$ 
    #R-code goes here. 
    mdl <- unserialize(model) 
    # class(feat_vec) outputs "array" 
    y_hat <- predict.lm(mdl, newdata = as.data.frame.list(feat_vec)) 
    return (y_hat) 
$$ LANGUAGE 'plr'; 

Cela retourne le mauvais y_hat !! Je sais cela parce que cette autre solution fonctionne (les entrées de cette fonction sont toujours le modèle (dans un bytearray) et un feat_vec (tableau)):

CREATE OR REPLACE FUNCTION lm_predict(
    feat_vec float[], 
    model bytea 
) 
RETURNS float 
AS 
$$ 
    #R-code goes here. 
    mdl <- unserialize(model) 
    coef = mdl$coefficients 
    y_hat = coef[1] + as.numeric(coef[-1]%*%feat_vec) 
    return (y_hat) 
$$ LANGUAGE 'plr'; 

Qu'est-ce que je fais mal ?? C'est le même modèle non sérialisé, la première option devrait me donner la bonne réponse aussi ...

+0

Est-ce code R? Cela ressemble à demi python; les deux-points ne fonctionnent pas de cette façon dans R, ni 'return' ou' + '. – alistaire

+0

Oui, il est R + pseudocode - vous pouvez ignorer la déclaration de la fonction En fait - c'est dans une fonction PL/R dans Postgres mais je ne voulais pas mettre l'accent sur Postgres – strv7

+0

... alors comment le pseudocode retourne un résultat , correct ou pas? – alistaire

Répondre

1

Le problème semble être l'utilisation de newdata = as.data.frame.list(feat_vec). Comme discuté dans votre previous question, cela renvoie des noms de colonne laids. Lorsque vous appelez predict, newdata doit avoir des noms de colonne cohérents avec les noms covariants dans votre formule de modèle. Vous devriez recevoir un message d'avertissement lorsque vous appelez .

## example data 
set.seed(0) 
x1 <- runif(20) 
x2 <- rnorm(20) 
y <- 0.3 * x1 + 0.7 * x2 + rnorm(20, sd = 0.1) 

## linear model 
model <- lm(y ~ x1 + x2) 

## new data 
feat_vec <- c(0.4, 0.6) 
newdat <- as.data.frame.list(feat_vec) 
# X0.4 X0.6 
#1 0.4 0.6 

## prediction 
y_hat <- predict.lm(model, newdata = newdat) 
#Warning message: 
#'newdata' had 1 row but variables found have 20 rows 

Qu'est-ce que vous avez besoin est

newdat <- as.data.frame.list(feat_vec, 
          col.names = attr(model$terms, "term.labels")) 
# x1 x2 
#1 0.4 0.6 

y_hat <- predict.lm(model, newdata = newdat) 
#  1 
#0.5192413 

Ceci est la même chose que ce que vous pouvez calculer manuellement:

coef = model$coefficients 
unname(coef[1] + sum(coef[-1] * feat_vec)) 
#[1] 0.5192413 
+0

Je ne reçois pas de messages d'avertissement lors de l'appel R de Postgres ... Mais quelque chose ne va pas – strv7

+0

merci pour votre réponse. J'apprécie vraiment cela. Cela ne fonctionne toujours pas pour moi, y_qui retourne toujours le même résultat alors que le calcul "manuel" renvoie des prédictions correctes. Je ne comprends pas pourquoi:/ Pourquoi dois-je inclure les col.names ?? Est-ce vraiment important? – strv7

+0

Cela a résolu mon problème lorsque vous travaillez avec randomForest ... merci! J'ai toujours le comportement bizarre avec lm mais heureux je l'ai eu pour travailler avec un autre modèle de régression et exactement le même code! – strv7