学習する天然ニューラルネット

主に機械学習に関する覚書や情報の整理。競プロ水色→Kaggle Master→?

Confident Learningは誤った教師から学習するか? ~ tf-idfのデータセットでノイズ生成から評価まで ~

概要

現実の判別問題において教師が完璧であることは珍しい。ラベリング作業において、知識不足や勘違いなどで引き起こされるヒューマンエラーはデータセットを汚染する。

このような間違った教師のことを、noisy label (corrupted label や polluted labelとも)という。誤った教師を用いると学習はうまく行かず判別性能は下がってしまう。近年ではこれに対処しようという研究が増えている。

ICML2020に Confident Learning: Estimating Uncertainty in Dataset Labels という論文が投稿された。しかも、よく整備された実装cleanlabまで提供されていた。

今回はRCV1-v2という文章をtf-idf(特徴量)にしたデータセットを用いて、Confident Learning (CL)が効果を発揮するのか実験を行った。またcleanlabを用いた実装を公開する。

結論としては、CLを用いると確かにnoisy labelなデータセットでも判別性能がよくなった。更にpseudo-labelingと組み合わせるともっと良くなるという結果が得られた。

目次

Confident Learning (CL)

ICML2020に投稿されたデータ中のnoisy labelを検出する枠組み。

[1911.00068] Confident Learning: Estimating Uncertainty in Dataset Labels

特徴としては以下のようなことが挙げられる。

  • どのような判別器も使用可
  • 他クラス分類対応
  • ハイパーパラメータがない (これは嬉しい。testも汚染されている状況ではチューニングなど無理なので)
  • 実装が公開済み

細かい仕組みについては、元論文か自分の解説ブログを参照してほしい。が、とりあえずCLを使うとデータ中のnoisy labelが検出できるんだな と把握しておけば問題ない。

aotamasaki.hatenablog.com

実装に関しては著者が公開済みでpip install cleanlabすることができる。

GitHub - cgnorthcutt/cleanlab: Find label errors in datasets, weak supervision, and learning with noisy labels.

実験計画

今回主に知りたいのは以下である。

  • 真のきれいなラベルで学習させたときの性能 (理想的な性能)
  • noisy labelを用いて学習させたときの性能 (baselineとなる性能)
  • そしてnoisy labelを用いてConfident Learningを適応したときの性能

CLは他のsemi-supervised learningのテクニックとも組み合わせて使えるので、pseudo-labelingとも組み合わせて計5つの実験を行った。

  1. ML:clean
  2. ML:noisy
  3. CL:without noises
  4. CL:pseudo for noises
  5. CL:pseudo for noises and test

これらについて、実験手順をイラストで説明する。

1. ML:clean

きれいなデータで学習するいつものやつ。 これは理想的な性能を示すための実験である。

データとか判別器はあとで説明するので、適当なものを今は思い浮かべてほしい。ただし図に示しているyは正しい(真の)ラベルである。

f:id:aotamasaki:20200404120339p:plain

2. ML:noisy

現実のデータセットの多くはnoisy labelである。それを再現するために人工的にノイズをy_trainに付与した。またy_trainは現実ではわからないため、y_train_noisyを用いて学習することになる。

このとき性能がどこまで落ちるのか。それを示すための実験である(いわゆるbaseline)。

f:id:aotamasaki:20200404120343p:plain

3. CL:without noises

もっとも基本的なCL。シンプルにnoiseと推定したサンプルを抜いて再学習する。

これでnoisy labelの悪影響は軽減されるだろう。しかしサンプル数は減ってしまいそうである。

f:id:aotamasaki:20200404120350p:plain

「ノイズ除去と訓練」と定義したところは以降使い回す。覚えておいてほしい。

4. CL:pseudo for noises

noiseと推定されたサンプルに対して、抜くのではなくラベルなしと扱っても良いではないか?そうすればX_trainの分布を崩さずに学習できる。

という発想のもと、ラベルに問題がありそうなサンプルに疑似ラベリングを施した。

f:id:aotamasaki:20200404120354p:plain

5. CL:pseudo for noises and test

上記の拡張。X_testも学習しちゃって良くない?という発想(y_testを使わなければカンニングにならない)。

さらにサンプル数が増えて学習がうまくいくことに期待。

f:id:aotamasaki:20200404120358p:plain

データセットと実験設定

興味がなければ読み飛ばしてもらっても構わない。

データセット

RCV1 v2データセットを用いた。

これはreutersの文章のデータセットである。scikit-learnではこれをtf-idfにしたものを提供している。

本来multi labelのデータセットだが、大分類の4クラスだけ残しsingle labelに加工した。その結果データの規模は以下のようになった。

  • sampleの数 685071
  • featureの数 47236 (ただしほとんどの要素が0)
  • それぞれのクラスの真のvalue counts [299612 54695 163135 167629]


