mercoledì 18 giugno 2025

Corso sulla Struttura dell’Intelligenza Artificiale: Creare una mini-AI autonoma


Creare una mini-AI autonoma

Obiettivo del modulo

Progettare, addestrare e deployare una micro-AI che svolge un compito ben definito (testo, immagini o decisioni), con pipeline completa: input → decisione AI → output → validazione, interfaccia d’uso (CLI, API o web), logging e salvataggio/ripristino dei pesi. Il percorso è hands-on e progressivo: si parte da un baseline semplice, poi si estende.


Scaletta passo-passo

🕐 Scoping e setup ambiente

  • Scegli il dominio:
    • Testo: classificatore di notizie (politica/sport/tech).
    • Immagini: generatore di descrizioni per immagini pre-caricate (feature estratte + template).
    • Decisioni: AI che suggerisce azioni su una checklist (regole+modello).
  • Definisci l’output: etichetta, punteggio, testo, raccomandazione con motivazione breve.
  • Setup: Python 3.10+, virtualenv, pacchetti minimi: pip install numpy pandas scikit-learn joblib fastapi uvicorn streamlit pydantic
  • Repo: struttura consigliata:
    mini_ai/
    ├─ data/ # dataset grezzi e processati
    ├─ models/ # pesi, vectorizer, versioni
    ├─ src/
    │ ├─ config.py
    │ ├─ preprocess.py
    │ ├─ model.py
    │ ├─ train.py
    │ ├─ eval.py
    │ ├─ serve_api.py # FastAPI
    │ └─ ui_streamlit.py # interfaccia web
    └─ logs/

🕑 Dati e metrica di successo

  • Raccolta: CSV con colonne minime (es. text,label per il testo; image_path,caption per immagini).
  • Split: train/val/test (70/15/15) con stratificazione per classi.
  • Metriche:
    • Classificazione: accuracy, F1 macro (classi sbilanciate), matrice di confusione.
    • Generazione (caption): BLEU/ROUGE (anche valutazione umana light: 1–5 coerenza).
    • Decisioni su checklist: precision@k e tasso di adozione (quante azioni proposte accettate).

🕒 Baseline funzionante (semplice & robusto)

Obiettivo: avere una prima versione end-to-end che produce un output coerente, anche se non perfetto.

  • Testo (consigliato per iniziare): CountVectorizer + Logistic Regression (veloce, solido, interpretabile).
    # src/train.py (estratto – baseline testo)
    import pandas as pd
    from sklearn.model_selection import train_test_split
    from sklearn.feature_extraction.text import CountVectorizer
    from sklearn.linear_model import LogisticRegression
    from sklearn.pipeline import Pipeline
    from sklearn.metrics import classification_report
    import joblib, os
    df = pd.read_csv("data/news.csv") # colonne: text,label
    train, test = train_test_split(df, test_size=0.2, stratify=df.label, random_state=42)
    pipe = Pipeline([
    ("vec", CountVectorizer(max_features=30000, ngram_range=(1,2))),
    ("clf", LogisticRegression(max_iter=200, n_jobs=-1))
    ])
    pipe.fit(train.text, train.label)
    pred = pipe.predict(test.text)
    print(classification_report(test.label, pred, digits=3))
    os.makedirs("models", exist_ok=True)
    joblib.dump(pipe, "models/news_baseline.joblib")
  • Immagini (baseline didattico): estrai feature con un backbone pre-addestrato (es. ResNet da torchvision), poi Nearest Neighbors per suggerire la caption dell’immagine più simile (semplice ma utile per il flusso end-to-end).
  • Decisioni: Rule-first + piccolo modello: regole deterministiche per i casi chiari; modello di classificazione binaria per consigliare “fai/non fare” dove le regole non bastano.

🕓 Validazione, error analysis, versioning

  • Valida sullo split di test; salva classification_report in logs/ con timestamp.
  • Errori ricorrenti: estrai i falsi positivi/negativi, crea una “lista nera” di pattern e una todo di miglioramenti (es. pulizia testo, stopword dominio-specifiche).
  • Versiona modelli/dati:
    # src/config.py
    MODEL_VERSION = "v1.0.0"
    ARTIFACT_DIR = f"models/{MODEL_VERSION}/"
    Salva anche le feature (vectorizer) e la configurazione usata (seed, parametri, vocabolario).

