Featured image of post 機械学習におけるクラスとラベルの再考

機械学習におけるクラスとラベルの再考

目次

背景

  • 分布外データの対処方法や機械学習におけるデータとデータソースの再考では、データそのものの収集・分割・品質管理という観点を扱った
  • 分類タスクには、それとは別に「クラス・ラベルそのものをどう設計・管理するか」という固有の問題がある
  • クラスの境界をどこに引くか、似ているクラス同士をどう切り分けるか、負例をどう定義するか、ラベルの信頼度をどう管理するかによって、同じデータ量でも学習・評価の質が大きく変わる
  • 今回は、このクラス・ラベル設計という観点から再整理する

クラス設計の原則

完全性と無矛盾性

データセットが間違っていれば、モデルも間違える。では、不完全性のない完璧なデータセットは作れるのか。

  • 完全性: 不可能。入力空間は無限であり、網羅はできない。現実的なユースケースを定義し、目標とするスコープを絞るしかない
  • 無矛盾性: 可能。タクソノミーを定義し、運用でカバーすることで、無矛盾なデータセットを作ることはできる

これはゲーデルの不完全性定理に近い構図で、完全性と無矛盾性の両方を同時に満たすことはできないが、無矛盾性だけであれば設計次第で達成できるという整理になる。ただし、ソリテスパラドックスのように、境界の定義自体には曖昧さが残ることには注意する。

seedとタクソノミーというデータ仮説

  • seedとは、データを収録・生成・収集する上で基本となるデータの設計書
  • Data-Centric AIの観点では、seedがデータの分解能の基本であり、実験における最も重要な仮説になる
  • 人間が対象世界をどの粒度・軸・関係性で分解するかという「データ仮説」を設計することが、知識空間(Knowledge Space)からデータ空間(Data Space)への射影規則を決めることに相当する
  • この仮説を先に言語化したものがタクソノミーであり、タクソノミーを先に定義してからデータを集めることで、無矛盾性を担保しやすくなる
  • タクソノミーに漏れがあると、学習・評価どちらでもカバーできない領域が生まれ、それがOODの一因にもなる
  • ただし、実験計画法の要因実験のように、軸・粒度をすべてマニュアルで組み合わせて定義しようとすると、組み合わせ爆発でパターン数が破綻しやすい
  • そのため、全パターンを人手で列挙するのではなく、実データから頻出パターンを抽出してタクソノミーを組み立てる方が現実的
  • 例
    • 文字レベルで扱う場合は、先にタクソノミーを定義してから分類する
    • 音声データの場合は、音声学(Phonetics)のIPA(国際音声記号)をベースにデータの定義を行う
    • 難しい課題では、失敗を見越してgrade(難易度)の定義をあらかじめ行う
    • クラスが二値分類でも、あえてnegativeを多クラス化し、エラーパターンごとに学習させる
    • 難しいクラスにはsubclassを定義してMECEに列挙する
    • 精度が上がらないサブクラスには、対となるDyadのpairを作って対照学習する
  • これが仮説となり、人によるデータレベルのinductive biasになる

タクソノミーとサブデータセットによる分割統治

  • 困難は分割せよ、ではないが、サブデータセットを作って対処するのも有効
  • サブデータセットは「grade(難易度)× クラス数」のように定義し、それぞれにタクソノミーとdefinitionを与える
  • 大量の矛盾するデータよりも、少量の無矛盾なデータを作るイメージ
  • 特に、意味の近いクラス同士を分類するinner-class classificationのようなケースで有効
  • 実務上は、gradeでフォルダを切り、クラスでフォルダを切り、その中でさらにタクソノミーを分析してseedを生成するという流れになる

