NLP pro italský jazyk: Specifické výzvy a řešení
Italština je jedním z nejsložitějších románských jazyků z morfologického hlediska: gramatický rod, deklinace, shoda adjektiv-podstatné jméno, nepravidelné slovesné tvary a flexibilní syntaktická struktura umožňuje předzpracování a modelování NLP výrazně náročnější než angličtina. Přesto velká většina výukových programů NLP a angličtiny a nejznámější modely jsou často optimalizovány pro angličtinu.
Tento článek tuto mezeru zaplňuje. Prozkoumáme specifické výzvy italštiny, dostupné datové soubory, italské modely BERT (cítit to, Alberto, dbmdz BERT), specifické předzpracování pro italský jazyk, a jak vybudovat systém analýzy sentimentu pro italštinu krok za krokem.
Toto je čtvrtý díl série Moderní NLP: od BERT po LLM. A tam pouze série v italštině který konkrétně pokrývá předzpracování a NLP modelování pro italský jazyk.
Co se naučíte
- Morfologické problémy italštiny: rod, deklinace, nepravidelná slovesa
- Specifické předzpracování: Italská stopwords, lemmatizace pomocí spaCy, normalizace
- Italské modely BERT: feel-it-italian-sentiment, AlBERTo, dbmdz BERT, GilBERTo
- Datová sada pro italštinu: SENTIPOLC, TweetSent-IT, ItalianSentiment
- Jemné doladění vlastních dat
- Řízení hovorového jazyka, italských dialektů a neologismů
- Kompletní kanál pro analýzu sentimentu ohledně italských textů
- Porovnání italských a vícejazyčných modelů BERT
1. Specifické výzvy italštiny v NLP
Italština má lingvistické vlastnosti, díky kterým je NLP složitější ve srovnání s angličtinou. Pochopení těchto výzev je základem budování efektivní systémy.
1.1 Bohatá morfologie
Na rozdíl od angličtiny má italština a velmi bohatá morfologie: stejný slovesný kořen vytváří desítky tvarů a přídavná jména se obecně shodují a číslo s podstatnými jmény. To vytváří problémy s řídkostí v datech.
Příklad: Sloveso „Andare“ v italštině
- Jdu, jdu, jdu, jdeme, jdu, jdu (současnost)
- Šel jsem, šel jsi, šel jsi, šel jsi, šel jsi, šel jsi (nedokonalé)
- andro, andrai, andra, my půjdeme, ty půjdeš, oni půjdou (budoucnost)
- Šel jsem, šel jsi, šel jsem, šli jsme, ty jsi šel, oni šli (vzdálená minulost)
- odešla, odešla (minulý konjunktiv)
V angličtině má „to go“ velmi málo forem. U modelu NLP je každý tvar zpočátku jiný token.
1.2 Enklitika a složená slova
V italštině lze ke slovesu připojit zájmena (enklitika), vytváření složitých tokenů, se kterými si standardní tokenizéry špatně poradí.
# Problemi comuni con i tokenizzatori per l'italiano
# Enclitici: pronomi attaccati al verbo
examples = [
"Dimmelo", # dimmi + lo
"Portarmelo", # portare + mi + lo
"Fallo", # fai + lo
"Dateglielo", # date + glie + lo
]
# Truncation sbagliata con tokenizzatori non italiani
from transformers import BertTokenizer
tokenizer_en = BertTokenizer.from_pretrained('bert-base-uncased')
tokenizer_it = BertTokenizer.from_pretrained('dbmdz/bert-base-italian-cased')
word = "Dimmelo"
print(f"EN tokenizer: {tokenizer_en.tokenize(word)}")
# ['dim', '##mel', '##o'] - non coglie la struttura
print(f"IT tokenizer: {tokenizer_it.tokenize(word)}")
# ['Dim', '##me', '##lo'] - migliore ma non perfetto
# La soluzione ottimale e la lemmatizzazione prima del tokenize
1.3 Interpunkce a hovorový pravopis
V italských online textech (sociální média, recenze) najdeme:
- Akcenty nahrazeny apostrofy: „can“ místo „can“
- Opakované znaky: "krásné!!!"
- Typické zkratky: "cmq" (nicméně), "nn" (ne), "xke" (protože)
- Přepínání kódu s angličtinou: „Produkt je skutečně nejvyšší kvality“
- Regionální dialektismy: "mizzica" (sicilský), "mannaggia" (jižní)
2. Předzpracování specifické pro italštinu
2.1 spaCy pro italštinu
prostorovost nabízí šablonu pro italštinu (it_core_news_sm/md/lg)
s lemmatizací, POS tagováním a analýzou závislostí.
# Installa il modello italiano: python -m spacy download it_core_news_lg
import spacy
nlp = spacy.load("it_core_news_lg")
def preprocess_italian(text: str,
remove_stopwords: bool = True,
lemmatize: bool = True) -> str:
"""Preprocessing completo per testi italiani."""
doc = nlp(text)
tokens = []
for token in doc:
# Salta punteggiatura, spazi, numeri (se non rilevanti)
if token.is_punct or token.is_space:
continue
# Normalizza a minuscolo
word = token.text.lower()
# Rimuovi stopwords italiane
if remove_stopwords and token.is_stop:
continue
# Lemmatizza
if lemmatize:
word = token.lemma_.lower()
tokens.append(word)
return ' '.join(tokens)
# Test
texts = [
"I prodotti sono stati consegnati rapidamente e tutto funzionava perfettamente",
"Ho comprato questo telefono tre mesi fa e sono rimasto deluso dalla batteria",
"PRODOTTO FANTASTICO! Lo consiglio assolutamente a tutti voi amici!!!"
]
for text in texts:
processed = preprocess_italian(text)
print(f"Original: {text}")
print(f"Processed: {processed}")
print()
2.2 Normalizace neformálního textu
import re
import unicodedata
def normalize_italian_text(text: str) -> str:
"""
Normalizzazione per testi italiani informali (social media, recensioni).
"""
# 1. Normalizza unicode (accenti)
text = unicodedata.normalize('NFC', text)
# 2. Sostituisci accenti con apostrofo (comune online)
accent_map = {
"a'": "a", # può' -> può
"e'": "e'", # mantenuto per 'e' (voce del verbo essere)
"i'": "i",
"o'": "o",
"u'": "u"
}
# Non sostituiamo indiscriminatamente per evitare ambiguità
# 3. Espandi abbreviazioni comuni
abbreviations = {
r'\bcmq\b': 'comunque',
r'\bnn\b': 'non',
r'\bxke\b': 'perchè',
r'\bxche\b': 'perchè',
r'\bx\b': 'per',
r'\bke\b': 'che',
r'\bkm\b': 'come',
r'\bqs\b': 'questo',
r'\btv\b': 'televisione',
r'\bgg\b': 'giorni',
r'\bprof\b': 'professore',
}
for abbr, expanded in abbreviations.items():
text = re.sub(abbr, expanded, text, flags=re.IGNORECASE)
# 4. Rimuovi caratteri ripetuti eccessivi (bellissimoooo -> bellissimo)
text = re.sub(r'(.)\1{2,}', r'\1\1', text) # max 2 ripetizioni
# 5. Rimuovi emoji (opzionale - può essere informativo per il sentiment)
# text = re.sub(r'[^\w\s.,!?;:\'\"()-]', ' ', text)
# 6. Normalizza spazi multipli
text = re.sub(r'\s+', ' ', text).strip()
return text
# Test
informal_texts = [
"cmq il prodotto e' fantasticooo!!!",
"nn mi e piaciuto x niente, sto cercando di restituirlo xke nn funziona",
"Amici... COMPRATE QUESTOOO!!! e' il TOP del TOP!!!",
]
for text in informal_texts:
normalized = normalize_italian_text(text)
print(f"Originale: {text}")
print(f"Normalizzato: {normalized}")
print()
3. Modely BERT pro italštinu
K dispozici je několik modelů BERT předem vycvičených na italských korpusech. Výběr modelu závisí na konkrétní doméně a úkolu.
3.1 pocit-it-italský-sentiment
cítit to a specifický datový soubor a model pro analýzu sentimentu a detekce emocí v italštině. Je založen na Twitteru a byl na něm vyškolen manuální anotace pocitů (pozitivní/negativní) a emocí (radost, smutek, hněv, strach, znechucení, překvapení).
from transformers import pipeline, AutoTokenizer, AutoModelForSequenceClassification
import torch
# feel-it per sentiment (positivo/negativo)
sentiment_model = pipeline(
"text-classification",
model="MilaNLProc/feel-it-italian-sentiment",
tokenizer="MilaNLProc/feel-it-italian-sentiment"
)
# feel-it per emozioni (gioia, tristezza, rabbia, paura, disgusto, sorpresa)
emotion_model = pipeline(
"text-classification",
model="MilaNLProc/feel-it-italian-emotion",
tokenizer="MilaNLProc/feel-it-italian-emotion"
)
# Test su testi italiani
texts = [
"Sono molto felice del mio acquisto, qualità eccellente!",
"Ho perso tutto il mio lavoro, sono devastato.",
"Questa e la situazione più ridicola che abbia mai visto.",
"Non credevo che potesse funzionare cosi bene, sono stupito!",
]
print("=== SENTIMENT ===")
for text in texts:
result = sentiment_model(text)[0]
print(f" [{result['label']}: {result['score']:.3f}] {text[:60]}")
print("\n=== EMOTION ===")
for text in texts:
result = emotion_model(text)[0]
print(f" [{result['label']}: {result['score']:.3f}] {text[:60]}")
3.2 AlBERTo: BERT pro italská sociální média
Alberto a byl předem vyškolen na korpus italských tweetů (přes 200 milionů tweetů). Je zvláště účinný pro neformální texty, sociální sítě a italský hovorový jazyk.
from transformers import AutoTokenizer, AutoModel
import torch
# AlBERTo - BERT uncased per Twitter italiano
alberto_name = "m-polignano-uniba/bert_uncased_L-12_H-768_A-12_Italian_alb3rt0"
tokenizer = AutoTokenizer.from_pretrained(alberto_name)
model = AutoModel.from_pretrained(alberto_name)
# Test di tokenizzazione su testo colloquiale
informal_texts = [
"PRODOTTO TOP! ma la spedizione ha fatto schifo cmq",
"mizzica quanto e bello sto telefono!! ci ho messo 2gg ma ne valeva la pena",
"ok mi avete rotto... non lo compro più #delusione",
]
for text in informal_texts:
tokens = tokenizer.tokenize(text)
print(f"Testo: {text[:50]}")
print(f"Tokens ({len(tokens)}): {tokens[:10]}...")
print()
# Estrazione embeddings
def get_sentence_embedding(text, model, tokenizer, pooling='cls'):
inputs = tokenizer(text, return_tensors='pt',
truncation=True, max_length=128, padding=True)
with torch.no_grad():
outputs = model(**inputs)
if pooling == 'cls':
return outputs.last_hidden_state[:, 0, :] # [CLS] token
elif pooling == 'mean':
mask = inputs['attention_mask'].unsqueeze(-1)
return (outputs.last_hidden_state * mask).sum(1) / mask.sum(1)
emb = get_sentence_embedding(informal_texts[0], model, tokenizer)
print(f"Embedding shape: {emb.shape}") # (1, 768)
3.3 dbmdz BERT anglicky
Modelka dbmdz/bert-base-italian-cased a byli předem vycvičeni na italské Wikipedii a v korpusu OPUS. A nejlepší výchozí bod pro formální texty (novinky, právní dokumenty, odborné texty).
from transformers import BertTokenizer, BertForSequenceClassification
from transformers import TrainingArguments, Trainer
from datasets import Dataset
import torch
# Modello base per l'italiano
MODEL = "dbmdz/bert-base-italian-cased"
tokenizer = BertTokenizer.from_pretrained(MODEL)
# Crea un classificatore di sentiment per l'italiano
model = BertForSequenceClassification.from_pretrained(
MODEL,
num_labels=2,
id2label={0: "NEGATIVO", 1: "POSITIVO"},
label2id={"NEGATIVO": 0, "POSITIVO": 1}
)
# Dataset di esempio in italiano
train_data = {
"text": [
"Il prodotto e arrivato in perfette condizioni, molto soddisfatto",
"qualità pessima, si e rotto dopo due giorni",
"Eccellente rapporto qualità/prezzo, lo consiglio",
"Imballaggio scarso, prodotto danneggiato alla consegna",
"Supera le aspettative, ottimo acquisto",
"Servizio clienti inesistente, rimborso impossibile",
"Materiali di qualità, costruzione solida",
"Non corrisponde alla descrizione, immagine ingannevole",
],
"label": [1, 0, 1, 0, 1, 0, 1, 0]
}
def tokenize_fn(examples):
return tokenizer(examples["text"], truncation=True,
padding="max_length", max_length=128)
dataset = Dataset.from_dict(train_data)
tokenized = dataset.map(tokenize_fn, batched=True)
# Training veloce (pochi dati = pochissime epoche)
args = TrainingArguments(
output_dir="./models/bert-italian-sentiment",
num_train_epochs=5,
per_device_train_batch_size=8,
learning_rate=3e-5,
warmup_ratio=0.1,
weight_decay=0.01,
save_steps=100,
logging_steps=10,
report_to="none"
)
trainer = Trainer(
model=model,
args=args,
train_dataset=tokenized,
)
trainer.train()
3.4 Porovnání italských modelů
Který model použít?
| Model | Optimální doména | Lepší úkoly | Velikost |
|---|---|---|---|
| pocit-to-sentiment | Sociální sítě, názory | Sentiment, detekce emocí | ~440 MB |
| pocit-to-emoce | Sociální sítě, názory | 6 základních emocí | ~440 MB |
| Alberto | Twitter, chat, SMS | Sentiment, NER, klasifikace | ~420 MB |
| dbmdz BERT pouzdro | Zprávy, formální dokumenty | NER, klasifikace, QA | ~420 MB |
| GilBERTo | Italské obecné texty | Obecné úlohy NLU | ~440 MB |
| mBERT | Cross-lingual | Vícejazyčné přenosové učení | ~670 MB |
4. Italské datové soubory pro analýzu sentimentu
from datasets import load_dataset
# SENTIPOLC 2016 - dataset italiano per polarity detection su Twitter
# Disponibile su: http://www.di.unito.it/~tutreeb/sentipolc-evalita16/
# Etichette: OBJ (oggettivo), POS (positivo), NEG (negativo), MIX
# Dataset disponibile su HuggingFace
try:
dataset = load_dataset("gsarti/itacola")
print("ITA-CoLA dataset:", dataset)
except Exception:
print("Dataset non disponibile direttamente, usa URL manuale")
# Costruzione dataset personalizzato da CSV
import pandas as pd
from datasets import Dataset
# Esempio: caricare recensioni italiane da CSV
# Formato atteso: colonne 'text' e 'label'
def load_italian_dataset(csv_path):
df = pd.read_csv(csv_path)
# Validazione
assert 'text' in df.columns, "Manca colonna 'text'"
assert 'label' in df.columns, "Manca colonna 'label'"
# Rimuovi righe con testo vuoto
df = df.dropna(subset=['text', 'label'])
df = df[df['text'].str.strip() != '']
# Normalizza etichette
label_map = {
'positivo': 1, 'pos': 1, '1': 1, 1: 1,
'negativo': 0, 'neg': 0, '0': 0, 0: 0
}
df['label'] = df['label'].map(label_map)
df = df.dropna(subset=['label'])
df['label'] = df['label'].astype(int)
return Dataset.from_pandas(df[['text', 'label']])
5. Kompletní potrubí pro italštinu
Vše integrujeme do produkčního potrubí pro analýzu sentimentu v italštině.
import re
import spacy
from transformers import pipeline as hf_pipeline
from typing import Optional
import unicodedata
class ItalianSentimentPipeline:
"""
Pipeline completa per il sentiment analysis in italiano.
Combina preprocessing specifico e feel-it per il sentiment.
"""
def __init__(self,
sentiment_model: str = "MilaNLProc/feel-it-italian-sentiment",
emotion_model: Optional[str] = "MilaNLProc/feel-it-italian-emotion",
use_spacy: bool = True,
confidence_threshold: float = 0.6):
# Carica modelli sentiment ed emotion
self.sentiment = hf_pipeline(
"text-classification",
model=sentiment_model,
truncation=True,
max_length=128
)
self.emotion = hf_pipeline(
"text-classification",
model=emotion_model,
truncation=True,
max_length=128
) if emotion_model else None
# spaCy per preprocessing avanzato
if use_spacy:
try:
self.nlp = spacy.load("it_core_news_sm")
except OSError:
print("Modello spaCy 'it_core_news_sm' non trovato.")
print("Installa con: python -m spacy download it_core_news_sm")
self.nlp = None
else:
self.nlp = None
self.threshold = confidence_threshold
def preprocess(self, text: str) -> str:
"""Preprocessing specifico per italiano."""
if not text or not text.strip():
return ""
# Normalizza unicode
text = unicodedata.normalize('NFC', text)
# Abbreviazioni comuni italiane
abbr_map = {
r'\bcmq\b': 'comunque',
r'\bnn\b': 'non',
r'\bxke\b': 'perchè',
r'\bx\b': 'per',
}
for pattern, replacement in abbr_map.items():
text = re.sub(pattern, replacement, text, flags=re.IGNORECASE)
# Riduzione caratteri ripetuti
text = re.sub(r'(.)\1{2,}', r'\1\1', text)
# Normalizza spazi
text = re.sub(r'\s+', ' ', text).strip()
return text
def analyze(self, text: str) -> dict:
"""Analisi completa: sentiment + emozione + preprocessing."""
if not text or not text.strip():
return {"error": "Testo vuoto"}
preprocessed = self.preprocess(text)
# Sentiment
sent_result = self.sentiment(preprocessed)[0]
sentiment_label = sent_result['label']
sentiment_score = sent_result['score']
result = {
"text_originale": text,
"text_preprocessato": preprocessed,
"sentiment": sentiment_label,
"sentiment_score": round(sentiment_score, 4),
"confident": sentiment_score >= self.threshold
}
# Emozione (se disponibile)
if self.emotion:
em_result = self.emotion(preprocessed)[0]
result["emotion"] = em_result['label']
result["emotion_score"] = round(em_result['score'], 4)
return result
def analyze_batch(self, texts: list) -> list:
return [self.analyze(t) for t in texts]
# Utilizzo
pipeline = ItalianSentimentPipeline()
test_texts = [
"Il prodotto e arrivato in perfette condizioni, sono molto soddisfatto dell'acquisto!",
"Pessima esperienza. Il pacco era danneggiato e il servizio clienti non risponde.",
"Mah, diciamo che si poteva fare meglio. Non e ne buono ne cattivo.",
"INCREDIBILE! Non avrei mai pensato che fosse cosi bello!!! Sto piangendo di gioia",
"Nn ci credo... mi ha di nuovo fregato sto negozio di schifo",
]
for text in test_texts:
result = pipeline.analyze(text)
print(f"Testo: {text[:60]}...")
print(f"Sentiment: {result['sentiment']} ({result['sentiment_score']:.3f})")
if 'emotion' in result:
print(f"Emozione: {result['emotion']} ({result['emotion_score']:.3f})")
print(f"Affidabile: {result['confident']}")
print()
6. Jemné doladění na konkrétní doméně
pocit-to bylo trénováno na Twitteru. Pro konkrétní domény, jako jsou recenze produktů, lékařské komentáře nebo právní texty a často je nutné dodatečné doladění.
from transformers import (
AutoTokenizer, AutoModelForSequenceClassification,
TrainingArguments, Trainer
)
from datasets import Dataset
import evaluate
import numpy as np
# Strategia 1: Fine-tuning di feel-it su dati dominio
def finetune_for_domain(
base_model: str,
train_texts: list,
train_labels: list,
val_texts: list,
val_labels: list,
output_dir: str,
num_epochs: int = 3
):
tokenizer = AutoTokenizer.from_pretrained(base_model)
model = AutoModelForSequenceClassification.from_pretrained(
base_model,
num_labels=2,
ignore_mismatched_sizes=True # per modelli già fine-tuned
)
def tokenize(examples):
return tokenizer(examples["text"], truncation=True,
padding="max_length", max_length=128)
train_ds = Dataset.from_dict({"text": train_texts, "label": train_labels})
val_ds = Dataset.from_dict({"text": val_texts, "label": val_labels})
train_tok = train_ds.map(tokenize, batched=True)
val_tok = val_ds.map(tokenize, batched=True)
accuracy = evaluate.load("accuracy")
def compute_metrics(eval_pred):
logits, labels = eval_pred
preds = np.argmax(logits, axis=-1)
return accuracy.compute(predictions=preds, references=labels)
args = TrainingArguments(
output_dir=output_dir,
num_train_epochs=num_epochs,
per_device_train_batch_size=16,
per_device_eval_batch_size=32,
learning_rate=2e-5,
warmup_ratio=0.1,
weight_decay=0.01,
evaluation_strategy="epoch",
save_strategy="epoch",
load_best_model_at_end=True,
metric_for_best_model="accuracy",
report_to="none"
)
trainer = Trainer(
model=model,
args=args,
train_dataset=train_tok,
eval_dataset=val_tok,
compute_metrics=compute_metrics
)
trainer.train()
trainer.save_model(output_dir)
tokenizer.save_pretrained(output_dir)
return trainer
# Strategia 2: Confronto modelli italiani
def compare_italian_models(texts, true_labels):
"""Confronto automatico di diversi modelli BERT italiani."""
models = {
"feel-it": "MilaNLProc/feel-it-italian-sentiment",
"AlBERTo-fine": "m-polignano-uniba/bert_uncased_L-12_H-768_A-12_Italian_alb3rt0",
"mBERT": "bert-base-multilingual-cased"
}
results = {}
for name, model_id in models.items():
try:
clf = hf_pipeline("text-classification", model=model_id,
truncation=True, max_length=128)
preds = clf(texts)
# ... calcola metriche
print(f"{name}: modello caricato correttamente")
except Exception as e:
print(f"{name}: errore - {e}")
return results
7. Management regionálních dialektů a odrůd
Itálie má silnou dialektovou tradici. Příspěvky na sociálních sítích, recenze a neformální zprávy často mísí standardní italštinu a dialekt, zvláště jižní (neapolský, sicilský, bariský, kalábrijský).
Strategie pro dialektový text
- Normalizace světla: převod nejběžnějších dialektových forem ve standardní italštině (např. „maje“ → „mai“ v neapolštině)
- Použijte Alberto: školení na Twitteru obsahuje mnoho dialektových forem vzhledem k povaze italských sociálních médií
- Vícejazyčný BERT: Někdy zvládá dialekty jako jazyky lépe „neznámý“ ve srovnání s italskými modely, které očekávají italské standardy
- Sběr dat specifických pro doménu: pokud vaše datová sada obsahuje mnoho dialektismů, sbírejte komentované příklady pro doladění
8. Benchmarky a metriky pro italštinu
from sklearn.metrics import classification_report, confusion_matrix
import numpy as np
def benchmark_italian_sentiment(model_pipeline, test_data):
"""
Benchmark completo per modelli di sentiment italiano.
test_data: lista di tuple (testo, label)
"""
texts = [d[0] for d in test_data]
true_labels = [d[1] for d in test_data]
predictions = model_pipeline(texts)
pred_labels = []
for pred in predictions:
label = pred['label'].upper()
if label in ['POSITIVE', 'POSITIVO', 'POS']:
pred_labels.append(1)
else:
pred_labels.append(0)
print("=== REPORT CLASSIFICAZIONE ===")
print(classification_report(
true_labels, pred_labels,
target_names=['NEGATIVO', 'POSITIVO'],
digits=4
))
# Analisi per categoria di testo
categories = {
'formale': [i for i, t in enumerate(texts) if len(t.split()) > 20],
'informale': [i for i, t in enumerate(texts) if len(t.split()) <= 20],
}
for cat_name, indices in categories.items():
if indices:
cat_true = [true_labels[i] for i in indices]
cat_pred = [pred_labels[i] for i in indices]
report = classification_report(cat_true, cat_pred, output_dict=True)
acc = report['accuracy']
print(f"\nCategoria '{cat_name}' ({len(indices)} esempi): accuracy={acc:.4f}")
return pred_labels
9. Jemné doladění pocitu z personalizovaných dat
pocit – je to vynikající výchozí bod, ale dosahuje se nejlepšího výkonu vždy přizpůsobte model vaší konkrétní doméně. Zde je kompletní pracovní postup pro jemné doladění italských vlastních dat.
from transformers import (
AutoTokenizer, AutoModelForSequenceClassification,
TrainingArguments, Trainer
)
from datasets import Dataset
import numpy as np
import evaluate
# 1. Dataset personalizzato (es. recensioni e-commerce italiane)
custom_data = {
"text": [
"Prodotto eccellente, consegna rapidissima. Super consigliato!",
"qualità pessima, si e rotto dopo una settimana. Deluso.",
"Ok, nella media. Ne potevo fare a meno.",
"Fantastico! Esattamente come descritto, sono molto soddisfatto.",
"Spedizione veloce ma il prodotto non corrisponde alla descrizione.",
"Materiale scadente, non vale il prezzo. Non ricompro.",
"Ottimo rapporto qualità/prezzo, lo consiglio a tutti.",
"Funziona perfettamente, esattamente quello che cercavo.",
],
"label": [1, 0, 0, 1, 0, 0, 1, 1] # 0=negativo, 1=positivo
}
# 2. Carica tokenizer feel-it
model_name = "MilaNLProc/feel-it-italian-sentiment"
tokenizer = AutoTokenizer.from_pretrained(model_name)
def tokenize(examples):
return tokenizer(
examples["text"],
padding="max_length",
truncation=True,
max_length=128
)
dataset = Dataset.from_dict(custom_data)
dataset = dataset.train_test_split(test_size=0.2, seed=42)
tokenized = dataset.map(tokenize, batched=True)
# 3. Carica modello con nuova classification head
model = AutoModelForSequenceClassification.from_pretrained(
model_name,
num_labels=2,
ignore_mismatched_sizes=True, # la head originale ha etichette diverse
id2label={0: "NEGATIVO", 1: "POSITIVO"},
label2id={"NEGATIVO": 0, "POSITIVO": 1}
)
# 4. Metriche di valutazione
accuracy_metric = evaluate.load("accuracy")
f1_metric = evaluate.load("f1")
def compute_metrics(eval_pred):
logits, labels = eval_pred
preds = np.argmax(logits, axis=-1)
return {
"accuracy": accuracy_metric.compute(predictions=preds, references=labels)["accuracy"],
"f1": f1_metric.compute(predictions=preds, references=labels)["f1"]
}
# 5. Training arguments calibrati per dataset piccoli
training_args = TrainingArguments(
output_dir="./feel-it-finetuned",
num_train_epochs=5, # più epoche per dataset piccoli
per_device_train_batch_size=8,
per_device_eval_batch_size=16,
learning_rate=2e-5,
warmup_ratio=0.2, # warmup più lungo per stabilità
weight_decay=0.01,
evaluation_strategy="epoch",
save_strategy="epoch",
load_best_model_at_end=True,
metric_for_best_model="f1",
fp16=False, # disabilita per GPU piccole o CPU
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized["train"],
eval_dataset=tokenized["test"],
compute_metrics=compute_metrics,
)
trainer.train()
results = trainer.evaluate()
print(f"Accuracy: {results['eval_accuracy']:.4f}")
print(f"F1: {results['eval_f1']:.4f}")
# 6. Salva e publica su HuggingFace Hub (opzionale)
trainer.save_model("./feel-it-custom-ecommerce")
tokenizer.save_pretrained("./feel-it-custom-ecommerce")
10. Tabulka výběru: Který italský model si vybrat
Průvodce výběrem italského modelu
| Use Case | Doporučený model | Motivace | Alternativní |
|---|---|---|---|
| Binární sentiment (pos/neg) | cítit to | Explicitně vycvičený pro italský cit | UmBERTo doladěno |
| Detekce emocí (6 tříd) | cítit to | Jedinečný italský model se 6 emocemi | XLM-RoBERTa multilabel |
| Sociální média / Twitter | Alberto | Trénováno na 196 milionech italských tweetů | cítit se s normalizací |
| Formální texty (novinky, dokumenty) | dbmdz/bert-base-italian-xxl-cased | Akademický korpus a italské novinky | UmBERTo |
| Italský NER | dbmdz/bert-base-italian-xxl-case + NER hlava | Bohatší italská slovní zásoba | spaCy it_core_news_lg |
| Vícejazyčné úkoly (IT+EN+...) | xlm-roberta-large | Top-1 na XNLI, podporuje 100 jazyků | mDeBERTa-v3-base |
| Nízká latence produkce | DistilBERT vícejazyčný kvantovaný | O 60 % rychlejší, zachovává 97 % kvalitu | Feel-it + export ONNX |
Závěry a další kroky
NLP pro italštinu vyžaduje zvláštní pozornost: bohatá morfologie, jazyk hovorové, dialektismy a nedostatek anotovaných zdrojů činí tuto doménu náročné, ale také velmi zajímavé. Modelky jako cítit to e Alberto se v posledních letech výrazně zlepšila situace.
Klíčové body
- USA cítit to jako výchozí bod pro pocity a emoce v italštině
- Pro sociální média a neformální texty, Alberto a často lepší
- U formálních textů (novinky, dokumenty) použijte dbmdz BERT pouzdro
- Specifické předzpracování (normalizace zkratek, lemmatizace) zlepšuje výsledky
- Pro dosažení nejlepších výsledků vždy dolaďte data konkrétní domény
- Sbírejte neustálou zpětnou vazbu: Italština se rychle vyvíjí (neologismy, anglicismy)
Série pokračuje
- Další: Rozpoznávání pojmenované entity — extrahovat entity z textu pomocí spaCy a BERT
- Článek 6: Klasifikace textu s více štítky — když má text více kategorií
- Článek 7: HuggingFace Transformers: Kompletní průvodce — API Trainer a Model Hub
- Článek 8: LoRA Jemné doladění — trénovat velké modely na spotřebitelských GPU
- Související série: AI inženýrství/RAG — Italská vložení pro sémantické vyhledávání







