目次
背景
- 機械学習におけるデータセットの分割の再考で、Train・Val・Diag・Testというメインsplitと、Challengeのようなサブsplitにデータを整理した
- 今回は、それぞれのsplitを担うデータを実際にどう作るか、という作成方法の観点から再整理する
- 特に、どれを自動生成してよく、どれを手動で作るべきか、そしてその理由を明確にする
- ここではデータそのもの(データソース・収集方法・品質)を扱う。タクソノミー・クラス設計・ラベルの信頼度といった、ラベル・クラス側の設計は機械学習におけるクラスとラベルの再考で扱う
前回のおさらい: メインsplitとサブsplit
| Dataset / Split | 主目的 | 開発者が見るか | 分類 |
|---|---|---|---|
| Train | Parameter Learning | Yes | メイン |
| Val | Model Selection | Yes | メイン |
| Diag | Error Analysis | Yes | メイン |
| Test | Final Generalization Estimate | No | メイン |
| Challenge | Failure-mode / Capability Evaluation | Yes | サブ |
Train・Valの作り方
自動生成してよい
- Trainは自動生成(合成データ生成など)で作ってよい
- Trainは「モデルに学習させたい範囲=スコープ」を定義するデータであり、生成プロセス自体がそのままスコープの定義になる
- 生成プロセスをコントロールできるからこそ、狙った分布・狙ったカバレッジのデータを効率よく用意できる
データソースの多様性
「自動生成」といっても、その元になるデータをどこから集めるかには、いくつか毛色の異なるアプローチがある。
- 辞書などの硬いデータソース: 辞書・法令・規格表のような、構造が明確で信頼性の高いデータソース。カバレッジや多様性には限界があるが、ラベルの正確さは高い
- 関連するデータソース(間接的な転用): 本来別の目的で作られたデータが、副産物として目的のラベル・構造を含んでいることがある。本来の作成目的とは別の切り口でデータを転用する発想
- ネットからのキュレーション: Web上の大量のテキスト・画像などから、パターンマッチングやフィルタリングで目的のデータを抽出する。スケールは出しやすい一方、ノイズが多く、前述のデータクレンジングが特に重要になる
これらは互いに独立したソースになりやすいという利点もある。複数のアプローチでTrainを集めておくと、データの多様性が増すだけでなく、前述の「トレイン系と診断系で元データソースを分ける」という要求にも応えやすくなる。
具体的な収集アイデアの実例は、G2Pライブラリを作る時に調査した先行文献などのメモのデータ収集のアイデアで詳しくまとめている。
収集時の実践
データを集める段階そのものにも、気をつけるべき実践がいくつかある。
- PositiveだけでなくNegativeも意図して集める: Negativeの収集を疎かにすると、実運用でどんな入力が来るか分からないままモデルを評価することになる。特にhard negativeやOODになりうる入力は、Positiveと同じくらい丁寧に設計して集めるべき
- Positiveがa・b・cという特徴を持っていて本当はaだけを学習させたい場合、b・cは持つがaは持たないNegativeがないと、モデルが間違った特徴を学習してしまう(例: 音声からある単語を学習させたかったのに、Negativeが不足していたため単語ではなく話者の喋り方を学習してしまった、というケース)
- 中間データも保存する: 最終的に使う加工済みデータだけでなく、加工前の中間データも保存しておく。後から加工方法自体を見直したくなった時に、収集からやり直さずに済む
- ダブルチェックをする: ラベル付けや収集作業は、1人だけでなく複数人でダブルチェックする。特にAIやクラウドソーシングで生成・収集したデータは、人の目でのダブルチェックが必須
ホールドアウトでTrain/Valに分ける
- 生成したデータプールを、ホールドアウトでTrainとValに分割する
- つまりTrainとValは、どちらも同じ生成プロセスに由来する「スコープ内(in-scope)」のデータという位置づけになる
- Valはモデル選択に使うため、Trainと同じ分布から取れていれば十分で、独立性の要求はDiag・Testほど厳しくない
- 分割の際は、元データのクラス比率(経験的な事前確率$P(Y)$)をなるべく維持したstratified splitで行う
- 例えば元データがA:70%, B:20%, C:10%なら、Train/Val/Testもそれぞれ概ね70/20/10になるように分割する
Diagの作り方
自動生成を避け、手動で作る
- Diagは基本的に自動生成を避け、人手で作ることが望ましい
- 理由は、統計的な優位性(有意性)を主張するために、サンプルの独立性が必要だから
- Trainと同じ生成プロセス(同じモデル・同じテンプレート・同じ乱数源など)でDiagも自動生成すると、TrainとDiagのサンプルが統計的に独立でなくなる
- 独立性が崩れると、Diagで良い結果が出たとしても、それが本当の汎化性能なのか、単に生成プロセスの癖への過学習を反映しているだけなのかを区別できなくなる
- 少ないサンプルサイズでも意味のある信頼区間を持たせるには、まずサンプル同士の独立性という前提を満たしておく必要がある
- 上記のような単純な比率推定であっても、信頼区間の妥当性は$n$個のサンプルが独立であることを前提にしている
- 独立性が崩れていると、見かけの$n$より実質的な情報量は少なく、信頼区間は実態より狭く(楽観的に)出てしまう
スコープ内・スコープ外・OODを含める
- Diagには、in-scopeのデータだけでなく、out-of-scopeのデータ、そしてOOD(Out-of-Distribution)のデータも意図的に含める
- 理由は、モデルの能力の幅を測れるようにするため
- in-scopeのデータだけでは「スコープ内でどれだけうまくいっているか」しか分からず、スコープの境界がどこにあり、境界を越えるとどう崩れるかが見えない
- スコープ内・スコープ外・OODを横断的に含めることで、Diag1つで「境界の内側の性能」と「境界そのものの位置」の両方を診断できる
Testの作り方
外部データソースをなるべく使う
- 評価データセット(Test)は、基本的に外部のデータソースをなるべく利用する
- 理由は、自分でデータを生成すると、事前確率(prior)が変わってしまうから
- 自分の生成プロセスには、無意識のうちにクラス比率・パターンの偏りが入り込みやすく、その偏った事前確率のもとで測った性能は、現実の事前確率のもとでの性能とズレる
- 外部のデータソースを使うことで、こうした自己言及的な偏りを避け、より現実の事前確率に近い状態で評価できる
- さらに一歩進めて、自前データを一切混ぜず、出来合いの公開データセットのみ100%でテストセットを作るという手もある。生成過程が完全に独立したデータで評価できるため、自前データの収集過程に共通する癖への過学習を検知しやすくなる
- これは精度を追求する本番用ではなく、あくまで評価のための物差しとして使う位置づけ
- 他人の作ったデータセットや手法を再現しようとすると、特徴量の計算方法など自分では気づかなかった変えられる点が色々見つかるため、学びや改善幅も大きい
エラーアナリシス禁止
- 評価データセットに対するエラーアナリシスは禁止
- 集計されたスコア以外の目的で、中身を見ること自体も禁止
- これは前回の記事で扱った「Testを覗いた瞬間、測っている量が無条件の汎化性能から、そのTestに条件付けられた量にすり替わる」という問題への対策そのもの
データソースの分離
トレイン系と診断系は元データソースを分ける
- データセットを作る際、元となる生データソース自体を、トレインデータ系(Train・Val)と診断データセット(Diag)とで必ず分ける
- 同じ生データプールからランダムに分割するだけでは、独立性の担保として不十分になりうる
- 完全に別のデータソース(別の収集経路、別の収集時期、別の生成方法など)を用意することで、より確実な独立性を担保する
- Testについても同様に、Train・Valはもちろん、Diagとも別のソースであることが望ましい
データの量
サンプル数そのものが必要
- seedを固定して実験がべき等に実行でき、2回同じ実験をして全く同じ結果が返ってきたとしても、サンプルサイズは別問題として必要
- サンプル数が極端に少ないと、実験の比較としては再現できても、実際にはドメインシフトが起きている可能性を検知できない
- 評価データは結局は注ぎ足し継ぎ足しで増やしていくものなので、最終的には数そのものが重要になる
- 経験則として、1クラスあたりのサンプルサイズが50以下のholdoutでは、統計的に優位な数値が出ないことが多い
- 学習時にべき等であっても、評価時にべき等とは限らないため、評価方法自体にも注意が必要
相対的な量にも注意する
- クラス間の相対的なサンプル量にも注意が必要
- 例えば、AクラスとBクラスがある評価データで、Bクラスのデータ(holdoutも含む)だけを増やすと、全体の指標がBクラス過多の影響を受けてしまう
- ミクロ指標(全体の精度)はBクラスに引っ張られ、平等な精度の指標ではなくなる
- Aクラスは相対的に量が少なくなり、学習側の注力もBクラスに大きく振られている可能性が出てくる
- つまり、もともと学習できていたAクラスの特徴を、モデル容量不足のために上書きしてしまっている可能性がある
- この場合、モグラたたき的にデータを直すのではなく、モデル容量の不足自体を疑うべき
- データ量を増やす際は、モデルのパラメータも合わせて増やす必要がないかを検討する
- 精度を報告する際も、1教科で90点なのか10教科で90点なのかで意味が全く違うように、分母(サンプルサイズ・クラス数)を必ず加味する
学習曲線分析でデータ量を判断する
- 「データを増やすべきか、それともモデルを変えるべきか」を判断する古典的な手法として、学習曲線分析(Learning Curve Analysis)がある
- 横軸に訓練データのサンプル数、縦軸にTrain誤差とVal誤差を取り、サンプル数を段階的に増やしながらそれぞれを記録してプロットする
- 曲線の形から、次の2パターンを見分けられる
- Train誤差・Val誤差がどちらも高く、両者が近い値に収束している場合: High Bias(underfitting)。データを増やしても誤差はほとんど下がらないため、データ収集よりモデルの表現力を上げる方が効く
- Train誤差は低いがVal誤差が高く、両者に大きな差がある場合: High Variance(overfitting)。この場合はデータを増やす、または正則化を強めることで差が縮まりやすい
- つまり、データを追加する前に、まず小規模なサンプルサイズでこの学習曲線を描き、追加データが本当に効くパターンかどうかを確認しておくと、無駄なデータ収集を避けられる
- これは前述の「相対的な量にも注意する」で触れた、モデル容量の不足を疑うべきケース(High Bias側)と、単純にデータが足りないケース(High Variance側)を、事前に切り分けるための手法とも言える
データ品質QA
ここまでの役割分担・独立性の設計を正しく行っても、データそのものにバグがあれば意味がない。何よりも大切なのは、データの品質QAである。最小構成でのミニテスト、バグの発見方法、パイプラインのテスト、重複除去などは、機械学習におけるデータ品質QAの再考で独立して扱う。
まとめ
- Train・Valは自動生成でよく、同じ生成プロセスからstratified splitでホールドアウトして分割する、スコープ内のデータ
- データソースには、辞書などの硬いデータソース・関連するデータソースの転用・ネットからのキュレーションという毛色の異なるアプローチがあり、複数使うことで多様性とソース分離の両方に貢献する
- Diagは自動生成を避け、独立性を保つために手動で作る。さらにin-scope・out-of-scope・OODを横断的に含めることで、能力の境界そのものを診断できるようにする
- Testはなるべく外部データソースを使い、事前確率のズレを避ける。エラーアナリシスや中身の閲覧は禁止
- 元データソース自体を、トレイン系と診断系で分けておくことが、統計的な独立性を担保する土台になる
- サンプル数は絶対量(1クラスあたり最低限の目安)と相対量(クラス間バランス)の両方に注意し、精度を報告する際は分母を必ず加味する
- データを増やす前に、小規模サンプルで学習曲線分析(Train/Val誤差 vs サンプル数)を描き、High Bias(モデルを変えるべき)かHigh Variance(データを増やすべき)かを切り分けるとよい
- 役割分担・独立性を正しく設計しても、データ自体にバグがあれば意味が無い。品質QAの具体的な方法は機械学習におけるデータ品質QAの再考で扱う
- タクソノミー・クラス設計・Grade・ラベルの信頼度(Gold/Silver)といった、ラベル・クラス側の設計は機械学習におけるクラスとラベルの再考で扱う