小さな範囲での学習可能性テスト

  • データセットが無矛盾かつ完全であれば、gradeの低いものは学習できるはずである
  • 最初に作ったseedデータをベースに、データ生成やaugmentationをする前に、素の状態でまずテストするとよい
  • 小さく試して、どのgradeまで学習できるかを確認してから拡張する方が安全
  • 精度が上がらない原因はモデルの容量や学習データの量ではなく、学習データそのものが矛盾していることも多い
  • ただし、小さく多様性のない範囲での実験になるため、そのまま汎化性能を保証するとは言えない
  • 基本を確認してから応用を学習させるという考え方

Gradeによる難易度設計

なぜGradeが有効か: 最小条件での分離可能性の検査

  • Gradeを設計する最大の利点は、「最小の条件でタスクが本当に解けるか」を検査できること
  • 直感的には、grade1(最も易しい設定)は当然解けるはず、と思い込みやすい
  • しかし、論理的に最低かつ最小の条件(それ以上削れない、必要最小限の情報だけを残した条件)では、実はクラスの分離が難しいことがある
  • 理由は、grade2以降で加わる文脈・特徴量が、実は意図せずクラスの分離を助けていた可能性があるから
  • 例えば「太郎」という単語の検出タスクで、grade1を「音声的な文脈を一切含まない、最短の音素列だけ」と定義したとする
    • この最小条件では、「太郎」の音素列が、別の単語の一部分(例えば別の名前の頭部分)と酷似しており、論理的に区別できない場合がある
    • grade3・grade4で加える文脈情報(前後の音・イントネーションなど)があって初めて分離できていたのだとすれば、grade1で解けないのは当然であり、モデルの性能不足ではない
  • つまりgrade1が解けないという結果は、モデルの問題ではなく、タスクの定義・クラス設計そのものに問題があることを示すシグナルになる
  • これは小さな範囲での学習可能性テストで触れた「精度が上がらない原因は、学習データそのものが矛盾していることも多い」という話と直結し、grade1の失敗を「タクソノミー自体を見直すべきサイン」として使える

評価用データをgrade別に用意する

  • Diag・Challengeのような評価用データは、難易度別に複数用意するとよい
  • たとえTrainにデータを追加しても、それが基礎能力に悪影響を及ぼしている可能性もある
  • そのため、学校の学年のように6段階程度でgrade別のholdoutデータセットを用意し、評価するとよい
  • 「grade1は通っているから、その使い方に限定する」といった逃げ道を作れるようにする意味もある
  • 例えば、paraphraseやreasonを付けたもの、否定形を混ぜたものはgradeを1段上げる、といった基準を決めておく
    • paraphraseの例: 同義語への置き換え、受動態と能動態の変換、品詞の変更、文の統合・分割

グレード別のラダー表を作る

  • gradeの基準を頭の中だけで管理せず、ラダー表(各gradeで何が加わるかを1段ずつ積み上げた表)として明文化しておくとよい
  • 例えば、「明日の天気を教えて」という問い合わせを起点にすると、以下のようなラダー表になる
Grade加わる変換例
Grade1なし(素のケース)明日の天気を教えて
Grade2同義語への置き換え明日の気象を教えて
Grade3受動態・能動態の変換や語順の変化明日の天気について教えてほしい
Grade4否定形の混入明日雨が降らないか教えて
Grade5文の統合・分割、複数意図の混在明日の天気と、傘が必要か教えて
Grade6上記の複合雨が降らなければ、明日の予定はどうなる?
  • 各gradeは前段のgradeに対して「1段だけ変換を加える」ように設計し、どこで精度が崩れたかを1段単位で特定できるようにする
  • このラダー表があると、「Grade3までは安定して動く」のように、開発者以外にもスコープの限界を説明しやすくなる
  • gradeによる精度の精緻化で触れた「GradeXまでは80%で解ける」という報告も、このラダー表があって初めて意味を持つ

holdoutだけに頼らない

  • holdout・heldoutだけでは、学習ができたこと以外の証明にならない
  • そのため、difficultケースや、生成プロセスから全く別に作ったデータをベースにした評価も併用するべき
  • つまり、複数種類のDiag・Testを用意しておくのがよい

