19

我正在尝试使用 vowpal wabbit 进行逻辑回归。我不确定这是否是正确的语法

For training, I do

 ./vw -d ~/Desktop/new_data.txt --passes 20 --binary --cache_file cache.txt -f lr.vw --loss_function logistic --l1 0.05

For testing I do 
./vw -d ~/libsvm-3.18_test/matlab/new_data_test.txt --binary -t -i lr.vw -p predictions.txt -r raw_score.txt

这是我的火车数据中的一个片段

-1:1.00038 | 110:0.30103 262:0.90309 689:1.20412 1103:0.477121 1286:1.5563 2663:0.30103 2667:0.30103 2715:4.63112 3012:0.30103 3113:8.38411 3119:4.62325 3382:1.07918 3666:1.20412 3728:5.14959 4029:0.30103 4596:0.30103

1:2601.25 | 32:2.03342 135:3.77379 146:3.19535 284:2.5563 408:0.30103 542:3.80618 669:1.07918 689:2.25527 880:0.30103 915:1.98227 1169:5.35371 1270:0.90309 1425:0.30103 1621:0.30103 1682:0.30103 1736:3.98227 1770:0.60206 1861:4.34341 1900:3.43136 1905:7.54141 1991:5.33791 2437:0.954243 2532:2.68664 3370:2.90309 3497:0.30103 3546:0.30103 3733:0.30103 3963:0.90309 4152:3.23754 4205:1.68124 4228:0.90309 4257:1.07918 4456:0.954243 4483:0.30103 4766:0.30103

这是我的测试数据中的一个片段

-1 | 110:0.90309 146:1.64345 543:0.30103 689:0.30103 1103:0.477121 1203:0.30103 1286:2.82737 1892:0.30103 2271:0.30103 2715:4.30449 3012:0.30103 3113:7.99039 3119:4.08814 3382:1.68124 3666:0.60206 3728:5.154 3960:0.778151 4309:0.30103 4596:0.30103 4648:0.477121

但是,如果我查看结果,预测都是 -1,原始分数都是 0。我有大约 200,000 个示例,其中 100 个为 +1,其余为 -1。为了处理这种不平衡的数据,我给出了 200,000/100 的正例权重和 200,000/(200000-100) 的负例权重。是不是因为我的数据非常不平衡,即使我调整了正在发生的权重?

我期待原始分数文件中的 (P(y|x)) 输出。但我全是零。我只需要概率输出。有什么建议吗?

4

2 回答 2

52

一个类似的问题发布在大众邮件列表上。为了未来用户的利益,我将尝试在此处总结所有回复中的要点。

不平衡训练集最佳实践:

您的训练集高度不平衡(200,000 到 100)。这意味着只有 0.0005 (0.05%) 个示例的标签为1。通过始终预测-1,分类器的准确率达到了 99.95%。换句话说,如果假阳性的代价等于假阴性的代价,这实际上是一个优秀的分类器。如果你正在寻找一个等权重的结果,你需要做两件事:

  • 重新权衡您的示例,以便较小的组与较大的组具有相同的权重
  • 重新排序/打乱示例,使正面和负面混合在一起。

第二点在学习率随时间衰减的在线学习中尤为重要。因此,假设您可以自由地重新排序(例如,示例之间没有时间依赖性),理想的顺序是完全统一的 shuffle(1, -1, 1, -1, ...)

另请注意,示例权重的语法(假设流行率为 2000:1)需要类似于以下内容:

    1   2000  optional-tag| features ...
    -1  1     optional-tag| features ...

如上所述,将单个2000加权示例分解为仅具有12000 次的权重,并将其与 2000 个常见示例(带有-1标签的示例)交错:

   1  | ...
   -1 | ...
   1  | ...  # repeated, very rare, example
   -1 | ...
   1  | ...  # repeated, very rare, example

