predict.lm() in a loop. warning: prediction from a rank-deficient fit may be misleading

前端 未结 3 907
一向
一向 2020-12-04 21:41

This R code throws a warning

# Fit regression model to each cluster
y <- list() 
length(y) <- k
vars <- list() 
length(vars) <- k
f <- list()
         


        
相关标签:
3条回答
  • 2020-12-04 22:22

    This warning:

    In predict.lm(model, test) :
      prediction from a rank-deficient fit may be misleading
    

    Gets thrown from R's predict.lm. See: http://stat.ethz.ch/R-manual/R-devel/library/stats/html/predict.lm.html

    Understand rank deficiency: Ask R to tell you the rank of a matrix:

    train <- data.frame(y=c(1234, 325, 152, 403), 
                       x1=c(3538, 324, 382, 335), 
                       x2=c(2985, 323, 223, 288), 
                       x3=c(8750, 322, 123, 935))
    test <- data.frame(x1=c(3538, 324, 382, 335), 
                       x2=c(2985, 323, 223, 288), 
                       x3=c(8750, 322, 123, 935))
    library(Matrix)
    cat(rankMatrix(train), "\n")   #prints 4
    cat(rankMatrix(test), "\n")    #prints 3
    

    A matrix that does not have "full rank" is said to be "rank deficient". A matrix is said to have full rank if its rank is either equal to its number of columns or to its number of rows (or to both).

    The problem is that predict.lm will throw this warning even if your matrices are full rank (not rank deficient) because predict.lm pulls a fast one under the hood, by throwing out what it considers useless features, modifying your full rank input to be rank-deficient. It then complains about it through a warning.

    Also this warning seems to be a catch-all for other situations like for example you have too many input features and your data density is too sparse and it's offering up it's opinion that predictions are brittle.

    Example of passing full rank matrices, yet predict.lm still complains of rank deficiency

    train <- data.frame(y=c(1,2,3,4),
                            x1=c(1,1,2,3),
                            x2=c(3,4,5,2),
                            x3=c(4,2,6,0),
                            x4=c(2,1,3,0)
                       )
    test <- data.frame(x1=c(1, 2,  3,  9),
                       x2=c(3, 5,  1, 15),
                       x3=c(5, 9,  5, 22),
                       x4=c(9, 13, 2, 99))
    library(Matrix)
    cat(rankMatrix(train), "\n")    #prints 4, is full rank, good to go
    cat(rankMatrix(test), "\n")     #prints 4, is full rank, good to go
    myformula = as.formula("y ~ x1+x2+x3+x4")
    model <- lm(myformula, train)
    predict(model, test) 
        #Warning: prediction from a rank-deficient fit may be misleading
    

    workaround:

    Assuming predict is returning good predictions, you can ignore the warning. predict.lm offers up it's opinion given insufficient perspective and here you are.

    So disable warnings on the predict step like this:

    options(warn=-1)      #turn off warnings
    predict(model, test)
    options(warn=1)      #turn warnings back on
    
    0 讨论(0)
  • 2020-12-04 22:24

    You can inspect the predict function with body(predict.lm). There you will see this line:

    if (p < ncol(X) && !(missing(newdata) || is.null(newdata))) 
        warning("prediction from a rank-deficient fit may be misleading")
    

    This warning checks if the rank of your data matrix is at least equal to the number of parameters you want to fit. One way to invoke it is having some collinear covariates:

    data <- data.frame(y=c(1,2,3,4), x1=c(1,1,2,3), x2=c(3,4,5,2), x3=c(4,2,6,0), x4=c(2,1,3,0))
    data2 <- data.frame(x1=c(3,2,1,3), x2=c(3,2,1,4), x3=c(3,4,5,1), x4=c(0,0,2,3))
    fit <- lm(y ~ ., data=data)
    
    predict(fit, data2)
           1        2        3        4 
    4.076087 2.826087 1.576087 4.065217 
    Warning message:
    In predict.lm(fit, data2) :
      prediction from a rank-deficient fit may be misleading
    

    Notice that x3 and x4 have the same direction in data. One is the multiple of the other. This can be checked with length(fit$coefficients) > fit$rank

    Another way is having more parameters than available variables:

    fit2 <- lm(y ~ x1*x2*x3*x4, data=data)
    predict(fit2, data2)
    Warning message:
    In predict.lm(fit2, data2) :
      prediction from a rank-deficient fit may be misleading
    
    0 讨论(0)
  • 2020-12-04 22:43

    It is because, one of your dependent variables has NA for Coefficients given as output by the lm(..) function. Such a variable is making no difference to the model, often due to multicollinearity problem ie, that predictor variable is linearly dependent on other predictor variables OR because, that predictor variable is constant for all the records(rows). The best thing to do is to drop that variable from the formula in lm(..) function and do the regression again. This does not reduce the accuracy of the model. In my case,

    model <- lm(Happiness.Score ~ Economy..GDP.per.Capita.+year+Health..Life.Expectancy., data=dfTrain)
    
    > model
    Call:
    lm(formula = Happiness.Score ~ Economy..GDP.per.Capita. + year + 
        Health..Life.Expectancy., data = dfTrain)
    
    Coefficients:
                 (Intercept)  Economy..GDP.per.Capita.                      year  
                       3.036                     1.569                        NA  
    Health..Life.Expectancy.  
                       1.559
    

    variable year has the same value for all records. After removing year variable

    model <- lm(Happiness.Score ~ Economy..GDP.per.Capita.+Health..Life.Expectancy., data=dfTrain)
    
    preds <- predict.lm(model, dfTest[, c(1:nrow(dfTest)-1]))
    

    This gives no warning message

    0 讨论(0)
提交回复
热议问题