gradeによる精度の精緻化

  • 仮にグレードを作っていないと、学習がうまくイカない場合は、低スコアになってしまう
  • その場合は使えないモデルを作ったということで、採用されなくなる
  • 他方、グレードを作った場合は、GradeXまでは80%で解けるのようにスコアがよく見える
  • これは仮にうまくいかなかった時に、逃げ道としてどこまでは行けるかを明示する事ができる
  • gradeXで80%までは行けるなら、次のグレードからアンサンブルにしようなどのような考え方も可能
  • すなわち、Gradeやスコープは有用ということ

スコープの選び方: バギーとリライアブル

Gradeを積む・積まないという選択は、結局「スコープをどこまで広げるか」という選択に帰着する。ここには2つの極がある。

アプローチ意味特徴
なんでもできる(バギー)スコープを最初から広げ、全gradeを一気に狙う対応範囲は理想的だが、Edge Caseが爆発的に増え、完全性・無矛盾性を確保できず不安定になりやすい
少しはできる(リライアブル)スコープを絞り、狭いgradeだけを確実に狙う対応範囲は狭いが、無矛盾性を保ちやすく、安定して動く
  • 「なんでもできる」は理想的な最終形ではあるが、そこへ直接到達しようとするのは修羅の道になりやすい
  • スコープが広いほど、クラス設計の原則で触れた無矛盾性の担保が難しくなり、バグや矛盾したデータが混入する余地も増える
  • そのため、まずは狭いスコープ(低いgrade)でリライアブルに動くものを確立し、小さな範囲での学習可能性テストのように段階的にgradeを上げてスコープを広げていく方が、結果的に「なんでもできる」に近づく近道になる

クラスの幾何学的デザイン(Geometric Class Design)

クラスの定義を絞る

  • 精度が低いクラスに対して、データ量を増やして曖昧な境界を学習させるのではなく、クラス自体の範囲を狭める方法も有効
  • クラスの判定対象を狭め、クラス間の境界が太くなるようにモデルを設計する
  • 国土を広げて(データを増やして)国境線の太さ(クラスの境界の太さ)を確保するより、国土自体を小さくして境界を太くするという考え方
  • もちろん、モデルの性能自体が原因の場合もある

コアとサーフェス

分類する空間は、大きく2種類に分けて考えられる。

  • コア: 意味軸。人間が定義したseedで作成するか、実データをサンプリングして得る
  • サーフェス: 表現軸。AIによってseedからaugmentationする(パラフレーズの生成など)

例えば文字ベースの分類では、あるクラスを決定する特徴的な属性を属性1、次点で優位な属性を属性2とし、これらの軸を掛け合わせてタクソノミーを作り、データをsubcat(サブカテゴリー)で分類する。クラス内の特徴を抽出してサンプルを生成するレシピを網羅することで、クラスの幾何学的な領域を設計できるようになる。

inner-classとinter-classでの一貫性

  • 意味の近いクラスを分類する場合は、ラベルの矛盾が発生しやすい
  • AというクラスとBというクラスのそれぞれのサンプルの中で、教師信号が一貫していないケースがある
  • そのため、クラス間で矛盾がないかのチェックが必要
  • そうでないと、モデルが安易な結論に陥りやすくなる

