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が検出できるんだな と把握しておけば問題ない。
実装に関しては著者が公開済みでpip install cleanlab
することができる。
実験計画
今回主に知りたいのは以下である。
- 真のきれいなラベルで学習させたときの性能 (理想的な性能)
- noisy labelを用いて学習させたときの性能 (baselineとなる性能)
- そしてnoisy labelを用いてConfident Learningを適応したときの性能
CLは他のsemi-supervised learningのテクニックとも組み合わせて使えるので、pseudo-labelingとも組み合わせて計5つの実験を行った。
- ML:clean
- ML:noisy
- CL:without noises
- CL:pseudo for noises
- CL:pseudo for noises and test
これらについて、実験手順をイラストで説明する。
1. ML:clean
きれいなデータで学習するいつものやつ。 これは理想的な性能を示すための実験である。
データとか判別器はあとで説明するので、適当なものを今は思い浮かべてほしい。ただし図に示しているyは正しい(真の)ラベルである。
2. ML:noisy
現実のデータセットの多くはnoisy labelである。それを再現するために人工的にノイズをy_train
に付与した。またy_train
は現実ではわからないため、y_train_noisy
を用いて学習することになる。
このとき性能がどこまで落ちるのか。それを示すための実験である(いわゆるbaseline)。
3. CL:without noises
もっとも基本的なCL。シンプルにnoiseと推定したサンプルを抜いて再学習する。
これでnoisy labelの悪影響は軽減されるだろう。しかしサンプル数は減ってしまいそうである。
「ノイズ除去と訓練」と定義したところは以降使い回す。覚えておいてほしい。
4. CL:pseudo for noises
noiseと推定されたサンプルに対して、抜くのではなくラベルなしと扱っても良いではないか?そうすればX_trainの分布を崩さずに学習できる。
という発想のもと、ラベルに問題がありそうなサンプルに疑似ラベリングを施した。
5. CL:pseudo for noises and test
上記の拡張。X_testも学習しちゃって良くない?という発想(y_testを使わなければカンニングにならない)。
さらにサンプル数が増えて学習がうまくいくことに期待。
データセットと実験設定
興味がなければ読み飛ばしてもらっても構わない。
データセット
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がほぼ存在しないと思われる。そのため評価に適していると感じたから。 詳しくはRCV1: A New Benchmark Collection for Text Categorization Researchを参照。
- 論文やcleanlabのサンプルでは特徴量が密なデータセットで有効性を検証していたが、要素の97%が0であるような疎なデータセットではどうなるか気になっていたため。
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
論文著者ブログ
自分の論文解説
RCV1-v2データセットに関して