Aktywne uczenie się adnotacji danych: przewodnik Gemini + Adala

Adala Framework — Aktywne uczenie się adnotacji danych

Aktywne uczenie się zmienia sposób, w jaki szkolimy AI modele poprzez inteligentny wybór najcenniejszych danych do adnotacji. W połączeniu z potężne LLM lubić Google Bliźnięta, tworzy wydajne procesy adnotacji, które redukują nakład pracy ręcznej, a jednocześnie zapewniają wysoką jakość danych.

W tym przewodniku opisano, jak budować takie rurociągi, korzystając z Ramka Adala – potężne, lecz niedostatecznie wykorzystywane narzędzie autonomiczne etykietowanie danych.

Wdrożymy klasyfikator objawów medycznych wykorzystujący Gemini's możliwości poprzez ustrukturyzowany, aktywny proces uczenia się.

Zrozumienie aktywnego uczenia się w adnotacjach danych

Zrozumienie aktywnego uczenia się w adnotacjach danych

Aktywne uczenie się rozwiązuje kluczowe wyzwanie w Nadzorowana nauka: uzyskiwanie dużych ilości oznaczonych danych. Zamiast losowego wybierania punktów danych do adnotacji, algorytmy aktywnego uczenia się zidentyfikować próbki najbardziej informatywne, które przyczynią się najbardziej do udoskonalenia modelu.

Dlaczego aktywne uczenie się jest ważne:

Zmniejsza koszty adnotacji, koncentrując wysiłek ludzki tam, gdzie jest to najbardziej potrzebne.
Poprawia dokładność modelu z mniejszą liczbą oznaczonych przykładów.
Rozwiązuje problem nierównowagi klasowej poprzez nadanie priorytetu niedoreprezentowanym kategoriom.
Tworzy ciągłą pętlę uczenia się pomiędzy modelem a adnotator.

Ramka Adala zapewnia te korzyści przepływy pracy produkcyjnej poprzez dostarczanie modułowych komponentów, które usprawniają aktywny proces uczenia sięZanim przejdziemy do realizacji, pozwól,'s sprawdź, co sprawia, że ​​Adala jest szczególnie odpowiednia integracja z nowoczesnymi programami LLM, takimi jak Google Gemini.

Czym jest Adala? Wprowadzenie do Framework

Adala (Autonomiczny Agent Etykietowania Danych) jest framework open source zaprojektowany specjalnie do wdrażania wyspecjalizowanych agentów analiza danychW przeciwieństwie do tradycyjnych narzędzi adnotacyjnych, Adala przyjmuje podejście oparte na agencie, które łączy:

Architektura oparta na umiejętnościach:Zdefiniuj konkretne możliwości, których potrzebuje Twój agent adnotacji.
Elastyczność środowiska wykonawczego:Możliwość przełączania się między różnymi LLM lub niestandardowymi środowiskami wykonawczymi.
Połączenia środowiskowe:Interakcja z różnymi źródłami danych.
Wbudowane pętle uczenia się:Szkolenie agentów w celu zapewnienia im możliwości doskonalenia się w miarę upływu czasu.

Patrząc na Adalę's przykład szybkiego startu, możemy zobaczyć jak to jest zbudowane klasyfikacja nastrojów:

pyton

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)

W ramach naszego zadania klasyfikacji objawów medycznych dostosujemy tę architekturę, aby zintegrować Google Bliźnięta wdrażając jednocześnie niestandardową strategię aktywnego uczenia się.

Konfigurowanie środowiska

Niech's zacznij od zainstalowania Adala i wymaganych zależności:

pyton

# 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

Będziemy musieli również sklonować repozytorium, aby uzyskać bezpośredni dostęp do jego komponentów:

pyton

# 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

Integracja Google Gemini jako niestandardowego adnotatora

W przeciwieństwie do pierwotnej implementacji, która wykorzystywała podstawowe opakowanie wokół Google Gemini, zbudujemy bardziej solidny adnotator który podąża za Adalą's wzorce projektowe. To sprawia, że ​​nasze rozwiązanie jest bardziej możliwe do utrzymania i rozszerzalne.

Najpierw musimy skonfigurować Generative Google AI klient:

pyton

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)

Teraz utworzymy niestandardowy adnotator, rozszerzając Adala's Klasa BaseAnnotator:

pyton

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

Ta implementacja zapewnia znaczące udoskonalenia w stosunku do oryginału:

  1. Następuje prawidłowe dziedziczenie klas z Adala's BazaAnnotator
  2. Implementuje prywatne metody pomocnicze do szybkiego budowania i analizy odpowiedzi
  3. Używa strukturyzowanego obsługa błędów i wpisz wskazówki
  4. Zapewnia kompletną dokumentację

