sklearn的LogisticRegression中的predict_proba()函数在使用sample_weight参数时给出了错误的预测结果。

3
我正在尝试使用SciKit Learn。我想尝试一下加权逻辑回归,但是当我使用sample_weight参数初始化LogisticRegression对象时,我得到了无意义的预测结果。
以下是一个玩具示例,用来演示这个问题。我设置了一个非常简单的数据集,有一个特征和一个二元目标输出。
feat  target  weight
A       0       1
A       0       1
A       1       1
A       1       1
B       0       1
B       0       1
B       0       1
B       1       W

因此,任何明智的逻辑回归都应该预测当feat=A时,成功的概率为0.5。当feat=B时,概率取决于权重W如果W=1,那么看起来成功的机会是0.25;如果W=3,这会平衡三个0,看起来成功的机会是0.5;如果W=9,现在有效地有九个1和三个0,所以成功的机会是0.75。

R中进行加权逻辑回归可以给出正确的预测:

test <- function(final_weight) {
  feat   <- c('A','A','A','A','B','B','B','B')
  target <- c(0, 0, 1, 1, 0, 0, 0, 1)
  weight <- c(1, 1, 1, 1, 1, 1, 1, final_weight)

  df = data.frame(feat, target, weight)

  m = glm(target ~ feat, data=df, family='binomial', weights=weight)
  predict(m, type='response')
}

test(1)
#   1    2    3    4    5    6    7    8 
#0.50 0.50 0.50 0.50 0.25 0.25 0.25 0.25 
test(3)
#  1   2   3   4   5   6   7   8 
#0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 
test(9)
#   1    2    3    4    5    6    7    8 
#0.50 0.50 0.50 0.50 0.75 0.75 0.75 0.75 

很好。 但是 在SciKit Learn中,使用LogisticRegression对象时,当使用W=9时,我得到了不合理的预测结果。以下是我的Python代码:

import pandas as pd
from sklearn.linear_model import LogisticRegression
from patsy import dmatrices

def test(final_weight):
    d = {
        'feat'   : ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B'],
        'target' : [0, 0, 1, 1, 0, 0, 0, 1],
        'weight' : [1, 1, 1, 1, 1, 1, 1, final_weight],
    }
    df = pd.DataFrame(d)
    print df, '\n'

    y, X = dmatrices('target ~ feat', df, return_type="dataframe")
    features = X.columns

    C = 1e10 # high value to prevent regularization
    solver = 'sag' # so we can use sample_weight
    lr = LogisticRegression(C=C, solver=solver)
    lr.fit(X, df.target, sample_weight=df.weight)

    print 'Predictions:', '\n', lr.predict_proba(X), '\n', '===='


test(1)
test(3)
test(9)

这将产生以下输出(我删除了一些内容,使其更简洁):
  feat  target  weight
...
4    B       0       1
5    B       0       1
6    B       0       1
7    B       1       1

Predictions:
[[ 0.50000091  0.49999909]
...
 [ 0.74997935  0.25002065]]
====
  feat  target  weight
...
4    B       0       1
5    B       0       1
6    B       0       1
7    B       1       3

/usr/local/lib/python2.7/dist-packages/sklearn/linear_model/sag.py:267: ConvergenceWarning: The max_iter was reached which means the coef_ did not converge
Predictions:
[[ 0.49939191  0.50060809]
...
 [ 0.49967407  0.50032593]]
====
  feat  target  weight
...
4    B       0       1
5    B       0       1
6    B       0       1
7    B       1       9

Predictions:
[[ 0.00002912  0.99997088]   # Nonsense predictions for A!
...
 [ 0.00000034  0.99999966]]  # And for B too...
====

您可以看到,当我将最终权重设为9时(这似乎不是一个不合理的高权重),预测失败了!不仅feat=B的预测荒谬,而且feat=A的预测现在也变得荒谬。

我的问题是:

  • 为什么当最终权重为9时,这些预测会出现如此错误?

我是否做错或误解了什么?

更一般地说,如果有人成功使用了SciKit Learn中的加权逻辑回归,并实现了与R的glm(..., family='binomial')函数相似的预测结果,那么我会非常感兴趣。

非常感谢您提前提供任何帮助。

1个回答

3

看起来问题出在求解器上:

solver = 'sag' 

使用随机求解器在训练集具有iid假设的大型数据集中很常见。但是在样本权重较高的情况下效果不佳。

将求解器更改为lbfgs后,结果与您在R中看到的结果相匹配。

solver = 'lbfgs' 

1
David,非常感谢!这似乎完美地解决了问题。由于某种原因,我一直认为只有“sag”求解器可以与sample_weight一起使用,但事实并非如此。 - Gareth Williams

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接