Aprendizaje activo para la anotación de datos: Guía de Gemini + Adala

Marco Adala: aprendizaje activo para la anotación de datos

El aprendizaje activo transforma la forma en que entrenamos AI modelos Seleccionando inteligentemente los datos más valiosos para la anotación. Al combinarse con LLM potentes San Pancho Google GéminisCrea canales de anotación eficientes que reducen el esfuerzo manual y mantienen una alta calidad de los datos.

Esta guía explora cómo construir dichas tuberías utilizando el Marco de Adala – una herramienta poderosa pero subutilizada para etiquetado de datos autónomo.

Implementaremos un clasificador de síntomas médicos que aprovecha Gemini's capacidades a través de un flujo de trabajo de aprendizaje activo estructurado.

Comprensión del aprendizaje activo para la anotación de datos

Comprensión del aprendizaje activo para la anotación de datos

El aprendizaje activo aborda el desafío clave en aprendizaje supervisadoObtención de grandes cantidades de datos etiquetados. En lugar de seleccionar aleatoriamente puntos de datos para su anotación, algoritmos de aprendizaje activo Identificar las muestras más informativas que contribuirán más a la mejora del modelo.

Por qué es importante el aprendizaje activo:

Reduce los costos de anotación al concentrar el esfuerzo humano donde más importa.
Mejora precisión del modelo con menos ejemplos etiquetados.
Aborda el desequilibrio de clases priorizando las categorías subrepresentadas.
Crea un ciclo de aprendizaje continuo entre el modelo y anotador.

El marco Adala incorpora estos beneficios a flujos de trabajo de producción Al proporcionar componentes modulares que agilizan la proceso de aprendizaje activoAntes de sumergirnos en la implementación, dejemos que...'s Examinar qué hace que Adala sea especialmente adecuada para de contacto con LLM modernos como Google Gemini.

¿Qué es Adala? Introducción al marco

Adala (Agente Autónomo de Etiquetado de Datos) es un marco de código abierto Diseñado específicamente para implementar agentes especializados para proceso de datosA diferencia de las herramientas de anotación tradicionales, Adala adopta un enfoque basado en agentes que combina:

Arquitectura basada en habilidades:Defina las capacidades específicas que necesita su agente de anotación.
Flexibilidad en tiempo de ejecución:Cambie entre diferentes LLM o tiempos de ejecución personalizados.
Conexiones con el medio ambiente:Interactuar con diversas fuentes de datos.
Bucles de aprendizaje integrados:Capacitar a los agentes para que mejoren con el tiempo.

Mirando a Adala's Ejemplo de inicio rápido, podemos ver cómo se estructura clasificación de sentimiento:

pitón

import pandas as pd
from adala.agents import Agent
from adala.environments import StaticEnvironment
from adala.skills import ClassificationSkill
from adala.runtimes import OpenAIChatRuntime
from rich import print

# Train dataset
train_df = pd.DataFrame([
    ["It was the negative first impressions, and then it started working.", "Positive"],
    ["Not loud enough and doesn't turn on like it should.", "Negative"],
    ["I don't know what to say.", "Neutral"],
    ["Manager was rude, but the most important that mic shows very flat frequency response.", "Positive"],
    ["The phone doesn't seem to accept anything except CBR mp3s.", "Negative"],
    ["I tried it before, I bought this device for my son.", "Neutral"],
], columns=["text", "sentiment"])

# Test dataset
test_df = pd.DataFrame([
    "All three broke within two months of use.",
    "The device worked for a long time, can't say anything bad.",
    "Just a random line of text."
], columns=["text"])

agent = Agent(
    # connect to a dataset
    environment=StaticEnvironment(df=train_df),
    # define a skill
    skills=ClassificationSkill(
        name='sentiment',
        instructions="Label text as positive, negative or neutral.",
        labels=["Positive", "Negative", "Neutral"],
        input_template="Text: {text}",
        output_template="Sentiment: {sentiment}"
    ),
    # define runtimes
    runtimes = {
        'openai': OpenAIChatRuntime(model='gpt-4o'),
    },
    teacher_runtimes = {
        'default': OpenAIChatRuntime(model='gpt-4o'),
    },
    default_runtime='openai',
)