中間クラスの必要性

  • クラスAとクラスBの境界を狭め、境界専用データセットを用意するのは有効な対処法だが、それでも解決しないケースがある
  • 例えば、NoneクラスとReadクラス(知識を要すると判断した場合に割り当てるクラス)があるとする。多くのサンプルは迷わず振り分けられるが、一定数、両者を継続的に取り違えるサンプルが残ることがある
  • こうした取り違えは、アノテーションのミスや境界の甘さではなく、AとBの設計そのものに原因があることがある
  • AとBは本来「どちらか一方(OR)」という排他的な関係として設計されているはずだが、実際にはAとBの性質を両方あわせ持つ、ANDの領域のサンプルが存在している、ということ
  • これは2×2の中に潜む部分と全体の構造で触れた、非排他的な領域を無理に排他的な区分に押し込めようとする問題と同じ構造
  • AND領域のサンプルを無理にAかBかに押し込めようとすると、どちらのクラスの境界も歪み、inner-class・inter-classの一貫性が崩れ続ける
  • 対処法は、無理に既存のクラスへ押し込めるのではなく、そのAND領域専用の中間クラスを新設すること
  • 例えるなら、どちらの国にも属さない集団を無理にどちらかの国籍に割り当てるのではなく、独立した居場所を用意して保護するようなもの
  • 中間クラスを作ることで、AとBそれぞれの境界は再びクリーンなOR(排他的)の関係に戻り、無矛盾性を回復できる
  • 中間クラス自体も、Noneクラスと同様に1つのメタクラスとして扱い、必要であればさらにサブクラス化できないかを検討する

離散ラベルかマルチラベルか

  • AND領域を持つサンプルへの対処は、中間クラスを新設する以外にも、そもそものラベルの表現方法を変えるという選択肢がある
  • 離散値(single-label): 各サンプルに1つだけラベルを割り当てる方式。モデル側はsoftmax・多クラス分類として学習し、クラス同士が真に排他的(OR関係)である前提に立つ
  • マルチラベル(logit形式): クラスごとに独立した0/1の値を持たせ、複数のクラスが同時に成立してよいとする方式。モデル側はクラスごとに独立したsigmoid出力・二値分類として学習する
  • AND領域のサンプルがある場合、中間クラスを新設する(クラスの数を増やして排他性を保つ)代わりに、そのサンプルにAとBの両方のラベルを立てる(そもそも排他性を前提にしない)という対処もできる
  • どちらを選ぶかは、AとBの共起が意味的に自然かどうかによる
    • 共起が例外的・境界的なものであれば、中間クラスとして明示的に切り出す方が、タクソノミーの見通しが良くなる
    • 共起が本質的に珍しくない(多くのサンプルがAとBを両方持ちうる)なら、最初からマルチラベルとして設計する方が自然
  • 中間的な手法として、0/1の代わりに確率値(0.7、0.3など)を持たせるソフトラベル・ラベルスムージングもある。ラベルの信頼度: GoldとSilverで触れたラベルの確信度を、ラベル自体の値に埋め込む手段としても使える

境界専用データセットを作る

  • クラスの範囲を狭めて境界を太くしても、間違いは起こりうる
  • 特に、物理的に意味が近い複数のクラスがある場合、その境界は間違いやすい
  • そのため、クラスの際(きわ)専用のデータセットを作るのが有効
  • 例えば12クラス分類の場合、2つを選ぶ組み合わせは
$$ \binom{12}{2} = 66 $$
  • 通りあり、境界の両側にそれぞれデータを用意する必要があるため
$$ 66 \times 2 = 132 $$
  • 通りが、原理的には必要な境界クラス用データの数になる

境界データセットのためのクラスの選び方

  • 66通りすべてを対象にするのは大変なので、ターゲットを絞った方がよい
  • 混同行列から誤爆ランキングを出し、優先度の高い境界を判断する方法がある
  • 他の指標との相関を見て判断する方法も考えられるが、同じデータを使った相関係数はトートロジーになるため注意が必要

Hard Caseの作り方

注意点

  • 特徴の変化のかけ方によって、有益にも有害にもなるため注意が必要
  • 例えば画像系では、特徴の一部を0でマスクして消す手法がよく使われる
  • 同じ手法を音のデータに適用すると、うまくいかないことが多い
  • 理由は、音の場合はマスクによる不自然さそのものを学習してしまうから
  • そのため、単調なマスクだけでなく、ノイズによるマスクなど複数の手法を試す必要がある

