web-dev-qa-db-ja.com

非常に不均衡なデータセットでvowpalwabbitを使用してロジスティック回帰を実行する方法

ロジスティック回帰にvowpalwabbitを使用しようとしています。これが正しい構文かどうかはわかりません

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))の出力を期待していました。しかし、私はすべてゼロになります。確率出力が必要です。みんな何が起こっているのか提案はありますか?

19
user34790

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
    
17
Martin Popel

同様の質問がvwメーリングリストに投稿されました。将来のユーザーのために、ここですべての回答の要点を要約しようと思います。

不均衡なトレーニングはベストプラクティスを設定します:

トレーニングセットは非常にアンバランスです(200,000から100)。これは、例の0.0005(0.05%)のみが1のラベルを持っていることを意味します。常に-1を予測することにより、分類器は99.95%という驚くべき精度を達成します。言い換えると、誤検知のコストが誤検知のコストと等しい場合、これは実際には優れた分類子です。等しい重みの結果を探している場合は、次の2つのことを行う必要があります。

  • 小さいグループが大きいグループと同じ重みを持つように、例を再計量します。
  • ポジティブとネガティブが混ざり合うように、例を並べ替え/シャッフルします。

2番目のポイントは、学習率が時間とともに低下するオンライン学習では特に重要です。したがって、オンライン学習の理想的な順序は、自由に並べ替えることができると仮定すると(たとえば、例間の時間依存性がない場合)、完全に均一なシャッフルです(1, -1, 1, -1, ...)

また、example-weightsの構文(有病率が2000:1であると想定)は、次のようにする必要があることに注意してください。

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

そして、前述のように、単一の2000加重例を分割して1の加重のみにし、2000回繰り返し、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の間のどこかになります)。プログラミングが必要なもう1つのアプローチは、能動学習を使用することです。データのごく一部でトレーニングを行い、学習せずにクラスを予測し続けます(-tまたは重みなし)。クラスが一般的なクラスおよびである場合、オンライン分類子は結果を非常に確実です(予測値が極端であるか、-1に非常に近い) --link glf1)を使用する場合は、冗長な例を破棄してください。 IOW:境界の場合のみにトレーニングを集中させます


--binaryの使用(必要に応じて)

--binaryは予測の符号を出力します(それに応じて漸進的損失を計算します)。確率が必要な場合は、not--binaryを使用し、vw予測出力をutl/logisticにパイプします(ソースツリー)。 utl/logisticは、生の予測を[-1, +1]の範囲の符号付き確率にマッピングします。

--binaryの影響の1つは、誤解を招く(楽観的な)損失です。予測を{-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に関連するのではなく、例ごとに直接使用されます。より正確には:vwl1l2は、勾配の合計(または各例の「標準」)。 --l1 1e-8のようにもっと低い値を使用してみてください。 utl/vw-hypersearchは、さまざまなハイパーパラメータの最適値を見つけるのに役立ちます。

複数のパスに注意してください

トレーニングエラーを最小限に抑えるために--passes 20を使用することはよくある間違いです。目標は、トレーニングエラーではなく、汎化エラーを最小限に抑えることであることを忘れないでください。 holdoutのクールな追加(Zhen Qinのおかげで)があっても、vwは、自動的に保持されたデータでエラーが発生しなくなると自動的に早期終了します(デフォルトでは10番目ごとの例が保持されています-アウト)、複数のパスが最終的に保持されたデータに適合し始めます(「無料ランチなし」の原則)。

48
arielf