agent.learn(learning_iterations=3, accuracy_threshold=0.95)
predictions = agent.run(test_df)

Para nuestra tarea de clasificación de síntomas médicos, adaptaremos esta arquitectura para integrar Google Géminis mientras se implementa una estrategia de aprendizaje activo personalizada.

Configuración de su entorno

Deje que's Comience instalando Adala y las dependencias necesarias:

pitón

# Install Adala directly from GitHub
!pip install -q git+https://github.com/HumanSignal/Adala.git

# Verify installation
!pip list | grep adala

# Install additional dependencies
!pip install -q google-generativeai pandas matplotlib numpy

También necesitaremos clonar el repositorio para tener acceso directo a sus componentes:

pitón

# Clone the repository for access to source files
!git clone https://github.com/HumanSignal/Adala.git

# Ensure the package is in our Python path
import sys
sys.path.append('./Adala')

# Import key components
from Adala.adala.annotators.base import BaseAnnotator
from Adala.adala.strategies.random_strategy import RandomStrategy
from Adala.adala.utils.custom_types import TextSample, LabeledSample

Integración de Google Gemini como anotador personalizado

A diferencia de la implementación original que utilizaba un contenedor básico alrededor de Google Gemini, crearemos uno más anotador robusto que sigue a Adala's Patrones de diseño. Esto hace que nuestra solución sea más mantenible y extensible.

Primero, necesitamos configurar Google Generative AI cliente:

pitón

import google.generativeai as genai
import os

# Set API key from environment or enter manually
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") or getpass("Enter your Gemini API Key: ")
genai.configure(api_key=GEMINI_API_KEY)

Ahora, crearemos un anotador personalizado extendiendo Adala's Clase BaseAnnotator:

pitón

import json
import re
from typing import List, Dict, Any, Optional

class GeminiAnnotator(BaseAnnotator):
    """Custom annotator using Google Gemini for medical symptom classification."""
    
    def __init__(self, 
                 model_name: str = "models/gemini-2.0-flash-lite", 
                 categories: List[str] = None,
                 temperature: float = 0.1):
        """Initialize the Gemini annotator.
        
        Args:
            model_name: The Gemini model to use
            categories: List of valid classification categories
            temperature: Controls randomness in generation (lower = more deterministic)
        """
        self.model = genai.GenerativeModel(
            model_name=model_name,
            generation_config={"temperature": temperature}
        )
        self.categories = categories or ["Cardiovascular", "Respiratory", 
                                         "Gastrointestinal", "Neurological"]
    
    def _build_prompt(self, text: str) -> str:
        """Create a structured prompt for the model.
        
        Args:
            text: The symptom text to classify
            
        Returns:
            A formatted prompt string
        """
        return f"""Classify this medical symptom into one of these categories:
        {', '.join(self.categories)}.
        
        Return JSON format: {{"category": "selected_category", 
        "confidence": 0.XX, "explanation": "brief_reason"}}
        
        SYMPTOM: {text}"""
    
    def _parse_response(self, response: str) -> Dict[str, Any]:
        """Extract structured data from model response.
        
        Args:
            response: Raw text response from Gemini
            
        Returns:
            Dictionary containing parsed fields
        """
        try:
            # Extract JSON from response even if surrounded by text
            json_match = re.search(r'(\{.*\})', response, re.DOTALL)
            result = json.loads(json_match.group(1) if json_match else response)
            return {
                "category": result.get("category", "Unknown"),
                "confidence": result.get("confidence", 0.0),
                "explanation": result.get("explanation", "")
            }
        except Exception as e:
            return {
                "category": "Unknown",
                "confidence": 0.0,
                "explanation": f"Error parsing response: {str(e)}"
            }
    
    def annotate(self, samples: List[TextSample]) -> List[LabeledSample]:
        """Annotate a batch of text samples.
        
        Args:
            samples: List of TextSample objects
            
        Returns:
            List of LabeledSample objects with annotations
        """
        results = []
        for sample in samples:
            prompt = self._build_prompt(sample.text)
            try:
                response = self.model.generate_content(prompt).text
                parsed = self._parse_response(response)
                
                # Create labeled sample with metadata
                labeled_sample = LabeledSample(
                    text=sample.text,
                    labels=parsed["category"],
                    metadata={
                        "confidence": parsed["confidence"],
                        "explanation": parsed["explanation"]
                    }
                )
            except Exception as e:
                # Graceful error handling
                labeled_sample = LabeledSample(
                    text=sample.text,
                    labels="Unknown",
                    metadata={"error": str(e)}
                )
            
            # Store reference to original sample
            labeled_sample._sample = sample
            results.append(labeled_sample)
            
        return results