🕔 Interfacce d’uso (CLI, API, Web)

  • CLI (per uso locale/automazione):
    # src/model.py (inference)
    import joblib
    _pipe = joblib.load("models/news_baseline.joblib")
    def predict_text(txt: str):
    label = _pipe.predict([txt])[0]
    prob = max(_pipe.predict_proba([txt])[0])
    return {"label": label, "confidence": float(prob)}
    # cli.py
    import argparse
    from src.model import predict_text
    parser = argparse.ArgumentParser()
    parser.add_argument("--text", required=True)
    args = parser.parse_args()
    print(predict_text(args.text))
  • API (per integrazioni):
    # src/serve_api.py
    from fastapi import FastAPI
    from pydantic import BaseModel
    from src.model import predict_text
    app = FastAPI(title="Mini-AI API")
    class Item(BaseModel):
    text: str
    @app.post("/predict")
    def predict(item: Item):
    return predict_text(item.text)
    # Avvio: uvicorn src.serve_api:app --reload --port 8000
  • Web UI (demo rapida):
    # src/ui_streamlit.py
    import streamlit as st
    from src.model import predict_text
    st.title("🧠 Mini-AI Classificatore di Notizie")
    txt = st.text_area("Inserisci il testo della notizia")
    if st.button("Predici"):
    out = predict_text(txt)
    st.write(f"**Classe:** {out['label']} | **Confidenza:** {out['confidence']:.2f}")
    Avvio: streamlit run src/ui_streamlit.py

🕕 Logging, debugging, salvataggio/riuso pesi

  • Logging strutturato (JSON line per facile analisi):
    # src/logging_utils.py
    import json, time, os
    def log_event(event: dict, fname="logs/events.jsonl"):
    os.makedirs("logs", exist_ok=True)
    event["ts"] = time.time()
    with open(fname, "a", encoding="utf-8") as f:
    f.write(json.dumps(event, ensure_ascii=False) + "\n")
  • Usalo in API/UI:
    # dentro /predict
    res = predict_text(item.text)
    log_event({"route": "predict", "input_len": len(item.text), "output": res})
    return res
  • Salvataggio & ripristino: già visto con joblib; per reti neurali usa torch.save/model.save() (TF). Aggiungi checksum o hash del file e della config per riproducibilità.
  • Debugging:
    • stampa le top-n feature che “spingono” la predizione (es. coef_ di Logistic Regression) per audit.
    • logga eccezioni con exc_info=True, conserva input problematica in logs/bad_cases/.

🕖 Hardening & deploy

  • Seed & determinismo: imposta random_state ovunque per esperimenti ripetibili.
  • Config separata (.yaml o .json) per parametri (feature, modello, soglie).
  • Test: unit test su preprocess e su un paio di casi attesi del modello.
  • Docker (opzionale):
    # Dockerfile (minimal)
    FROM python:3.11-slim
    WORKDIR /app
    COPY requirements.txt .
    RUN pip install -r requirements.txt
    COPY . .
    CMD ["uvicorn", "src.serve_api:app", "--host", "0.0.0.0", "--port", "8000"]
  • Deploy: locale, VM, o PaaS (Railway/Render/Cloud Run). Esporre endpoint /predict; proteggi con chiave API se pubblico.

🔬 Lab guidato: micro-AI end-to-end

  1. Importa dati (CSV) e fai lo split con stratificazione.
  2. Addestra baseline (testo: CountVectorizer+LR) e salva pesi.
  3. Valida su test e salva report e matrice di confusione (immagine/CSV).
  4. Servi il modello via API FastAPI e prova con curl o Postman.
  5. Interfaccia Streamlit per demo; logga ogni richiesta.
  6. Itera: migliora preprocessing (stopword dominio-specifiche, n-grammi), confronta F1 e aggiorna versione (v1.1.0).

🧭 Design dell’autonomia: validazione & fallback

Evenienza reale: la mini-AI deve “sapere dire non so”. Aggiungi un validatore e un fallback:

  • Soglia di confidenza: se confidence < 0.55 → restituisci “richiedi conferma” o inoltra a regola/operatore.
  • Controlli di sicurezza: blocca input vuoti o troppo lunghi, rimuovi HTML/script.
  • Audit: salva i low-confidence per active learning e migliorare il dataset in seguito.

📈 Miglioramenti successivi (opzionali)

  • Text: TF-IDF, SVM, o DistilBERT (Hugging Face) con fine-tuning.
  • Immagini: CLIP per embedding e nearest neighbor con caption semantiche.
  • Decisioni: meta-policy: regole deterministiche + classificatore + spiegazioni (feature importanti) nel payload.

Nessun commento:

Posta un commento

Corso Fondamenti di Informatica e Reti: 6 Reti di computer e Internet

Reti di computer e Internet Introduzione Prova a pensare alla vita quotidiana senza reti informatiche: niente messaggi WhatsApp, niente m...