主動學習
按模型不確定性重排 Potato 的標註佇列,包含五種查詢策略、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。在真實項目裡這兩個預設值都低到值得調高,因為每五條標註就重訓一次,算力花在了一個幾乎沒有變化的模型上。
完整配置
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 認得的寫法。前兩者的子鍵是 name 和 hyperparameters,第三個的子鍵是 enabled、save_directory 和 retention_count。用了別的子鍵名的塊會被忽略且不報錯,這次執行會悄悄退回預設值。
查詢策略
| 策略 | 說明 |
|---|---|
uncertainty | 模型最沒把握的實例。預設值 |
diversity | 與已標註內容最不相似的實例 |
badge | Batch Active learning by Diverse Gradient Embeddings |
bald | Bayesian Active Learning by Disagreement |
hybrid | 不確定性與多樣性的加權組合 |
active_learning:
query_strategy: uncertainty無法識別的策略名不會讓啟動失敗,而是帶一條警告退回 uncertainty,所以某個策略看起來沒起作用時,去看日誌。
調節 hybrid 和 bald
hybrid 預設按 70% 不確定性、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。
| 分類器 | 路徑 | 適用場景 | 速度 |
|---|---|---|---|
| 邏輯迴歸 | sklearn.linear_model.LogisticRegression | 多數文本任務 | 快 |
| 隨機森林 | sklearn.ensemble.RandomForestClassifier | 非線性模式 | 中等 |
| SVC | sklearn.svm.SVC | 小資料集 | 慢 |
| 多項式樸素貝葉斯 | 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樸素貝葉斯,用在速度比最後一點精度更重要的時候:
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: 20由 LLM 輔助選擇
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 會退回自報置信度。
模型持久化
訓練好的模型可以在重啟後留下來,不必從頭重建:
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: true與 AI 輔助組合使用
主動學習決定接下來展示什麼,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 許可權的角色。
實踐建議
先攢夠基線資料
空集上訓練不出任何東西,而用二十條標註訓出來的模型,重排的多半是噪聲:
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,以及每個類別是否至少有一個樣例。只有一個類別的訓練集擬合不出分類器。
重排看起來沒有效果
去日誌裡找有沒有無法識別的 query_strategy,它會悄悄退回 uncertainty。確認 enabled: true,並確認 schema_names 寫的方案確實存在。
池子很大時速度慢
調低 max_instances_to_reorder,調高 update_frequency,或者在詞表非常大時改用 HashingVectorizer。
延伸閱讀
實現細節見原始碼文件。