UD03 · Notebook 8 — Del texto al vector¶
Requisitos
Va en el contenedor de la unidad (docker compose up -d en la carpeta de la UD03), o en cualquier Python 3.12+ con:
pip install nltk spacy scikit-learn
python -m spacy download es_core_news_sm
Este taller no necesita GPU ni Colab.
Objetivo: construir un clasificador que determine si una reseña es positiva o negativa, usando un dataset anotado por el alumnado y scikit-learn.
Es una entrega evaluable: se corrige con la rúbrica de su tarea en Moodle.
Fase 1 — Crea tu dataset (origen y licencia)¶
Crea un fichero reseñas.csv con al menos 30 reseñas cortas en español (por parejas: 20 de entrenamiento, 10 de prueba) y su etiqueta (1 = positiva, 0 = negativa). Anota en el informe el origen (opiniones propias o de un restaurante ficticio) y la licencia (p. ej. anotación propia bajo CC BY).
| texto | etiqueta |
|---|---|
| La comida estaba riquísima y el servicio rápido | 1 |
| Pedimos y el plato llegó frío | 0 |
| ... | ... |
reseñas = [
# TU CÓDIGO: al menos 20 frases, mitad positivas (1) y mitad negativas (0)
]
etiquetas = [
# TU CÓDIGO: la etiqueta de cada reseña, en el mismo orden
]
print(f"{len(reseñas)} reseñas · {sum(etiquetas)} positivas · {len(etiquetas)-sum(etiquetas)} negativas")
✏️ Respuesta: ¿de dónde has sacado las reseñas? ¿Podrías redistribuirlas? Indica origen y licencia — es el paso 2 de la metodología del §12.1, y aquí se hace primero porque sin datos no hay nada que preprocesar.
(escribe aquí)
Fase 2 — Preprocesado con nltk¶
Aplica limpiar a todas las reseñas y muestra 3 ejemplos antes/después.
import nltk
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
nltk.download(['punkt_tab', 'stopwords'], quiet=True)
vacias = set(stopwords.words('spanish'))
def preprocesar(texto):
# TU CÓDIGO: tokeniza, pasa a minusculas y quita las stopwords
...
reseñas_proc = [preprocesar(r) for r in reseñas]
print(reseñas_proc[0])
Fase 3 — Vectorizar y entrenar¶
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
# TU CÓDIGO: vectoriza (recuerda: stop_words solo acepta 'english', para español pasa la lista)
# y entrena un LogisticRegression
X_train, X_test, y_train, y_test = ...
modelo = ...
print("Exactitud:", modelo.score(X_test, y_test))
Fase 4 — Matriz de confusión¶
Interpeta la matriz: ¿cuántos positivos correctos, cuántos falsos positivos?
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
import matplotlib
matplotlib.use('Agg') # en Colab o Jupyter con pantalla, quita esta linea
# TU CÓDIGO
pred = ...
ConfusionMatrixDisplay(confusion_matrix(y_test, pred)).plot()
✏️ Respuesta: ¿qué confunde más el modelo, falsos positivos o falsos negativos? ¿Tiene sentido con el tamaño de tu dataset?
(escribe aquí)
Fase 5 — Prueba con reseñas nuevas¶
nuevas = [
# TU CÓDIGO: tres reseñas nuevas, tuyas
]
# TU CÓDIGO: vectorizalas con el MISMO vectorizador (no entrenes uno nuevo) y predice
...
Fase 6 — Análisis de errores¶
Busca en el test al menos 2 errores del modelo e intenta explicarlos (jerga, ironía, ambigüedad, vocabulario nuevo). Documenta la conclusión.
✏️ Respuesta: para cada error, ¿qué tipo de ambigüedad lo explica —léxica, pragmática, ironía—? Es el paso 5 de la metodología: mirar los errores, no solo la exactitud.
(escribe aquí)
Entrega¶
Sube el notebook ejecutado. Se valora que interpretes los resultados, no solo que las celdas den un número.
| Fase | Evidencia mínima |
|---|---|
| 1 | El conjunto de reseñas, con su origen y licencia declarados |
| 2 | El texto preprocesado: tokens, sin stopwords, normalizado |
| 3 | El clasificador entrenado y su exactitud sobre datos no vistos |
| 4 | La matriz de confusión, interpretada: qué confunde con qué |
| 5 | Las predicciones sobre reseñas nuevas, tuyas |
| 6 | Dos errores leídos uno a uno y qué tipo de ambigüedad los explica |
Soluciones
Las soluciones no se publican: se corrigen y comentan en clase.