Skip to content

Aprendizado Ativo

Reordene a fila de anotação do Potato pela incerteza do modelo, com cinco estratégias de consulta, classificadores do sklearn, tratamento de partida a frio e persistência do modelo entre reinicializações.

O aprendizado ativo reordena a fila de anotação para que os anotadores vejam as instâncias sobre as quais um modelo tem menos certeza, em vez de percorrer o corpus na ordem em que ele chegou.

Como Funciona

  1. Colete um conjunto inicial de anotações
  2. Treine um classificador com o que foi rotulado até agora
  3. Pontue o conjunto não rotulado por incerteza
  4. Reordene a fila para colocar as instâncias mais incertas na frente
  5. Anote as instâncias priorizadas
  6. Retreine periodicamente à medida que as anotações se acumulam

O ciclo de aprendizagem ativa: treine no que está rotulado, pontue o conjunto não rotulado por incerteza, anote os itens mais incertos e retreineInvista o esforço de anotação onde o modelo mais aprende

Configuração

Configuração Básica

yaml
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

O padrão de min_instances_for_training é 10 e o de update_frequency é 5. Os dois padrões são baixos o bastante para valer a pena aumentá-los em um projeto real, já que retreinar a cada cinco anotações gasta processamento com um modelo que mal mudou.

Configuração Completa

yaml
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

Os blocos aninhados classifier, vectorizer e model_persistence são a forma documentada e a que o potato validate --strict reconhece. Suas subchaves são name e hyperparameters nos dois primeiros, e enabled, save_directory e retention_count no terceiro. Um bloco que usa outros nomes de subchave é ignorado sem aviso, e a execução volta silenciosamente aos valores padrão.

Estratégias de Consulta

EstratégiaDescrição
uncertaintyInstâncias em que o modelo tem menos confiança. É o padrão
diversityInstâncias menos parecidas com o que já foi anotado
badgeBatch Active learning by Diverse Gradient Embeddings
baldBayesian Active Learning by Disagreement
hybridUma combinação ponderada de incerteza e diversidade
yaml
active_learning:
  query_strategy: uncertainty

Um nome de estratégia não reconhecido volta para uncertainty com um aviso, em vez de impedir a inicialização. Por isso, confira o log se uma estratégia parecer não ter efeito.

Ajuste de Hybrid e BALD

Por padrão, hybrid usa 70% de incerteza e 30% de diversidade:

yaml
active_learning:
  query_strategy: hybrid
  hybrid_weights:
    uncertainty: 0.7
    diversity: 0.3

bald treina um pequeno ensemble e ordena pela discordância dentro dele:

yaml
active_learning:
  query_strategy: bald
  bald_params:
    n_estimators: 5
    bootstrap_fraction: 0.8

Classificadores

Os classificadores são indicados pelo caminho de importação do sklearn. O padrão é sklearn.linear_model.LogisticRegression.

ClassificadorCaminhoMelhor ParaVelocidade
Regressão Logísticasklearn.linear_model.LogisticRegressionA maioria das tarefas com textoRápido
Random Forestsklearn.ensemble.RandomForestClassifierPadrões não linearesMédio
SVCsklearn.svm.SVCConjuntos de dados pequenosLento
Multinomial NBsklearn.naive_bayes.MultinomialNBClassificação simples de textoMuito rápido

Regressão logística, o ponto de partida recomendado:

yaml
active_learning:
  classifier:
    name: sklearn.linear_model.LogisticRegression
    hyperparameters:
      C: 1.0
      max_iter: 1000

Random forest, quando a decisão não é aproximadamente linear:

yaml
active_learning:
  classifier:
    name: sklearn.ensemble.RandomForestClassifier
    hyperparameters:
      n_estimators: 100
      max_depth: 10

Um SVC precisa ser instruído a produzir probabilidades, já que a pontuação de incerteza depende delas:

yaml
active_learning:
  classifier:
    name: sklearn.svm.SVC
    hyperparameters:
      kernel: rbf
      probability: true

Naive Bayes, quando a velocidade importa mais do que o último ponto de acurácia:

yaml
active_learning:
  classifier:
    name: sklearn.naive_bayes.MultinomialNB
    hyperparameters:
      alpha: 1.0

calibrate_probabilities vem ativado por padrão. Isso importa porque a amostragem por incerteza ordena pela probabilidade prevista, e um classificador não calibrado trata itens em que erra com confiança como se estivessem resolvidos.

Vetorizadores

O padrão é sklearn.feature_extraction.text.TfidfVectorizer.

TF-IDF, características ponderadas:

yaml
active_learning:
  vectorizer:
    name: sklearn.feature_extraction.text.TfidfVectorizer
    hyperparameters:
      max_features: 5000
      ngram_range: [1, 2]
      stop_words: english