これを選んだ理由としては、2つある。

noise 生成

noiseの生成に用いた分布は乱数から生成した。以下の通り。noise rateは27%、ラベルが正しいのは73%ということなる。

p(given=i|true=j) =
[[0.68936167 0.         0.         0.        ]
 [0.2387445  0.85410683 0.21184431 0.05112328]
 [0.         0.14589317 0.78815569 0.28050091]
 [0.07189383 0.         0.         0.66837581]]

判別器と評価

  • 判別器はLogistic Regression
    • 比較的軽量なため
  • パラメータチューンなしの一発勝負
    • 真のラベルがわからない現実ではモデル選択は非常に困難なため
  • 4 fold-CVで評価

実験結果

以下の表は行に手法、列に各out of fold(test)の場合を示していて、数値は正解率を示している。

性能を比較する際には下4行に注目すべきだ。性能が一番良い手法を太字で示してある。 最右列は平均と不偏標準偏差を示している。

method/ Accuracy[%] test1 test2 test3 test4 mean (std)
ML:clean (ideal performance) 97.38 97.45 97.45 97.48 97.44 (.04)
ML:noisy (baseline performance) 95.29 95.29 95.43 95.42 95.36 (.07)
CL:wituout noises 95.94 95.94 96.02 95.99 95.98 (.04)
CL:pseudo for noises 96.18 96.24 96.28 96.33 96.26 (.06)
CL:pseudo for noises and test 96.20 96.22 96.27 96.31 96.25 (.05)

これをみるとCLを用いたほうが、学習がうまくいくことが確認できる。またPseudo-labelingと組み合わせてさらに性能が改善していることが確認できる。

一方今回のデータにおいて、X_testへのpseudo labelingの有無は性能に影響を与えなかった。(X_trainだけで分布をサポートするサンプル数には十分足りたということか?)

ちなみにデータセット内のnoisy labelをどれぐらい当てられたかと言うと正解率としては94%ぐらいである。

評価指標\ performance[%]
accuracy 94
precision 91
recall 87
f1-score 89

cleanlabの一部機能の解説

学習に関して

LearningWithNoisyLabelsはcleanlabの目玉機能だ。

model=LogisticRegression(multi_class='auto')
clf=LearningWithNoisyLabels(clf=model)
clf.fit(X_train,y_train_noisy)

これだけで、CL:without noisesに示した黄色枠の処理を行ってくれる。

どのサンプルがnoiseと推定されたかはclf.noise_maskを見れば良い。

データ生成に関して

noisy labelの性能を図るために、今回のように自分でノイズを生成したい人たちがる(研究者とか)。それを手助けしてくれる関数も存在する。

今回用いたノイズ行列p(given=i|true=j)は以下のコードで生成できる。注意点としてはpyという真のyについてvalue countsした配列を渡さなければ行けない点だろう。

generate_noise_matrix_from_trace(
    4, 3, min_trace_prob=0.6, frac_zero_noise_rates=0.5, py=py, seed=seed)

上記のノイズ行列は乱数でなくても自分で設定しても構わない。それができたら今度は実際にラベルを汚染させる作業である。これの機能も以下を叩くだけである。

generate_noisy_labels(y_train, noise_matrix)

今回の実験の実装

今回の実験のコードをおいておく。サーバーで回して3時間ぐらいかかったのでノパソで回すのは非推奨...。

blog/experiments.py at master · masakiaota/blog · GitHub

cross validationなしの簡単な実験は以下のnotebookにまとめている。一つ一つなにをやっているかはnotebookを見たほうがわかりやすいだろう。

blog/router_with_confident_learning/notebooks at master · masakiaota/blog · GitHub

(reuterがrouterに間違ってたりするのはご愛嬌)

まとめ

  • ICML2020 Confident Learning の効果を、人工的にノイズを作ることで検証した。
  • RCV1-v2という高次元かつ疎なデータを用いた。
  • 5つの実験を計画し結果は以下になった。
method/Accuracy[%] mean (std)
ML:clean (ideal performance) 97.44 (.04)
ML:noisy (baseline performance) 95.36 (.07)
CL:wituout noises 95.98 (.04)
CL:pseudo for noises 96.26 (.06)
CL:pseudo for noises and test 96.25 (.05)
  • CLで単純にnoiseを取り除くだけでも効果があった。
  • Pseudo-labelingと組み合わせることで、更に性能が向上した。このように、CLはと他の手法は組み合わせやすく、これにより性能がさらに向上する可能性を秘めている。

参考

論文 [1911.00068] Confident Learning: Estimating Uncertainty in Dataset Labels

論文著者ブログ

l7.curtisnorthcutt.com

l7.curtisnorthcutt.com

自分の論文解説

aotamasaki.hatenablog.com

RCV1-v2データセットに関して

http://www.jmlr.org/papers/v5/lewis04a.html