Esta implementación proporciona mejoras significativas con respecto al original:

  1. Sigue la herencia de clase adecuada de Adala.'s Anotador base
  2. Implementa métodos auxiliares privados para la creación rápida y el análisis de respuestas.
  3. Usos estructurados manejo de errores y sugerencias de tipo
  4. Proporciona documentación completa

Creación de una canalización de clasificación de síntomas

Deje que's crear un conjunto de datos de sintomas medicos para nuestra tarea de clasificación. A diferencia de la implementación original, utilizaremos un conjunto de datos más diverso con representación equilibrada en todas las categorías:

pitón

# Create a more comprehensive dataset
symptom_data = [
    # Cardiovascular symptoms
    "Chest pain radiating to left arm during exercise",
    "Heart palpitations when lying down",
    "Swollen ankles and shortness of breath",
    "Dizziness when standing up quickly",
    
    # Respiratory symptoms
    "Persistent dry cough with occasional wheezing",
    "Shortness of breath when climbing stairs",
    "Coughing up yellow or green mucus",
    "Rapid breathing with chest tightness",
    
    # Gastrointestinal symptoms
    "Stomach cramps and nausea after eating",
    "Burning sensation in upper abdomen",
    "Frequent loose stools with abdominal pain",
    "Yellowing of skin and eyes",
    
    # Neurological symptoms
    "Severe headache with sensitivity to light",
    "Numbness in fingers of right hand",
    "Memory loss and confusion",
    "Tremors in hands when reaching for objects"
]

# Convert to TextSample objects
text_samples = [TextSample(text=text) for text in symptom_data]

Implementación de estrategias avanzadas de aprendizaje activo

La implementación original utilizaba un mecanismo simple de puntuación por prioridad. Lo mejoraremos con múltiples estrategias para demostrar Adala.'s flexibilidad:

pitón

import numpy as np
from typing import List, Callable

class PrioritizationStrategy:
    """Base class for sample prioritization strategies."""
    
    def score_samples(self, samples: List[TextSample]) -> np.ndarray:
        """Assign priority scores to samples.
        
        Args:
            samples: List of samples to score
            
        Returns:
            Array of scores, higher values indicate higher priority
        """
        raise NotImplementedError("Subclasses must implement this method")
    
    def select(self, samples: List[TextSample], n: int = 1) -> List[TextSample]:
        """Select the top n highest scoring samples.
        
        Args:
            samples: List of samples to select from
            n: Number of samples to select
            
        Returns:
            List of selected samples
        """
        if not samples:
            return []
        
        scores = self.score_samples(samples)
        indices = np.argsort(-scores)[:n]  # Descending order
        return [samples[i] for i in indices]

class KeywordPriority(PrioritizationStrategy):
    """Prioritize samples based on medical urgency keywords."""
    
    def __init__(self, keyword_weights: Dict[str, float]):
        """Initialize with keyword weights.
        
        Args:
            keyword_weights: Dictionary mapping keywords to priority weights
        """
        self.keyword_weights = keyword_weights
    
    def score_samples(self, samples: List[TextSample]) -> np.ndarray:
        scores = np.zeros(len(samples))
        for i, sample in enumerate(samples):
            # Base score
            scores[i] = 0.1
            
            # Add weights for each keyword found
            text_lower = sample.text.lower()
            for keyword, weight in self.keyword_weights.items():
                if keyword in text_lower:
                    scores[i] += weight
        
        return scores

class UncertaintyPriority(PrioritizationStrategy):
    """Prioritize samples based on model uncertainty."""
    
    def __init__(self, model_fn: Callable[[List[TextSample]], List[float]]):
        """Initialize with uncertainty model function.
        
        Args:
            model_fn: Function that returns uncertainty scores for samples
        """
        self.model_fn = model_fn
    
    def score_samples(self, samples: List[TextSample]) -> np.ndarray:
        # Higher uncertainty = higher priority
        return np.array(self.model_fn(samples))