Budowanie kanału klasyfikacji objawów

Niech's utwórz zbiór danych objawy medyczne dla naszego zadania klasyfikacji. W przeciwieństwie do pierwotnej implementacji, użyjemy bardziej zróżnicowanego zestawu danych z zrównoważona reprezentacja w różnych kategoriach:

pyton

# 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]

Wdrażanie zaawansowanych strategii aktywnego uczenia się

Oryginalna implementacja używała prostego mechanizmu punktacji priorytetów. Ulepszymy go za pomocą wielu strategii, aby zademonstrować Adala's elastyczność:

pyton

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)

Teraz pozwól's wdrożyć naszą ulepszoną pętlę aktywnego uczenia się:

pyton

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()

Uruchamianie potoku typu end-to-end

Teraz możemy uruchomić nasz kompletny proces aktywnego uczenia:

pyton

# 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}")

Zastosowania praktyczne i rozszerzenia

Ten rodzaj rurociągu ma wiele praktycznych zastosowań wykraczających poza klasyfikację objawów medycznych:

1. Moderacja treści

Priorytet treść zgłoszona przez użytkownika
Skup się na kategoriach wysokiego ryzyka
Dostosuj progi pewności na podstawie zawartości

2. Analiza opinii klientów

Zidentyfikuj pilne problemy klientów
Wychwytywanie pojawiających się problemów z produktem
Przekaż opinię odpowiednim zespołom

3. Przetwarzanie dokumentacji badań klinicznych

Wyodrębnij raporty zdarzeń niepożądanych
Klasyfikuj wyniki zgłaszane przez pacjentów
Nadaj priorytet sygnałom bezpieczeństwa

Możesz rozszerzyć tę implementację poprzez:

Dodanie pętli sprzężenia zwrotnego w celu ulepszenia adnotatora
Wdrażanie różnych strategii selekcji (różnorodność, klastrowanie)
Tworzenie interfejsu internetowego do walidacji z udziałem człowieka
Włączanie klasyfikacja wieloetykietowa w przypadku złożonych objawów

Wniosek

Integracja Adala i Google Gemini zapewnia potężny framework do budowania inteligentnych kanałów adnotacji. Wykorzystując aktywne strategie uczenia sięmożemy radykalnie zmniejszyć wymagany nakład pracy ręcznej, przy jednoczesnym zachowaniu wysokiej jakości adnotacje.

Modułowe wzorce projektowe zaprezentowane w tym samouczku umożliwiają: łatwa adaptacja do różnych domen i zadań adnotacyjnych.

Dla zainteresowanych dalszymi badaniami, Repozytorium Adala GitHub oferuje dodatkowe przykłady i dokumentację, aby rozszerzyć te koncepcje na więcej złożone scenariusze adnotacji.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Ta strona używa Akismet do redukcji spamu. Dowiedz się, w jaki sposób przetwarzane są Twoje dane dotyczące komentarzy.

Dołącz Aimojo Plemię!

Dołącz do ponad 76,200 XNUMX członków i otrzymuj co tydzień fachowe porady! 
???? BONUS: Odbierz nasze 200 dolarówAI „Zestaw narzędzi Mastery Toolkit” GRATIS po rejestracji!

Trendy AI Narzędzia
kajber

Zmień dźwięk, tekst i zdjęcia w oszałamiające AI Wygenerowany film Nieskończone płótno dla muzyków, artystów i twórców wizualnych

Sztuczna inteligencja DeepBrain

Utwórz profesjonalne AI Filmy awatara z tekstu w kilka minut AI Generator wideo stworzony z myślą o szybkości i skali

Sztuczna inteligencja Murfa

Klasa korporacyjna AI Generator głosu, który 10-krotnie skraca czas produkcji lektora Najszybsza platforma zamiany tekstu na mowę dla twórców, programistów i zespołów lokalizacyjnych.

płatność 

Zredukuj swój DSO i odzyskaj zaległe faktury szybciej dzięki AI Automatyzacja Platforma inteligentnej windykacji i należności

Workato AI

Zintegruj wszystkie aplikacje, agentów i przepływy pracy na jednej platformie automatyzacji przedsiębiorstwa iPaaS nr 1 dla AI Zaawansowana orkiestracja biznesowa

© Copyright 2023 - 2026 | Zostań AI Pro | Wykonane z ♥