能動学習
Potatoのアノテーションキューをモデルの不確実性で並べ替えます。5つのクエリ戦略、sklearn分類器、コールドスタートの扱い、再起動をまたぐモデルの永続化に対応します。
能動学習はアノテーションキューを並べ替え、コーパスが届いた順に作業するのではなく、モデルが最も判断に迷うインスタンスをアノテーターに先に見せます。
仕組み
- 収集:最初のアノテーションを一定数集める
- 学習:これまでにラベル付けされたデータで分類器を訓練する
- スコア付け:未ラベルのプールを不確実性でスコア付けする
- 並べ替え:最も不確実なインスタンスが先頭に来るようにキューを並べ替える
- アノテーション:優先されたインスタンスにアノテーションする
- 再学習:アノテーションが増えるにつれて定期的に再学習する
モデルが最もよく学ぶところにアノテーションの労力を割く
設定
基本設定
active_learning:
enabled: true
schema_names:
- sentiment
min_annotations_per_instance: 1
min_instances_for_training: 20
update_frequency: 50
max_instances_to_reorder: 1000min_instances_for_trainingのデフォルトは10、update_frequencyのデフォルトは5です。どちらも実際のプロジェクトでは引き上げる価値があるほど低い値です。5件のアノテーションごとに再学習すると、ほとんど変わっていないモデルに計算資源を費やすことになります。
完全な設定
active_learning:
enabled: true
schema_names:
- sentiment
min_annotations_per_instance: 1
min_instances_for_training: 20
update_frequency: 50
max_instances_to_reorder: 1000
# How disagreement between annotators resolves into one training label
resolution_strategy: majority_vote
# Fraction of the queue left in random order, so the model does not
# only ever see what it already found interesting
random_sample_percent: 0.2
classifier:
name: sklearn.linear_model.LogisticRegression
hyperparameters:
C: 1.0
max_iter: 1000
vectorizer:
name: sklearn.feature_extraction.text.TfidfVectorizer
hyperparameters:
max_features: 5000
ngram_range: [1, 2]
query_strategy: uncertainty
model_persistence:
enabled: true
save_directory: "models/"
retention_count: 5ネストしたclassifier、vectorizer、model_persistenceの各ブロックが文書化された形式であり、potato validate --strictが認識するのもこの形式です。最初の2つのサブキーはnameとhyperparameters、3つ目のサブキーはenabled、save_directory、retention_countです。これ以外のサブキー名を使ったブロックは警告なしに無視され、実行は黙ってデフォルトに戻ります。
クエリ戦略
| 戦略 | 説明 |
|---|---|
uncertainty | モデルの確信度が最も低いインスタンス。デフォルト |
diversity | すでにアノテーションされたものと最も似ていないインスタンス |
badge | Batch Active learning by Diverse Gradient Embeddings |
bald | Bayesian Active Learning by Disagreement |
hybrid | uncertaintyとdiversityの重み付き組み合わせ |
active_learning:
query_strategy: uncertainty認識できない戦略名は起動を失敗させず、警告を出してuncertaintyにフォールバックします。戦略が効いていないように見える場合はログを確認してください。
HybridとBALDの調整
hybridのデフォルトはuncertainty 70%、diversity 30%です:
active_learning:
query_strategy: hybrid
hybrid_weights:
uncertainty: 0.7
diversity: 0.3baldは小さなアンサンブルを訓練し、その内部での意見の不一致で順位を付けます:
active_learning:
query_strategy: bald
bald_params:
n_estimators: 5
bootstrap_fraction: 0.8分類器
分類器はsklearnのインポートパスで指定します。デフォルトはsklearn.linear_model.LogisticRegressionです。
| 分類器 | パス | 適した用途 | 速度 |
|---|---|---|---|
| Logistic Regression | sklearn.linear_model.LogisticRegression | ほとんどのテキストタスク | 高速 |
| Random Forest | sklearn.ensemble.RandomForestClassifier | 非線形なパターン | 中程度 |
| SVC | sklearn.svm.SVC | 小規模データセット | 低速 |
| Multinomial NB | sklearn.naive_bayes.MultinomialNB | 単純なテキスト分類 | 非常に高速 |
推奨される出発点であるロジスティック回帰:
active_learning:
classifier:
name: sklearn.linear_model.LogisticRegression
hyperparameters:
C: 1.0
max_iter: 1000判断境界が線形に近くない場合のランダムフォレスト:
active_learning:
classifier:
name: sklearn.ensemble.RandomForestClassifier
hyperparameters:
n_estimators: 100
max_depth: 10SVCには確率を出力するよう明示的に指定する必要があります。不確実性スコアは確率に依存するためです:
active_learning:
classifier:
name: sklearn.svm.SVC
hyperparameters:
kernel: rbf
probability: true精度の最後の1ポイントより速度が重要な場合のナイーブベイズ:
active_learning:
classifier:
name: sklearn.naive_bayes.MultinomialNB
hyperparameters:
alpha: 1.0calibrate_probabilitiesはデフォルトで有効です。不確実性サンプリングは予測確率で順位を付けるため、キャリブレーションされていない分類器は、自信を持って間違えている項目をすでに決着済みであるかのように扱ってしまいます。
ベクトライザー
デフォルトはsklearn.feature_extraction.text.TfidfVectorizerです。
TF-IDFによる重み付き特徴量:
active_learning:
vectorizer:
name: sklearn.feature_extraction.text.TfidfVectorizer
hyperparameters:
max_features: 5000
ngram_range: [1, 2]
stop_words: english単純な出現回数:
active_learning:
vectorizer:
name: sklearn.feature_extraction.text.CountVectorizer
hyperparameters:
max_features: 3000
ngram_range: [1, 1]保持しきれないほど大きな語彙にはハッシング:
active_learning:
vectorizer:
name: sklearn.feature_extraction.text.HashingVectorizer
hyperparameters:
n_features: 10000ngram_rangeはYAMLのリストとして書き、sklearnが期待するタプルに変換されます。そのため、ここでは[1, 2]で正しく、特別な構文は必要ありません。
コールドスタート
モデルがまだ存在しない段階では不確実性を測る対象がないため、最初のバッチはモデルなしで選ばれます:
active_learning:
cold_start_strategy: random
cold_start_batch_size: 20LLMによる選択支援
コールドスタート期間中、または分類器と並行して、LLMがインスタンスをスコア付けできます:
active_learning:
enabled: true
schema_names:
- sentiment
llm:
enabled: true
endpoint_type: vllm
base_url: http://localhost:8000/v1
model: meta-llama/Llama-3.2-3B-Instruct
confidence_method: verbalizedconfidence_methodは確信度スコアの求め方を決めます。このスコアが選択を左右するため、どれを選ぶかが重要です:
| 手法 | 仕組み | トレードオフ |
|---|---|---|
verbalized | モデルが自身の確信度を1-10のスケールで報告する | どこでも使えるが、一部のモデルでは信頼性が低い |
logprobs | トークンの対数確率から計算する | 最もよくキャリブレーションされるが、logprobsを返すエンドポイントが必要 |
consistency | 同じインスタンスを複数回問い合わせ、一致度でスコア付けする | どこでも使えるが、インスタンスごとにN回の呼び出しがかかる |
エンドポイントがlogprobsを返さない場合、logprobsはverbalizedの確信度にフォールバックします。
モデルの永続化
訓練済みモデルは、ゼロから作り直すのではなく再起動後も保持できます:
active_learning:
model_persistence:
enabled: true
save_directory: "models/"
retention_count: 5retention_countのデフォルトは2で、保存しておくモデル数の上限を決めます。
データベースによる永続化は設定できなくなりました。database_enabledとdatabase_configのキーは削除されました。その背後にあった層は、成功をログに記録するだけで何も保存しないスタブだったためです。実行履歴は現在常に記録され、設定は不要です。どちらのキーも、設定にまだ残っていても無視されます。
複数のスキーム
schema_namesには、モデルの訓練に使うアノテーションのスキームを列挙します。指定しない場合は、プロジェクトのラベル付け可能なスキームがデフォルトになります:
annotation_schemes:
- annotation_type: radio
name: sentiment
description: "What is the sentiment?"
labels: [Positive, Negative, Neutral]
- annotation_type: radio
name: topic
description: "What is the topic?"
labels: [Politics, Sports, Tech, Entertainment]
active_learning:
enabled: true
schema_names:
- sentiment
- topic完全な設定例
annotation_task_name: "Sentiment Analysis with Active Learning"
task_dir: "."
port: 8000
data_files:
- "data/reviews.json"
item_properties:
id_key: id
text_key: text
annotation_schemes:
- annotation_type: radio
name: sentiment
description: "What is the sentiment?"
labels:
- Positive
- Negative
- Neutral
sequential_key_binding: true
active_learning:
enabled: true
schema_names:
- sentiment
min_annotations_per_instance: 1
min_instances_for_training: 30
update_frequency: 50
max_instances_to_reorder: 500
random_sample_percent: 0.2
classifier:
name: sklearn.linear_model.LogisticRegression
hyperparameters:
C: 1.0
max_iter: 1000
vectorizer:
name: sklearn.feature_extraction.text.TfidfVectorizer
hyperparameters:
max_features: 5000
ngram_range: [1, 2]
query_strategy: uncertainty
model_persistence:
enabled: true
save_directory: "models/"
retention_count: 5
output_annotation_dir: "output/"
export_annotation_format: jsonl
user_config:
allow_all_users: trueAIサポートとの組み合わせ
能動学習は次に何を表示するかを決めます。AIサポートは画面に表示されているものについてアノテーターを支援します。両者は独立しており、組み合わせて使えます:
active_learning:
enabled: true
schema_names:
- sentiment
min_instances_for_training: 30
ai_support:
enabled: true
endpoint_type: openai
ai_config:
model: gpt-4o-mini
api_key: ${OPENAI_API_KEY}
max_tokens: 800
include:
all: true結果の解釈には注意してください。モデルがラベルを提案してアノテーターがそれを受け入れ、しかも同系統のモデルがそのインスタンスを選んでいた場合、最後に測定する一致度の一部はモデルが自分自身と一致した分です。
監視
管理者ダッシュボードには、モデルの精度、学習サイクル数、不確実性の分布、残りのインスタンス数が表示されます。アクセスには管理者キー、またはview_admin_dashboardを持つロールが必要です。
ベストプラクティス
まずベースラインを集める
空の集合では何も訓練できず、20件のアノテーションで訓練したモデルはほとんどノイズを並べ替えるだけです:
active_learning:
min_instances_for_training: 50クラスバランスに注意する
不確実性サンプリングは決定境界に集中するため、ラベル分布がコーパスの分布から偏ります。モデルの訓練にはそれで問題ありませんが、アノテーション済みサンプルをデータの記述として報告すると誤解を招きます。random_sample_percentがキューの一部を偏りのないまま残すのは、まさにこのためです。
再学習の頻度を上げすぎない
active_learning:
update_frequency: 100再起動をまたいでモデルを保持する
active_learning:
model_persistence:
enabled: true
save_directory: "models/"トラブルシューティング
学習が始まらない
アノテーション数がmin_instances_for_trainingに達しているか、すべてのクラスに少なくとも1つの例があるかを確認してください。1クラスしかない訓練セットでは分類器を学習できません。
並べ替えが効いていないように見える
ログで未知のquery_strategyがないか確認してください。未知の戦略は黙ってuncertaintyにフォールバックします。enabled: trueになっていること、schema_namesが実際に存在するスキームを指していることも確認してください。
プールが大きいと遅い
max_instances_to_reorderを減らすか、update_frequencyを増やすか、非常に大きな語彙にはHashingVectorizerに切り替えてください。
関連情報
- AIサポート - アノテーション中のLLM支援
- タスク割り当て - その他の割り当て戦略
- 管理者ダッシュボード - 学習ループの監視
- 多様性に基づく並べ替え - 分類器を使わない埋め込みベースの並べ替え
実装の詳細については、ソースドキュメントを参照してください。