Text Classification
Transformers
Safetensors
Spanish
bert
machine-learning
educational-example
text-embeddings-inference
Instructions to use WalterWi/transformers_clas_texto with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use WalterWi/transformers_clas_texto with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="WalterWi/transformers_clas_texto")# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForSequenceClassification tokenizer = AutoTokenizer.from_pretrained("WalterWi/transformers_clas_texto") model = AutoModelForSequenceClassification.from_pretrained("WalterWi/transformers_clas_texto", device_map="auto") - Notebooks
- Google Colab
- Kaggle
File size: 6,497 Bytes
f343795 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | """Entrena un clasificador de texto con Hugging Face Transformers y lo exporta.
Problema: clasificar comentarios sobre departamentos en "positivo" o "negativo".
Es un BERT diminuto (2 capas, 32 dimensiones) entrenado DESDE CERO, con un tokenizer propio
de vocabulario cerrado. As铆 se ven todas las piezas que publica un modelo de Transformers:
config.json la arquitectura (cu谩ntas capas, dimensiones, etiquetas)
model.safetensors los pesos
tokenizer.json el vocabulario y c贸mo se corta el texto en tokens
tokenizer_config.json la configuraci贸n del tokenizer y sus tokens especiales
En un caso real no se entrena desde cero: se hace fine-tuning de un modelo preentrenado
(por ejemplo, uno en espa帽ol del Hub). Las piezas exportadas son las mismas.
Uso:
python train.py
"""
import json
import random
from itertools import product
from pathlib import Path
import torch
from sklearn.metrics import accuracy_score
from tokenizers import Tokenizer, models, normalizers, pre_tokenizers, processors, trainers
from transformers import BertConfig, BertForSequenceClassification, PreTrainedTokenizerFast
CARPETA = Path(__file__).parent
ETIQUETAS = ["negativo", "positivo"]
random.seed(42)
torch.manual_seed(42)
# ---------------------------------------------------------------------------
# 1. Datos: comentarios armados con plantillas (dataset sint茅tico y chico)
# ---------------------------------------------------------------------------
PLANTILLAS = [
"el departamento es muy {a}",
"me pareci贸 un lugar {a}",
"la verdad es {a} y {b}",
"un depto {a}, bastante {b}",
"es {a} pero sobre todo {b}",
]
POSITIVOS = ["luminoso", "amplio", "tranquilo", "c贸modo", "lindo", "seguro", "moderno", "c谩lido"]
NEGATIVOS = ["oscuro", "chico", "ruidoso", "h煤medo", "feo", "inseguro", "viejo", "fr铆o"]
def armar_ejemplos(adjetivos, etiqueta):
ejemplos = []
for plantilla, a, b in product(PLANTILLAS, adjetivos, adjetivos):
if a != b:
ejemplos.append((plantilla.format(a=a, b=b), etiqueta))
return ejemplos
datos = armar_ejemplos(POSITIVOS, 1) + armar_ejemplos(NEGATIVOS, 0)
datos = list(dict.fromkeys(datos)) # sin repetidos
random.shuffle(datos)
corte = int(len(datos) * 0.8)
train, test = datos[:corte], datos[corte:]
print(f"{len(train)} comentarios de entrenamiento, {len(test)} de test")
# ---------------------------------------------------------------------------
# 2. Tokenizer: aprende el vocabulario de los textos de entrenamiento
# ---------------------------------------------------------------------------
tok = Tokenizer(models.WordLevel(unk_token="[UNK]"))
tok.normalizer = normalizers.Sequence([normalizers.NFD(), normalizers.Lowercase(), normalizers.StripAccents()])
tok.pre_tokenizer = pre_tokenizers.Whitespace()
tok.train_from_iterator(
[texto for texto, _ in train],
trainers.WordLevelTrainer(special_tokens=["[PAD]", "[UNK]", "[CLS]", "[SEP]"]),
)
tok.post_processor = processors.TemplateProcessing(
single="[CLS] $A [SEP]",
special_tokens=[("[CLS]", tok.token_to_id("[CLS]")), ("[SEP]", tok.token_to_id("[SEP]"))],
)
tokenizer = PreTrainedTokenizerFast(
tokenizer_object=tok,
unk_token="[UNK]", pad_token="[PAD]", cls_token="[CLS]", sep_token="[SEP]",
model_max_length=32,
)
print(f"Vocabulario: {tokenizer.vocab_size} tokens")
# ---------------------------------------------------------------------------
# 3. Modelo: un BERT diminuto con una cabeza de clasificaci贸n de 2 etiquetas
# ---------------------------------------------------------------------------
config = BertConfig(
vocab_size=tokenizer.vocab_size,
hidden_size=32,
num_hidden_layers=2,
num_attention_heads=2,
intermediate_size=64,
max_position_embeddings=32,
num_labels=len(ETIQUETAS),
id2label=dict(enumerate(ETIQUETAS)),
label2id={e: i for i, e in enumerate(ETIQUETAS)},
pad_token_id=tokenizer.pad_token_id,
)
modelo = BertForSequenceClassification(config)
def a_tensores(lote):
textos, etiquetas = zip(*lote)
entrada = tokenizer(list(textos), padding=True, return_tensors="pt", return_token_type_ids=False)
return entrada, torch.tensor(etiquetas)
# ---------------------------------------------------------------------------
# 4. Entrenamiento: el mismo ciclo de siempre (predice, p茅rdida, optimizador)
# ---------------------------------------------------------------------------
optimizador = torch.optim.AdamW(modelo.parameters(), lr=1e-3)
modelo.train()
for epoca in range(15):
random.shuffle(train)
perdida_total = 0.0
for i in range(0, len(train), 16):
entrada, etiquetas = a_tensores(train[i:i + 16])
salida = modelo(**entrada, labels=etiquetas) # la p茅rdida (entrop铆a cruzada) viene en la salida
optimizador.zero_grad()
salida.loss.backward()
optimizador.step()
perdida_total += salida.loss.item()
print(f"茅poca {epoca:2d} 路 p茅rdida {perdida_total / (len(train) / 16):.4f}")
# ---------------------------------------------------------------------------
# 5. Evaluaci贸n con comentarios que el modelo no vio
# ---------------------------------------------------------------------------
modelo.eval()
entrada, etiquetas = a_tensores(test)
with torch.no_grad():
predichas = modelo(**entrada).logits.argmax(dim=-1)
print(f"Accuracy en test: {accuracy_score(etiquetas, predichas):.3f}")
# ---------------------------------------------------------------------------
# 6. Exportaci贸n: modelo (config + pesos) y tokenizer, en la misma carpeta
# ---------------------------------------------------------------------------
modelo.save_pretrained(CARPETA) # config.json + model.safetensors
tokenizer.save_pretrained(CARPETA) # tokenizer.json + tokenizer_config.json
# Compatibilidad: Transformers 5 anota una clase de tokenizer que la versi贸n 4 (la de Colab)
# no conoce. PreTrainedTokenizerFast la entienden las dos.
ruta_config_tok = CARPETA / "tokenizer_config.json"
config_tok = json.loads(ruta_config_tok.read_text(encoding="utf-8"))
config_tok["tokenizer_class"] = "PreTrainedTokenizerFast"
config_tok.pop("backend", None)
ruta_config_tok.write_text(json.dumps(config_tok, indent=2, ensure_ascii=False), encoding="utf-8")
print("Modelo y tokenizer guardados en la carpeta")
|