shifted positive

  • 例えば「太郎」を対象にする場合、最低でも「〜太郎」「〜太郎〜」「太郎〜」の3パターンを作れる
  • 時系列的なずらしによってpositiveケースを増やす例で、データのかさ増しにも使える

adversarial negatives

  • いわゆるhard negativeの一種
  • 例えば「太郎」に対して、音的に似ている「tara」や「soro」のような、一部を変更した特徴量をnegativeとして用意する
  • 意図的に似た音のケースを増やす例

Truncated Negative

  • Positiveケースの一部を含むデータを、あえてNegativeとして用意する手法
  • 例えば「太郎」という名前を分類したい場合、前半の「〜太」と後半の「郎〜」を、それぞれTruncated Negativeとして用意できる
  • 全体を学習させたいが、部分だけで安易に分類させたくない場合に有効
  • 部分切り出しによってデータ自体も増えるため、かさ増しにも有効

Hidden Negative

  • 画像のFine-grained Classificationなどでは、特徴をマスクで隠して学習させる手法が有効とされている
  • Hard NegativeをPositiveケースの一部を隠して作る手法
  • 特徴的な部分をベースに学習が進んでしまうのを避け、あえて大局的な特徴を隠すことで、局所特徴を学習させる
  • こちらもデータのかさ増しに有効

組み合わせ数を数える

  • 上記のpositive/negativeのパターンは、特徴量の要素ごとにさらに増やせる
  • 例えば「たろう」を対象にHidden Negativeを適用する場合、3文字なので3要素(A・B・C)とすると、正解はABCのみになる
  • 計算すると、Hidden Negativeだけでも次のパターンが考えられる
$$ \binom{3}{2} + \binom{3}{1} + \binom{3}{0} = 3 + 3 + 1 = 7 $$
  • 2つ選ぶ: AB・AC・BC(3通り)
  • 1つ選ぶ: A・B・C(3通り)
  • 0個選ぶ: 選ばない(1通り)
  • つまり、順番と要素が固定であれば、7パターンのHidden Negativeを作れる

メタクラス

  • メタクラスとは、個々の意味クラス(何であるかを表すクラス)とは異なる階層で、データセット全体の構造上の役割を担うクラスのこと
  • 代表的なものに、None(負例メタクラス)・OOD(分布外であることを示すクラス)・Impossible(そもそも分類が不可能であることを示すクラス)の3種類がある
  • OODについては分布外データの対処方法で扱っているため、ここではNoneとImpossibleを、メタクラスという共通の観点から整理する

Noneメタクラス

  • Noneは、既知のどの意味クラスにも当てはまらないサンプルを受け止める、負例用のメタクラス
  • 個々の意味クラスと同じ階層に並べるのではなく、全体を覆うメタクラスとして位置づけることで、Noneの1-Recallが実質的なFPRに対応するなど、通常のクラスとは異なる評価軸を持つことが明確になる
  • 具体的な設計・評価方法は、次のNoneクラス(負例クラス)を追加するで詳しく扱う
  • このNoneメタクラスの設計は、哲学のtruthmaker理論における否定的事実の問題と同じ構造を持つ。詳しくはTruthmaker理論と機械学習におけるNoneクラス設計で扱っている

Impossibleクラス

  • 与えられた入力そのものから、原理的に分類が不可能であることを示すためのメタクラス
  • Noneが「既知のどのクラスにも当てはまらない」という分類結果を表すのに対し、Impossibleは「そもそも判断材料が足りない・入力が壊れている」という入力の状態についての判断であり、役割が異なる
    • None: 意味のある入力に対して、既知のpositiveクラスのいずれでもないと判定した結果
    • Impossible: 音声が途中で切れている、画像が全面ノイズで判別不能、テキストが文字化けしているなど、そもそも人間が見ても判断できない入力
  • NoneとImpossibleを混同すると、Noneクラスの中に「本来は分類不能なだけのサンプル」が紛れ込み、Noneクラスの一貫性が崩れる
  • Impossibleを明示的なメタクラスとして切り出しておくことで、モデルの性能低下の原因が「クラス設計の問題」なのか「そもそも判断不能な壊れた入力が混ざっているだけ」なのかを切り分けられる
  • 特に評価データにImpossibleサンプルが混ざっていると、モデル本来の性能を過小評価してしまうため、事前にImpossibleクラスとして分離しておく価値がある
  • Impossibleかどうかの判定自体の難しさに注意する。「判断できないことを判断する」タスクになるため、人手でのダブルチェックが必要になりやすい