应该在更平滑的收敛和更低的训练损失方面带来更好的结果。*警告:作为一般规则,重复任何示例太多,例如在 1:2000 比率的情况下,很可能导致过度拟合重复的类。您可能想通过较慢的学习(使用--learning_rate ...)和/或随机重采样来解决这个问题:(使用--bootstrap ...

考虑对流行类进行下采样

为避免过度拟合:与其将稀有类的权重增加 2000 倍,不如考虑采取相反的方式,通过丢弃大部分示例来“减低”更常见的类。虽然这听起来可能令人惊讶(丢弃完全好的数据怎么会有好处?)它会避免如上所述的重复类的过度拟合,并且实际上可能会导致更好的泛化。根据情况和错误分类的成本,最佳下采样因子可能会有所不同(在这种情况下不一定是 1/2000,但可能在 1 到 1/2000 之间)。另一种需要一些编程的方法是使用主动学习:在非常小的部分数据上进行训练,然后在不学习的情况下继续预测类别(-t或零权重);如果该类是流行类并且-1在线分类器对结果非常肯定(预测值极端,或者使用时非常接近--link glf1),把多余的例子扔掉。IOW:只把你的训练集中在边界情况上


使用--binary(取决于您的需要)

--binary输出预测的符号(并相应地计算渐进损失)。如果您想要概率,请不要使用--binary和管道vw预测输出到utl/logistic(在源代码树中)。 utl/logistic将原始预测映射到范围内的有符号概率[-1, +1]

的影响之一--binary是误导(乐观)损失。将预测限制在 {-1, +1} 可以显着提高表观准确度,因为每个正确的预测都有 0.0 的损失。这可能会产生误导,因为--binary经常添加会使模型看起来比不添加更准确(有时非常准确)--binary

更新(2014 年 9 月):最近添加了一个新选项vw--link logistic它在内部实现[0,1]映射,同时进行预测vw。同样,--link glf1实现更常用的[-1, 1]映射。助记符:glf1代表“具有[-1, 1]范围的广义逻辑函数”

轻松--l1一点--l2

使用高--l1和/或--l2值是一个常见的错误。每个示例直接使用这些值,而不是相对于1.0. 更准确地说: in vw:l1l2直接应用于每个示例中的梯度总和(或“规范”)。尝试使用低得多的值,例如--l1 1e-8. utl/vw-hypersearch可以帮助您找到各种超参数的最佳值。

小心多次通过

--passes 20为了最大限度地减少训练错误,这是一个常见的错误。请记住,目标是最小化泛化误差而不是训练误差。即使有很酷的添加holdout(感谢Zhen Qin),vw当错误停止下降时自动提前终止自动保留数据(默认情况下每10个示例被保留),多次传递最终将开始过度拟合保留的数据(“没有免费的午餐”原则)。

于 2014-07-08T21:00:32.703 回答
18

arielf总结了详细的答案。

  1. 重要的是要知道预期的最终成本(损失)函数是什么:逻辑损失、0/1 损失(即准确性)、F1 分数、RO 曲线下的面积,还有其他什么?

  2. 这是 arielf 部分答案的 Bash 代码。请注意,我们应该首先从 train.txt 中删除重要性加权的奇怪尝试(我的意思是问题中的“: 1.​​00038”和“: 2601.25 ”)。

    A. Prepare the training data
    grep '^-1' train.txt | shuf > neg.txt
    grep '^1' train.txt | shuf > p.txt
    for i in `seq 2000`; do cat p.txt; done > pos.txt
    paste -d '\n' neg.txt pos.txt > newtrain.txt
    
    B. Train model.vw
    # Note that passes=1 is the default.
    # With one pass, holdout_off is the default.
    `vw -d newtrain.txt --loss_function=logistic -f model.vw`
    #average loss = 0.0953586
    
    C. Compute test loss using vw
    `vw -d test.txt -t -i model.vw --loss_function=logistic -r   
    raw_predictions.txt`
    #average loss = 0.0649306
    
    D. Compute AUROC using http://osmot.cs.cornell.edu/kddcup/software.html
    cut -d ' ' -f 1 test.txt | sed -e 's/^-1/0/' > gold.txt
    $VW_HOME/utl/logistic -0 raw_predictions.txt > probabilities.txt
    perf -ROC -files gold.txt probabilities.txt 
    #ROC    0.83484
    perf -ROC -plot roc -files gold.txt probabilities.txt | head -n -2 > graph
    echo 'plot "graph"' | gnuplot -persist
    
于 2014-07-09T16:24:17.747 回答