# Create a combined strategy
keyword_weights = {
    "chest": 0.5,
    "pain": 0.4,
    "breathing": 0.4, 
    "dizz": 0.3,
    "head": 0.2,
    "numb": 0.2
}

keyword_strategy = KeywordPriority(keyword_weights)

Ahora deja's Implementar nuestro ciclo de aprendizaje activo mejorado:

pitón

from matplotlib import pyplot as plt
from IPython.display import clear_output
import time

def run_active_learning_loop(
    samples: List[TextSample],
    annotator: GeminiAnnotator,
    strategy: PrioritizationStrategy,
    iterations: int = 5,
    batch_size: int = 1,
    visualization_interval: int = 1
):
    """Run an active learning loop with visualization.
    
    Args:
        samples: Pool of unlabeled samples
        annotator: Annotation system
        strategy: Sample selection strategy
        iterations: Number of learning iterations
        batch_size: Samples to annotate per iteration
        visualization_interval: How often to update visualizations
    
    Returns:
        List of labeled samples
    """
    labeled_samples = []
    remaining_samples = list(samples)
    
    print("\nStarting Active Learning Loop:")
    
    for i in range(iterations):
        print(f"\n--- Iteration {i+1}/{iterations} ---")
        
        # Filter out already labeled samples
        remaining_samples = [
            s for s in remaining_samples 
            if s not in [getattr(l, '_sample', l) for l in labeled_samples]
        ]
        
        if not remaining_samples:
            print("No more samples to label. Stopping.")
            break
        
        # Select most important samples
        selected = strategy.select(remaining_samples, n=batch_size)
        
        # Annotate selected samples
        newly_labeled = annotator.annotate(selected)
        labeled_samples.extend(newly_labeled)
        
        # Display annotation results
        for sample in newly_labeled:
            print(f"Text: {sample.text}")
            print(f"Category: {sample.labels}")
            print(f"Confidence: {sample.metadata.get('confidence', 0):.2f}")
            explanation = sample.metadata.get('explanation', '')
            print(f"Explanation: {explanation[:100]}..." if len(explanation) > 100 else explanation)
            print()
        
        # Visualize results periodically
        if (i + 1) % visualization_interval == 0:
            visualize_results(labeled_samples)
            
    return labeled_samples

def visualize_results(labeled_samples: List[LabeledSample]):
    """Create visualizations of annotation results.
    
    Args:
        labeled_samples: List of labeled samples to visualize
    """
    if not labeled_samples:
        return
        
    # Extract data
    categories = [s.labels for s in labeled_samples]
    confidence = [s.metadata.get("confidence", 0) for s in labeled_samples]
    texts = [s.text[:30] + "..." for s in labeled_samples]
    
    # Set up plots
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
    
    # Plot 1: Confidence by category
    category_counts = {}
    category_confidence = {}
    
    for cat, conf in zip(categories, confidence):
        if cat not in category_counts:
            category_counts[cat] = 0
            category_confidence[cat] = 0
        category_counts[cat] += 1
        category_confidence[cat] += conf
    
    for cat in category_confidence:
        category_confidence[cat] /= category_counts[cat]
    
    cats = list(category_counts.keys())
    counts = list(category_counts.values())
    avg_conf = list(category_confidence.values())
    
    x = np.arange(len(cats))
    width = 0.35
    
    ax1.bar(x - width/2, counts, width, label='Count')
    ax1.bar(x + width/2, avg_conf, width, label='Avg Confidence')
    ax1.set_xticks(x)
    ax1.set_xticklabels(cats, rotation=45)
    ax1.set_title('Category Distribution and Confidence')
    ax1.legend()
    
    # Plot 2: Individual sample confidence
    sorted_indices = np.argsort(confidence)
    ax2.barh(range(len(texts)), [confidence[i] for i in sorted_indices])
    ax2.set_yticks(range(len(texts)))
    ax2.set_yticklabels([texts[i] for i in sorted_indices])
    ax2.set_title('Sample Confidence')
    ax2.set_xlabel('Confidence')
    
    plt.tight_layout()
    plt.show()

Ejecución del pipeline de extremo a extremo

Ahora podemos ejecutar nuestro proceso completo de aprendizaje activo:

pitón

# Initialize components
categories = ["Cardiovascular", "Respiratory", "Gastrointestinal", "Neurological"]
annotator = GeminiAnnotator(categories=categories)
strategy = keyword_strategy

# Run the active learning loop
labeled_data = run_active_learning_loop(
    samples=text_samples,
    annotator=annotator,
    strategy=strategy,
    iterations=5,
    visualization_interval=2
)

# Final visualization and analysis
visualize_results(labeled_data)

# Print summary statistics
print("\nAnnotation Summary:")
print(f"Total samples annotated: {len(labeled_data)}")

categories = [s.labels for s in labeled_data]
unique_categories = set(categories)
print(f"Categories found: {len(unique_categories)}")
for category in unique_categories:
    count = categories.count(category)
    print(f"  - {category}: {count} samples ({count/len(labeled_data):.1%})")

avg_confidence = sum(s.metadata.get("confidence", 0) for s in labeled_data) / len(labeled_data)
print(f"Average confidence: {avg_confidence:.2f}")

Aplicaciones prácticas y extensiones

Esta canalización tiene numerosas aplicaciones prácticas más allá de la clasificación de síntomas médicos:

1. Moderación de contenido

priorizar contenido reportado por el usuario
Centrarse en las categorías de alto riesgo
Adaptar los umbrales de confianza en función del tipo de contenido

2. Análisis de los comentarios de los clientes

Identificar urgencia problemas del cliente
Capturar problemas emergentes de productos
Envíe la retroalimentación a los equipos apropiados

3. Procesamiento de documentos de ensayos clínicos

Extraer informes de eventos adversos
clasificar los resultados informados por los pacientes
Priorizar las señales de seguridad

Puede ampliar esta implementación mediante:

Agregar un bucle de retroalimentación para mejorar el anotador
Implementar diferentes estrategias de selección (diversidad, clustering)
Creación de una interfaz web para la validación humana en el circuito
Habilitación clasificación multietiqueta para síntomas complejos

Conclusión

La integración de Adala y Google Gemini proporciona una marco poderoso para crear canales de anotación inteligentes. Al aprovechar la información activa aprendiendo estrategiasPodemos reducir drásticamente el esfuerzo manual requerido mientras mantenemos anotaciones de alta calidad.

Los patrones de diseño modular que se demuestran en este tutorial permiten Fácil adaptación a diferentes dominios y tareas de anotación.

Para aquellos interesados ​​en explorar más a fondo, el Repositorio de GitHub de Adala Ofrece ejemplos adicionales y documentación para ampliar estos conceptos a más escenarios de anotación complejos.

Deje un comentario

Su dirección de correo electrónico no será publicada. Las areas obligatorias están marcadas como requeridas *

Este sitio usa Akismet para reducir el correo no deseado. Conozca cómo se procesan los datos de sus comentarios.

Únete a los Aimojo ¡Tribu!

¡Únase a más de 76,200 miembros para recibir consejos exclusivos cada semana! 
🎁 BONUS: Obtenga nuestros $200 “AI “Mastery Toolkit” ¡GRATIS cuando te registras!

Tendencias AI Accesorios
IA a superescala

Convierte cualquier URL en una campaña publicitaria lista para lanzar en minutos. El AI Ad Agent está diseñado para profesionales del marketing de resultados y marcas centradas en el crecimiento.

tl;dv

Deja de olvidar lo que se dijo. Empieza a actuar en cada reunión. El AI Sistema para tomar notas de reuniones que registra las conversaciones y las convierte en información útil para la toma de decisiones.

Pregúntale a Yura

Convierta cada conversación con el cliente en una acción comercial completada. El No-Code AI Agente diseñado para la ejecución operativa

Kuberns

Implementa de forma más inteligente. Escala más rápido. Reduce los costes de la nube hasta en un 40 %. La plataforma PaaS en la nube con IA integrada está diseñada para una implementación completa sin configuración previa.

Uizardo

Convierte ideas en prototipos interactivos sin necesidad de tener ninguna habilidad de diseño. AI Herramienta de diseño de interfaz de usuario para wireframes, maquetas y prototipos de aplicaciones.

© Copyright 2023 - 2026 | Conviértete en un AI Pro | Hecho con ♥