Noneクラス・Negationクラスの設計

Noneクラス(負例クラス)を追加する

  • 低い確信度を単純に棄却するだけでなく、明示的なNoneまたはOtherクラスを追加する
  • これにより、モデルは既知のpositiveクラスだけでなく、学習時に与えた負例をNoneとして識別できるようになる
  • ただし、Noneクラスを追加しても、あらゆる未知入力を識別できるわけではない
  • 学習に使用した負例や、それに近いOODには有効だが、まったく異なる未知入力に対して誤って高い確信度を出す可能性は残る
  • Noneは全体の負例クラス用のメタクラスであるため、実質的にはNoneの1-Recallこそが本来のFPRになる
  • Noneクラスのrecall(Noneを見逃さなかった割合)は、そのまま通常クラスのprecisionに対応する
  • つまり、見逃さずに正確に処理できた通常クラスの評価につながる
  • Noneクラスの性能が下がれば、当然通常クラスの性能にも影響が出る

既知の弱点をあらかじめ加味する

  • 例えばNLPでは、否定表現において精度が下がりやすいという既知の弱点がある
  • 特徴が似ているにもかかわらず、クラス領域が外れてしまうことが原因
  • こうした既知の弱点については、あらかじめデータセットのバランスを調整して対処できる

Negationの明確化

  • 特にnegationが絡む場合に有効な手法
  • 例えば、Moveクラスの反対がDon’t MoveなのかStopクラスなのか、AIが迷うケースがある
  • その場合は、意味を明確化するために、MoveクラスのスロットにNegationを持たせ、Move(negated=True)のように表現する
  • すると、メタクラスであるNone以外の否定表現は、Negationスロットで対応できるようになる
  • 結果として「動かない」と「Stop」が同一視されなくなり、精度が上がる
  • これはデータセットの無矛盾性とも関連する

ラベルの信頼度: GoldとSilver

データセットのラベルは、どうやって付与されたかによって信頼度が異なる。この信頼度をGold・Silverという段階で区別して管理しておくことも重要。

Gold(ゴールド)ラベル

  • 人の手で検証・確認されたラベル
  • 品質は高いが、作成コストが高く量を確保しにくい

Silver(シルバー)ラベル

  • モデルやルールベース処理などで自動生成されたラベル
  • 量は確保しやすいが、ゴールドに比べてノイズが混ざりやすい

段階的なティア管理

  • 単純な二値の区分だけでは不十分なことも多く、信頼度をさらに細かい段階に分けて管理すると扱いやすい
  • 例: 読みが一意で人手検証済み(gold_verified)、人手検証済みだが本質的に複数の正解がありうる(gold_free_variation)、まだ判断がついていない自動生成ラベル(silver_ambiguous)
  • ティアごとに、機械的なクロスチェックを先に流し、意見が割れたものを優先的に人手レビュー(Silver→Goldへの昇格)に回す、という段階的な運用と組み合わせるとよい
  • 詳しくはフリガナデータをクレンジングする時に直した項目のメモや分布外データの対処方法でも扱っている

用途による使い分け

  • Trainには、SilverをGoldと混ぜて量を確保しつつ使うことが多い。多少のラベルノイズは学習の過程である程度吸収されやすい
  • Diag・Testのような、性能を正しく測定するためのデータには、なるべくGoldを使うべき
  • ラベル自体にノイズがあると、性能の低さがモデルの問題なのかラベルのノイズなのかを区別できなくなり、機械学習におけるデータ品質QAの再考の意味が薄れてしまう

