Python与R之间线性回归系数的差异

Niz*_*zag 12 python regression r pandas scikit-learn

我正在尝试在Python中运行我已经在R中完成的线性回归,以便找到具有0个系数的变量.我遇到的问题是R中的线性回归为具有低方差的列返回NAs,而scikit learn regression返回系数.在R代码中,我通过保存带有NAs的变量作为线性回归的输出来查找并保存这些变量,但我似乎无法找到在python中模仿这种行为的方法.我正在使用的代码可以在下面找到.

R代码:

a <- c(23, 45, 546, 42, 68, 15, 47)
b <- c(1, 2, 4, 6, 34, 2, 8)
c <- c(22, 33, 44, 55, 66, 77, 88)
d <- c(1, 1, 1, 1, 1, 1, 1)
e <- c(1, 1, 1, 1, 1, 1, 1.1)
f <- c(1, 1, 1, 1, 1, 1, 1.01)
g <- c(1, 1, 1, 1, 1, 1, 1.001)

df <- data.frame(a, b, c, d, e, f, g)
var_list = c('b', 'c', 'd', 'e', 'f', 'g')

target <- temp_dsin.df$a
reg_data <- cbind(target, df[, var_list])


if (nrow(reg_data) < length(var_list)){
  message(paste0('    WARNING: Data set is rank deficient. Result may be doubtful'))
}
reg_model <- lm(target ~ ., data = reg_data)

print(reg_model$coefficients)

#store the independent variables with 0 coefficients
zero_coef_IndepVars.v <- names(which(is.na(reg_model$coefficients)))

print(zero_coef_IndepVars.v)
Run Code Online (Sandbox Code Playgroud)

Python代码:

import pandas as pd
from sklearn import linear_model

a = [23, 45, 546, 42, 68, 15, 47]
b = [1, 2, 4, 6, 34, 2, 8]
c = [22, 33, 44, 55, 66, 77, 88]
d = [1, 1, 1, 1, 1, 1, 1]
e = [1, 1, 1, 1, 1, 1, 1.1]
q = [1, 1, 1, 1, 1, 1, 1.01]
f = [1, 1, 1, 1, 1, 1, 1.001]


df = pd.DataFrame({'a': a,
                             'b': b,
                             'c': c,
                             'd': d,
                             'e': e,
                             'f': q,
                             'g': f})


var_list = ['b', 'c', 'd', 'e', 'f', 'g']

# build linear regression model and test for linear combination
target = df['a']
reg_data = pd.DataFrame()
reg_data['a'] = target
train_cols = df.loc[:,df.columns.str.lower().isin(var_list)]


if reg_data.shape[0] < len(var_list):
    print('    WARNING: Data set is rank deficient. Result may be doubtful')

# Create linear regression object
reg_model = linear_model.LinearRegression()

# Train the model using the training sets
reg_model.fit(train_cols , reg_data['a'])

print(reg_model.coef_)
Run Code Online (Sandbox Code Playgroud)

R的输出:

(Intercept)           b           c           d           e           f           g 
 537.555988   -0.669253   -1.054719          NA -356.715149          NA          NA 

> print(zero_coef_IndepVars.v)
[1] "d" "f" "g"
Run Code Online (Sandbox Code Playgroud)

Python的输出:

           b             c   d               e              f            g
[-0.66925301   -1.05471932   0.   -353.1483504   -35.31483504   -3.5314835]
Run Code Online (Sandbox Code Playgroud)

如您所见,"b","c"和"e"列的值很接近,但"d","f"和"g"的值非常不同.对于这个示例回归,我想返回['d','f','g'],因为它们的输出是来自R的NA.问题是sklearn线性回归为col'd'返回0,而它返回col'f'为-35.31,col'g'为-3.531.

有谁知道R如何决定是否返回NA或值/如何在Python版本中实现此行为?知道差异源于何处可能有助于我在python中实现R行为.我需要python脚本的结果来准确匹配R输出.

Jor*_*eys 18

这是实施方面的差异.lm在R中使用基于QR分解的底层C代码.模型矩阵被分解为正交矩阵Q和三角矩阵R.这导致其他人称为"检查共线性".R没有检查,QR分解的性质确保最小共线变量在拟合算法中变得"优先".

有关线性回归上下文中QR分解的更多信息:https: //www.stat.wisc.edu/~larget/math496/qr.html

来自sklearn的代码基本上是一个包装器numpy.linalg.lstsq,它最小化了欧几里德二次范数.如果您的模型是Y = AX,它最小化||Y - AX||^2.这是一种不同的(并且计算上不太稳定)算法,并且它没有QR分解的良好副作用.

个人注意事项:如果您希望在经过验证和测试的计算框架中对模型进行稳健拟合并坚持使用Python,请查找基于QR或SVD的线性回归实现.包裹scikit-learnstatsmodels(仍然在2017年4月22日的测试版中)应该可以帮助您.