我在R和Python上对鸢尾花数据集进行了逻辑回归分析,但两者的结果(系数、截距和得分)不同。
#Python代码。 In[23]: iris_df.head(5) Out[23]: Sepal.Length Sepal.Width Petal.Length Petal.Width Species 0 5.1 3.5 1.4 0.2 0 1 4.9 3.0 1.4 0.2 0 2 4.7 3.2 1.3 0.2 0 3 4.6 3.1 1.5 0.2 0 In[35]: iris_df.shape Out[35]: (100, 5) #查看依赖变量Species的水平.. In[25]: iris_df['Species'].unique() Out[25]: array([0, 1], dtype=int64) #创建依赖和独立变量数据集.. x = iris_df.ix[:,0:4] y = iris_df.ix[:,-1] #开始建模.. y = np.ravel(y) logistic = LogisticRegression() model = logistic.fit(x,y) #获取模型系数.. model_coef= pd.DataFrame(list(zip(x.columns, np.transpose(model.coef_)))) model_intercept = model.intercept_ In[30]: model_coef Out[36]: 0 1 0 Sepal.Length [-0.402473917528] 1 Sepal.Width [-1.46382924771] 2 Petal.Length [2.23785647964] 3 Petal.Width [1.0000929404] In[31]: model_intercept Out[31]: array([-0.25906453]) #得分... In[34]: logistic.predict_proba(x) Out[34]: array([[ 0.9837306 , 0.0162694 ], [ 0.96407227, 0.03592773], [ 0.97647105, 0.02352895], [ 0.95654126, 0.04345874], [ 0.98534488, 0.01465512], [ 0.98086592, 0.01913408],
R代码。
> str(irisdf)'data.frame': 100 obs. of 5 variables: $ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ... $ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ... $ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ... $ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ... $ Species : int 0 0 0 0 0 0 0 0 0 0 ... > model <- glm(Species ~ ., data = irisdf, family = binomial)警告信息:1: glm.fit: 算法未收敛 2: glm.fit: 拟合概率数值为0或1 > summary(model)调用:glm(公式 = Species ~ ., family = binomial, data = irisdf)偏差残差: 最小值 第一四分位数 中位数 第三四分位数 最大值 -1.681e-05 -2.110e-08 0.000e+00 2.110e-08 2.006e-05 系数: 估计值 标准误差 z值 Pr(>|z|)(截距) 6.556 601950.324 0 1Sepal.Length -9.879 194223.245 0 1Sepal.Width -7.418 92924.451 0 1Petal.Length 19.054 144515.981 0 1Petal.Width 25.033 216058.936 0 1(二项分布家族的分散参数取为1) 空偏差: 1.3863e+02 自由度99残差偏差: 1.3166e-09 自由度95AIC: 10Fisher评分迭代次数: 25
由于收敛问题,我增加了最大迭代次数,并将epsilon设置为0.05。
> model <- glm(Species ~ ., data = irisdf, family = binomial,control = glm.control(epsilon=0.01,trace=FALSE,maxit = 100))> summary(model)调用:glm(公式 = Species ~ ., family = binomial, data = irisdf, control = glm.control(epsilon = 0.01, trace = FALSE, maxit = 100))偏差残差: 最小值 第一四分位数 中位数 第三四分位数 最大值 -0.0102793 -0.0005659 -0.0000052 0.0001438 0.0112531 系数: 估计值 标准误差 z值 Pr(>|z|)(截距) 1.796 704.352 0.003 0.998Sepal.Length -3.426 215.912 -0.016 0.987Sepal.Width -4.208 123.513 -0.034 0.973Petal.Length 7.615 159.478 0.048 0.962Petal.Width 11.835 285.938 0.041 0.967(二项分布家族的分散参数取为1) 空偏差: 1.3863e+02 自由度99残差偏差: 5.3910e-04 自由度95AIC: 10.001Fisher评分迭代次数: 12#R得分..> scores = predict(model, newdata = irisdf, type = "response")> head(scores,5) 1 2 3 4 5 2.844996e-08 4.627411e-07 1.848093e-07 1.818231e-06 2.631029e-08
R和Python中的得分、截距和系数完全不同。哪个是正确的?我想在Python中继续进行。现在我对哪个结果准确感到困惑。
回答:
更新问题是,在花瓣宽度变量上存在完美分离。换句话说,这个变量可以完美预测给定数据集中一个样本是setosa还是versicolor。这打破了R中逻辑回归使用的对数似然最大化估计。问题在于,通过将花瓣宽度的系数推向无穷大,可以使对数似然值变得非常高。
一些背景和策略在这里讨论。
在CrossValidated上也有一个很好的讨论策略的线程。
那么为什么sklearn的LogisticRegression有效呢?因为它采用了“正则化逻辑回归”。正则化会惩罚估计参数的大值。
在下面的例子中,我使用了logistf包中的Firth偏差减少方法的逻辑回归来生成一个收敛的模型。
library(logistf)iris = read.table("path_to _iris.txt", sep="\t", header=TRUE)iris$Species <- as.factor(iris$Species)sapply(iris, class)model1 <- glm(Species ~ ., data = irisdf, family = binomial)# 不收敛,会抛出警告。model2 <- logistf(Species ~ ., data = irisdf, family = binomial)# 收敛了。
原始根据R解决方案中的标准误差和z值,我认为你的模型规格有问题。接近0的z值基本上告诉你模型与依赖变量之间没有相关性。所以这是一个无意义的模型。
我的第一个想法是你需要将Species字段转换为分类变量。在你的例子中它是int
类型。尝试使用as.factor