ラベル・属性の管理方法

データセット、特にTrainデータセットを作る際には、サンプルが持つ属性をどう区分・管理するかという問題もある。属性の性質によって、適した管理方法が異なる。

直交する属性: フォルダ管理

  • クラス・サブクラス・カテゴリー・ID/OOD・Positive/Negative・Easy/Hardのような属性は、互いに直交する(1サンプルにつき各軸で1つの値だけを持ち、軸同士も独立している)
  • こうした属性は、フォルダ階層でそのまま表現できる
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class_A/
  id/
    positive/
      easy/
      hard/
    negative/
      easy/
      hard/
  ood/
    positive/
      easy/
      hard/
    negative/
      easy/
      hard/
  • ディレクトリ構造自体がそのままデータの分類を表すため、追加のマスターファイルが無くても直感的に管理できる
  • 特にID(In-Distribution)とOOD(Out-of-Distribution)は、機械学習におけるデータとデータソースの再考のDiagで扱う「スコープの境界」を直接反映する軸でもあり、他の軸と同様にきちんと分けて管理しておくことが重要
  • 他にも、以下のような軸がフォルダ管理に向いている
    • spec/seed(データを生成・収集する前提となる設計書やtaxonomy)
    • self/others(自分で作ったデータか、他所のデータか)
    • real/generated・third_party(データの出自)
    • sampling_weight(学習時のサンプリング重み別)
    • case(特定のケース別)
    • calibration(確信度キャリブレーション用)
    • generalization dataset(いわゆるOOD dataset。汎化性能を客観的に測るために別途用意しておく必要がある)

直交しない属性: Tag.jsonでの管理

  • UseCase・FailurePatternのような属性は、クラスのように均等に分布せず、1サンプルが複数の値を同時に持つこともある多対多の関係になる
  • こうした属性をフォルダで表現しようとすると、同じサンプルを複数の場所に置く必要が出てきて破綻する
  • 代わりに、Tag.jsonのようなマスターファイルで、サンプルIDとタグの対応表として管理する方がよい
1
2
3
4
{
  "sample_001": ["use_case:login", "failure:timeout"],
  "sample_002": ["use_case:login", "use_case:logout"]
}

対称的な属性: Pair.jsonでの管理

  • Dyad(対)になるような、表現がわずかに違うだけの対応関係を持つサンプルもある
  • この対応関係自体が情報を持つため、pair_idを振り、Pair.jsonのようなマスターファイルでどのサンプル同士が対になっているかを管理する
1
2
3
4
{
  "pair_001": ["sample_010", "sample_011"],
  "pair_002": ["sample_023", "sample_024"]
}

まとめると

属性の性質例管理方法
直交するクラス・カテゴリー・Positive/Negative・Easy/Hardフォルダ階層
直交しないUseCase・FailurePatternTag.json(多対多のマスター管理)
対称的Dyad・minimal pairPair.json(pair_idによる対応管理)

具体的なデータセット定義例

多クラス分類の例

  • まずdataについて、種となるデータ(seeds)と生成されたデータ(generated)を分ける
  • data/{seeds, generated}のような形にする
  • さらにdata/seeds/grade1/class_name/{positive,negative}/subclass_name/{def.md, seed.csv}のように切る
  • gradeは難易度を表し、grade1からgrade6程度まで定義する
  • gradeを定義する理由は、うまくいかなかった時に、どこまでうまくいっているのかを測れるようにするため
  • それぞれの$\text{grade} \times \text{class} \times \text{subclass}$について、分割統治法のように解いていくイメージ
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  seed1/
    grade1/
      class1/
        positive/
          subclass1/
          subclass2/
        negative/
          subclass1/
          subclass2/
      class2/
        positive/
          subclass1/
          subclass2/
        negative/
          subclass1/
          subclass2/
    grade2/
      class2/
        positive/
          subclass1/
          subclass2/
        negative/
          subclass1/
          subclass2/