Contagens simples:

yaml
active_learning:
  vectorizer:
    name: sklearn.feature_extraction.text.CountVectorizer
    hyperparameters:
      max_features: 3000
      ngram_range: [1, 1]

Hashing, para um vocabulário grande demais para caber na memória:

yaml
active_learning:
  vectorizer:
    name: sklearn.feature_extraction.text.HashingVectorizer
    hyperparameters:
      n_features: 10000

ngram_range é escrito como uma lista YAML e convertido na tupla que o sklearn espera, então [1, 2] está correto aqui e não exige sintaxe especial.

Partida a Frio

Antes de existir um modelo, não há nada sobre o que ter incerteza, então o primeiro lote é escolhido sem modelo:

yaml
active_learning:
  cold_start_strategy: random
  cold_start_batch_size: 20

Seleção Assistida por LLM

Um LLM pode pontuar instâncias durante o período de partida a frio ou junto com o classificador:

yaml
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: verbalized

confidence_method define como a pontuação de confiança é obtida, e a escolha importa porque é essa pontuação que conduz a seleção:

MétodoComo funcionaContrapartida
verbalizedO modelo informa a própria confiança em uma escala de 1 a 10Universal, mas pouco confiável em alguns modelos
logprobsCalculado a partir das log-probabilidades dos tokensO mais bem calibrado, exige um endpoint que retorne logprobs
consistencyA mesma instância é consultada várias vezes e pontuada pela concordânciaFunciona em qualquer lugar, ao custo de N chamadas por instância

logprobs volta para a confiança verbalizada quando o endpoint não as retorna.

Persistência de Modelo

Os modelos treinados podem sobreviver a uma reinicialização em vez de serem reconstruídos do zero:

yaml
active_learning:
  model_persistence:
    enabled: true
    save_directory: "models/"
    retention_count: 5

O padrão de retention_count é 2, e ele limita quantos modelos salvos são mantidos.

A persistência em banco de dados não é mais configurável. As chaves database_enabled e database_config foram removidas porque a camada por trás delas era um stub que registrava sucesso e não armazenava nada. O histórico de execuções agora é sempre registrado e não precisa de configuração, e as duas chaves são ignoradas se uma configuração ainda as contiver.

Múltiplos Esquemas

schema_names lista os esquemas cujas anotações treinam o modelo. Se não for definido, o padrão são os esquemas rotuláveis do projeto:

yaml
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

Configuração Completa

yaml
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

Combinando com Suporte de IA

O aprendizado ativo decide o que mostrar em seguida. O suporte de IA ajuda o anotador com o que está na tela. Os dois são independentes e se combinam:

yaml
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

Leia o resultado com cuidado. Se o modelo sugere um rótulo, o anotador o aceita e a mesma família de modelos escolheu a instância, a concordância que você mede no final é, em parte, o modelo concordando consigo mesmo.

Monitoramento

O painel do administrador mostra a acurácia do modelo, a contagem de ciclos de treinamento, a distribuição da incerteza e quantas instâncias restam. Para acessá-lo é preciso a chave de administrador ou um papel que tenha view_admin_dashboard.

Boas Práticas

Colete uma Base Primeiro

Não é possível treinar nada com um conjunto vazio, e um modelo treinado com vinte anotações reordena principalmente ruído:

yaml
active_learning:
  min_instances_for_training: 50

Acompanhe o Equilíbrio de Classes

A amostragem por incerteza se concentra na fronteira de decisão, o que afasta a distribuição de rótulos da distribuição do corpus. Isso não é problema para treinar um modelo, mas é enganoso se você apresentar a amostra anotada como uma descrição dos dados. random_sample_percent mantém parte da fila sem viés exatamente por esse motivo.

Não Retreine com Muita Frequência

yaml
active_learning:
  update_frequency: 100

Mantenha os Modelos entre Reinicializações

yaml
active_learning:
  model_persistence:
    enabled: true
    save_directory: "models/"

Solução de Problemas

O treinamento nunca começa

Verifique se as anotações atingiram min_instances_for_training e se cada classe tem pelo menos um exemplo. Não é possível ajustar um classificador com um conjunto de treinamento de uma única classe.

A reordenação parece não fazer nada

Procure no log uma query_strategy desconhecida, que volta silenciosamente para a incerteza. Confirme enabled: true e que schema_names nomeia esquemas que de fato existem.

Lentidão com um conjunto grande

Reduza max_instances_to_reorder, aumente update_frequency ou passe a usar HashingVectorizer para um vocabulário muito grande.

Leitura Adicional

Para detalhes de implementação, consulte a documentação de origem.