NLP pentru limba italiană: provocări și soluții specifice
Italiana este una dintre cele mai complexe limbi romanice din punct de vedere morfologic: gen gramatical, declinări, acord adjectiv-substantiv, forme verbale neregulate și o structură sintactică flexibilă face posibilă preprocesarea și modelarea NLP mult mai provocatoare decât engleza. Totuși, marea majoritate de tutoriale NLP și engleză, iar cele mai cunoscute modele sunt adesea optimizate pentru limba engleză.
Acest articol umple acest gol. Vom explora provocările specifice ale italianului, seturile de date disponibile, modelele italiene BERT (simte-o, Alberto, dbmdz BERT), preprocesare specifică pentru limba italiană, și cum să construiți un sistem de analiză a sentimentelor pentru italiană pas cu pas.
Aceasta este a patra parte a seriei NLP modern: de la BERT la LLM. Și acolo doar seriale în italiană care acoperă în mod specific preprocesarea și modelarea NLP pentru limba italiană.
Ce vei învăța
- Provocări morfologice ale limbii italiene: gen, declinări, verbe neregulate
- Preprocesare specifică: cuvinte oprite italiene, lematizare cu spaCy, normalizare
- Modele italiene BERT: feel-it-italian-sentiment, AlBERTo, dbmdz BERT, GilBERTo
- Setul de date pentru italiană: SENTIPOLC, TweetSent-IT, ItalianSentiment
- Ajustare fină a simțului asupra datelor personalizate
- Managementul limbajului colocvial, dialectelor italiene și neologismelor
- Canal complet pentru analiza sentimentelor asupra textelor italiene
- Comparație între modelele BERT italiene și multilingve
1. Provocări specifice ale italianului în NLP
Italiana are caracteristici lingvistice care fac NLP mai complex comparativ cu engleza. Înțelegerea acestor provocări este fundamentală pentru construcție sisteme eficiente.
1.1 Morfologie bogată
Spre deosebire de engleză, italiana are un morfologie foarte bogată: aceeași rădăcină verbală generează zeci de forme, iar adjectivele sunt în general de acord și număr cu substantive. Acest lucru creează probleme de dispersie a datelor.
Exemplu: Verbul „Andare” în italiană
- Mă duc, merg, merg, merg, merg, merg (prezent)
- M-am dus, te-ai dus, te-ai dus, te-ai dus, te-ai dus, te-ai dus (imperfect)
- andro, andrai, andra, noi vom merge, tu vei merge, ei vor merge (viitor)
- M-am dus, te-ai dus, m-am dus, am mers, te-ai dus, ei au plecat (trecut îndepărtat)
- a plecat, a plecat (subjunctiv trecut)
În engleză „to go” are foarte puține forme. Pentru un model NLP, fiecare formă este inițial un simbol diferit.
1.2 Enclitice și cuvinte compuse
În italiană, pronumele pot fi atașate verbului (enclitice), crearea de jetoane complexe pe care tokenizatoarele standard le pot gestiona prost.
# 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 Punctuația și ortografia colocvială
În textele online italiene (rețele sociale, recenzii) găsim:
- Accente înlocuite cu apostrofe: „poate” în loc de „poate”
- Personaje repetate: „frumos!!!”
- Abrevieri tipice: „cmq” (totuși), „nn” (nu), „xke” (pentru că)
- Schimbarea codului cu limba engleză: „Produsul este cu adevărat de calitate superioară”
- Dialectisme regionale: "mizzica" (siciliana), "mannaggia" (sud)
2. Preprocesare specifică pentru italiană
2.1 spaCy pentru italiană
spațios oferă un șablon pentru limba italiană (it_core_news_sm/md/lg)
cu lematizare, etichetare POS și analiza dependențe.
# 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 Normalizarea textului informal
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. Modele BERT pentru italiană
Sunt disponibile mai multe modele BERT pregătite în prealabil pe corpuri italiene. Alegerea modelului depinde de domeniul și sarcina specifică.
3.1 simt-o-sentiment-italian
simte-o și un set de date și un model specific pentru analiza sentimentelor și detectarea emoțiilor în italiană. Se bazează pe Twitter și a fost instruit adnotări manuale ale sentimentelor (pozitive/negative) și ale emoțiilor (bucurie, tristețe, mânie, frică, dezgust, surpriză).
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 pentru rețelele sociale italiene
Alberto și a fost pre-instruit pe un corpus de tweet-uri italiene (peste 200 de milioane de tweet-uri). Este deosebit de eficient pentru textele informale, rețelele sociale și limba colocvială italiană.
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 engleză
Modelul dbmdz/bert-base-italian-cased și a fost pregătit în prealabil pe Wikipedia italiană și un corpus OPUS. Și cel mai bun punct de plecare pentru texte formale (știri, acte juridice, texte academice).
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 Compararea modelelor italiene
Ce model să folosești?
| Model | Domeniul optim | Sarcini mai bune | Dimensiune |
|---|---|---|---|
| simt-o-sentiment | Social media, opinii | Sentiment, detectarea emoțiilor | ~440 MB |
| simți-o-emoție | Social media, opinii | 6 emoții de bază | ~440 MB |
| Alberto | Twitter, chat, SMS | Sentiment, NER, clasificare | ~420 MB |
| dbmdz BERT cased | Știri, documente formale | NER, clasificare, QA | ~420 MB |
| Gilberto | texte generale italiene | Sarcini generice NLU | ~440 MB |
| mBERT | Interlingvistic | Învățare prin transfer multilingv | ~670 MB |
4. Seturi de date italiene pentru analiza sentimentelor
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. Conductă completă pentru italiană
Integram totul într-un canal pregătit pentru producție pentru analiza sentimentelor în italiană.
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. Ajustare fină pe un domeniu specific
simt-a fost antrenat pe Twitter. Pentru anumite domenii, cum ar fi recenziile de produse, comentarii medicale sau texte legale, iar reglajele suplimentare sunt adesea necesare.
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. Managementul dialectelor și varietăților regionale
Italia are o tradiție dialectală puternică. Postările pe rețelele sociale, recenziile iar mesajele informale amestecă adesea italiana standard și dialectul, în special sudic (napolitană, siciliană, bariană, calabreză).
Strategii pentru textul dialectului
- Normalizarea luminii: convertiți cele mai comune forme de dialect în italiană standard (de exemplu, „maje” → „mai” în napolitană)
- Folosește Alberto: instruit pe Twitter include multe forme de dialect având în vedere natura rețelelor sociale italiene
- BERT multilingv: Uneori, tratează mai bine dialectele ca limbi „necunoscut” în comparație cu modelele italiene care se așteaptă la standarde italiene
- Colectarea datelor specifice domeniului: dacă setul dvs. de date conține multe dialectisme, culege exemple adnotate pentru reglare fină
8. Benchmark-uri și valori pentru limba italiană
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. Reglarea fină a feel-it pe Date Personalizate
simt-este un excelent punct de plecare, dar se obtine cele mai bune performante adaptând întotdeauna modelul la domeniul tău specific. Iată un flux de lucru complet pentru reglarea fină a datelor personalizate italiene.
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. Tabel de selecție: ce model italian să alegi
Ghid pentru alegerea modelului italian
| Caz de utilizare | Model recomandat | Motivația | Alternativă |
|---|---|---|---|
| Sentiment binar (poz/neg) | simte-o | Antrenat explicit pentru sentimentul italian | UmBERT la reglat fin |
| Detectarea emoțiilor (6 clase) | simte-o | Model italian unic cu 6 emoții | XLM-RoBERTa multilabel |
| Social media / Twitter | Alberto | Antrenat pe 196 de milioane de tweet-uri italiene | simți-o cu normalizare |
| Texte formale (știri, documente) | dbmdz/bert-base-italian-xxl-cased | Corpus academic și știri italiene | UmBERTo |
| NER italian | dbmdz/bert-base-italian-xxl-case + cap NER | Vocabular italian mai bogat | spaCy it_core_news_lg |
| Sarcini multilingve (IT+EN+...) | xlm-roberta-large | Top-1 pe XNLI, acceptă 100 de limbi | mDeBERTa-v3-base |
| Producție cu latență scăzută | DistilBERT multilingv cuantizat | 60% mai rapid, menține calitatea cu 97%. | feel-it + export ONNX |
Concluzii și pașii următori
NLP pentru italiană necesită o atenție specială: morfologia bogată, limbajul colocvial, dialectismele și deficitul de resurse adnotate fac acest domeniu provocator, dar și foarte interesant. Modele ca simte-o e Alberto au îmbunătățit semnificativ situația în ultimii ani.
Puncte cheie
- STATELE UNITE ALE AMERICII simte-o ca punct de plecare pentru sentimente și emoții în italiană
- Pentru rețelele sociale și textele informale, Alberto și adesea superior
- Pentru texte formale (știri, documente), utilizați dbmdz BERT cased
- Preprocesarea specifică (normalizarea abrevierilor, lematizarea) îmbunătățește rezultatele
- Ajustați întotdeauna datele de domeniu specifice pentru cele mai bune rezultate
- Colectați feedback continuu: limba italiană evoluează rapid (neologisme, anglicisme)
Seria continuă
- Următorul: Recunoașterea entității numite — extrageți entități din text cu spaCy și BERT
- Articolul 6: Clasificarea textului cu mai multe etichete — când un text are mai multe categorii
- Articolul 7: HuggingFace Transformers: Ghid complet — API Trainer și Model Hub
- Articolul 8: Reglaj fin LoRA — antrenați modele mari pe GPU-uri pentru consumatori
- Serii înrudite: AI Engineering/RAG — înglobări italiene pentru căutare semantică