二値分類の例

以下は、ある名前を対象にした二値分類のクラス設計の実例。

  • グレードをトップで分けるのではなく、まずreal/syntheticというsourceの軸で分ける
  • その後にgrade分け(難易度分け)をクラスに落とし込み、クラス単位で難易度を教える
  • この例では単純な二値分類ではなく、negativeの内訳を細分化して5クラス分類にしている
  • 対象クラスのフォルダ以外はすべてnegativeケースになる
  • 最後に、サブクラス単位でさらに分割している
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
  synthetic/
    target_voice/
      easy_simple/
    hard_negative_voice/
      wrong_name_with_prefix/
      arbitrary_prefix/
      bare_other_name/
      real_word_fragment/
      invented_syllable/
    no_voice/
      synthetic_noise/
  real/
    target_voice/
      easy_simple/
    negative_voice/
      corpus_a/ corpus_b/ corpus_c/
    no_voice/
      silence_clips/ ambient_noise/ musan_noise/

まとめ

  • 分類クラスの設計には、完全性は目指さず無矛盾性を目指すという原則があり、seedとタクソノミーというデータ仮説、サブデータセットによる分割統治で実現しやすくなる
  • 評価用データはgrade別に難易度設計しておくと、基礎能力への悪影響やholdout過信を避けられる
  • Gradeの本質的な価値は、最小条件でタスクが本当に解けるかを検査できること。grade1が解けない場合、モデルの問題ではなくタスク定義・クラス設計自体を見直すべきシグナルになる
  • スコープは「なんでもできる(バギー)」か「少しはできる(リライアブル)」かの選択で、理想は前者だが直接狙うと修羅の道になりやすく、狭いgradeから段階的に広げる方が近道になる
  • grade別のラダー表を作っておくと、各gradeで何が加わるかを1段単位で明文化でき、スコープの限界を開発者以外にも説明しやすくなる
  • クラスの範囲を絞り境界を太くするGeometric Class Designや、コア(意味軸)とサーフェス(表現軸)の分離によって、クラスの幾何学的な領域を設計できる
  • 2つのクラスを継続的に取り違えるサンプルがある場合、それはANDの領域が存在するサインであり、無理に既存クラスへ押し込めず、専用の中間クラスを新設することで無矛盾性を回復できる
  • AND領域への対処は、中間クラスの新設以外にも、離散ラベル(排他性を前提にしたsingle-label)かマルチラベル(クラスごとに独立したlogit形式)かというラベル表現自体の選択でも解決できる
  • 特に意味の近いクラス同士は、inner-class・inter-classでの一貫性チェックと、境界専用データセットが有効
  • shifted positive・adversarial negatives・Truncated Negative・Hidden Negativeなど、hard caseの作り方には複数の手法があり、組み合わせ数を数えることでデータのかさ増し効果も見積もれる
  • NoneクラスやNegationスロットの設計によって、明示的な負例の識別や否定表現の混同を防げる
  • メタクラスという観点では、None(負例)・OOD(分布外)・Impossible(分類不能な入力)の3種類があり、特にImpossibleを切り出しておくと、性能低下の原因がクラス設計の問題か壊れた入力かを切り分けられる
  • ラベルにはGold(人手検証済み、高品質・高コスト)とSilver(自動生成、大量・ノイズあり)の信頼度差があり、Trainは混ぜて量を確保、Diag・Testはなるべく Goldを使うという使い分けが重要
  • クラス・属性の管理は、直交する(フォルダ管理)・直交しない(Tag.json)・対称的(Pair.json)という性質ごとに、適した方法を使い分ける
  • 実際のフォルダ構成例として、grade×class×subclassの多クラス分類と、source軸を起点にした二値分類の2パターンを示した

参考文献

Built with Hugo
テーマ Stack は Jimmy によって設計されています。