Abrir en Google Colab
|
Descargar notebook
|
Modelado clásico de lenguaje natural
Creando un pipeline de preprocesamiento de texto
A pesar de que los métodos anteriores son no supervisados, son de utilidad para el modelado de de problemas no supervisados como supervisados. Para llevar estos métodos a un entorno práctico normalmente se construyen flujos de procesamiento como el que se muestra más abajo. Estos flujos se los llama Pipeline:

A modo de ejemplo, vamos a utilizar la API de Scikit-Learn para generar cada uno de estos pasos y así construir un modelo que resuelva un problema de negocio de punta a punta.
¿Que es lo que vamos a hacer? Intentaremos construir un pipeline de machine learning donde como entrada recibamos texto, ejecutemos todos los pasos que vimos en este notebook incluyendo:
Eliminación de stopwords
Tokenización
Stemming y Lemmatization
Procesamiento especico del tema
Creación de features utilizando algun metodo de reducción de dimensionalidad, SVD, LSI, LDA
, para luego utilizar estas features para entrenar un modelo que nos permita predecir alguna propiedad interesante del set de datos. En este caso en particular, donde estamos viendo tweets, algunos casos interesantes podrían ser:
Predecir el sector al que pertenece el tweet: Alimentación, Bebidas, etc.
Predecir el paso en el Marketing Funel al que pertece
Para ejecutar este notebook
Para ejecutar este notebook, instale las siguientes librerias:
[42]:
!wget https://raw.githubusercontent.com/santiagxf/M72109/master/NLP/Datasets/mascorpus/tweets_marketing.csv \
--quiet --no-clobber --directory-prefix ./Datasets/mascorpus/
!wget https://raw.githubusercontent.com/santiagxf/M72109/master/m72109/nlp/normalization.py \
--quiet --no-clobber --directory-prefix ./m72109/nlp/
!wget https://raw.githubusercontent.com/santiagxf/M72109/master/m72109/nlp/transformation.py \
--quiet --no-clobber --directory-prefix ./m72109/nlp/
!wget https://raw.githubusercontent.com/santiagxf/M72109/master/docs/nlp/classic/classic-modeling.txt \
--quiet --no-clobber
!pip install -r classic-modeling.txt --quiet
[2]:
!python -m spacy download es_core_news_sm 1> /dev/null
Primero importaremos algunas librerias necesarias
[3]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from tqdm import tqdm
Sobre el set de datos con el que vamos a trabajar
Utilizaremos como ejemplo un set de datos en español que contiene tweets que diferentes usuarios han publicado en relación a diferentes marcas de productos u empresas en el rubro de alimentación, construcción, automoviles, etc. Estos tweets, a su vez, están asociados a una de las diferentes fases en el proceso de ventas (también conocido como Marketing Funel) y por eso están tagueados con las fases de:
Awareness – el cliente es conciente de la existencia de un producto o servicio
Interest – activamente expresa el interes de un producto o servicio
Evaluation – aspira una marca o producto en particular
Purchase – toma el siguiente paso necesario para comprar el producto o servicio
Postpurchase - realización del proceso de compra. El cliente compara la diferencia entre lo que deseaba y lo que obtuvo
Referencia: Spanish Corpus of Tweets for Marketing
Nota: La version de este conjunto de datos que utilizaremos aqui es una versión preprocesada del original.
[4]:
tweets = pd.read_csv('Datasets/mascorpus/tweets_marketing.csv')
Inspeccionamos el set de datos
[5]:
tweets.head(5)
[5]:
| TEXTO | SECTOR | MARCA | CANAL | AWARENESS | EVALUATION | PURCHASE | POSTPURCHASE | NC2 | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | #tablondeanuncios Funda nordica ikea #madrid h... | RETAIL | IKEA | Microblog | 0 | 0 | 0.0 | 0 | 1.0 |
| 1 | #tr Me ofrezco para montar muebles de Ikea - H... | RETAIL | IKEA | Microblog | 0 | 0 | 0.0 | 0 | 1.0 |
| 2 | #VozPópuli Vozpópuli @voz_populi - #LoMásLeido... | RETAIL | ALCAMPO | Microblog | 0 | 0 | 0.0 | 0 | 1.0 |
| 3 | #ZonaTecno Destacado: Todo lo que hay que sabe... | RETAIL | CARREFOUR | Microblog | 0 | 0 | 0.0 | 0 | 1.0 |
| 4 | $Carrefour retira pez #Panga. OCU y grupos x #... | RETAIL | CARREFOUR | Microblog | 0 | 0 | 0.0 | 0 | 1.0 |
[6]:
tweets.groupby('SECTOR').head(1)[['TEXTO', 'SECTOR']]
[6]:
| TEXTO | SECTOR | |
|---|---|---|
| 0 | #tablondeanuncios Funda nordica ikea #madrid h... | RETAIL |
| 725 | "Ilcinsisti lis MB dispiniblis" te odeeeeeo Mo... | TELCO |
| 964 | #CarlosSlim y Bimbo lanzarán un vehículo eléct... | ALIMENTACION |
| 1298 | ‼🏎Toyota #Day, 4ruedas ,1/4 milla, 1 #pasión, ... | AUTOMOCION |
| 1748 | "- Tú qué.\n- Yo na."\nConversaciones banco sa... | BANCA |
| 2348 | - Cariño, te juro que sólo tenían Cruzcampo en... | BEBIDAS |
| 3023 | #adidas #hockey Amenabar 2080 CABA https://t.c... | DEPORTES |
Creando un pipeline
Creando un paso de Pipeline para procesamiento de texto
El paso más complejo que tenemos para crear es quizas el preprocesamiento del texto. Esto lo podemos encapsular en un modulo de Scikit-Learn. Esta libreria tiene 2 tipos de modulos:
Transformers
Estimators
Los transformers toman un set de features y devuelven otro set de features, por eso es que reciben el nombre de «trasformers», porque basicamente transforman vectores. Los estimators, por el contrario, reciben un set de features y producen un podelo que aproxima, o estima, una variable target. Por este motivo, estos modulos reciben el nombre de «estimators».
Para simplicidad, en este curso disponemos de un TweetTextNormalizer ya implementado que basicamente utiliza el mismo código que vimos en la lección de procesamiento de texto.
Tip: Recomendamos que revise todos los parametros que recibe esta clase.
Instanciamos nuestro preprocesamiento de texto
[47]:
from m72109.nlp.normalization import TweetTextNormalizer
normalizer = TweetTextNormalizer(
language='spanish',
lemmatize=True,
stem=False,
reduce_len=True,
strip_handles=True,
strip_stopwords=True,
strip_urls=True,
strip_accents=True,
token_min_len=4,
preserve_case=False
)
Podemos ver como funciona nuestro modulo de preprocesamiento de texto al llamarlo con la función transform:
[48]:
tweet = tweets['TEXTO'][5]
print(tweet)
. @PoliciadeBurgos @PCivilBurgos @Aytoburgos Mismo peligro c/ Rio Viejo junto Mercadona Villimar
[49]:
normalizer.transform([tweet])
100%|██████████| 1/1 [00:00<00:00, 13.51it/s]
[49]:
array(['mismo peligro viejo junto mercadona villimar '], dtype=object)
Creando pasos de pipeline para la vectorizacion y ingeniería de features
Importamos algunas librerias que necesitaremos
[50]:
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.decomposition import LatentDirichletAllocation
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.metrics import classification_report
Instanciamos nuestro vectorizador, en este caso usando el método TF-IDF
[51]:
vectorizer = TfidfVectorizer(use_idf=True, sublinear_tf=True, norm='l2')
Instanciamos nuestro generador de features, que en este caso son los tópicos que LDA genere
[52]:
featurizer = LatentDirichletAllocation(n_components=7)
Creando un paso de pipeline para clasificar
Instanciamos nuestro clasificador que utilizará las features generadas hasta este momento
[53]:
estimator = LogisticRegression(max_iter=10000, multi_class='multinomial')
Ensamblando el pipeline
Creamos un pipeline que ejecute todos los pasos en secuencia
[54]:
pipeline = Pipeline(steps=[('normalizer', normalizer),
('vectorizer', vectorizer),
('featurizer', featurizer),
('estimator', estimator)])
En este caso intentaremos predecir el sector al que pertenece un tweet en particular. Para ello, como en todo proceso de machine learning separaremos nuestros datos en training y testing, para poder evaluar los resultados:
[55]:
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(tweets['TEXTO'], tweets['SECTOR'],
test_size=0.33, stratify=tweets['SECTOR'])
El método fit intrenará nuestro modelo de punta a punta. Tomará unos minutos
[56]:
model = pipeline.fit(X=X_train, y=y_train)
100%|██████████| 2521/2521 [01:47<00:00, 23.56it/s]
Es hora de ver que tan bien le fué a nuestro modelo en esta tarea
[57]:
predictions = model.predict(X_test)
100%|██████████| 1242/1242 [00:53<00:00, 23.02it/s]
[60]:
print(classification_report(y_test, predictions, zero_division=0))
precision recall f1-score support
ALIMENTACION 0.00 0.00 0.00 110
AUTOMOCION 0.00 0.00 0.00 148
BANCA 0.50 0.01 0.02 198
BEBIDAS 0.34 0.39 0.36 223
DEPORTES 0.28 0.32 0.30 216
RETAIL 0.25 0.69 0.37 268
TELCO 0.00 0.00 0.00 79
accuracy 0.28 1242
macro avg 0.20 0.20 0.15 1242
weighted avg 0.24 0.28 0.20 1242
¿Les parece que estás métricas son buenas? ¿Se les ocurre como mejorarlo? Algunas ideas:
¿Quien funcionará mejor? ¿Stemmer o Lemmatization?
¿Qué será mejor hacer con los hashtags? ¿Quitarlos?
¿Que cantidad de factores latentes funcionará mejor? ¿7, 10, 200, 300?
¿Es Logistic Regression el mejor clasificador que podemos probar? ¿Si subimos la cantidad de tópicos que me sería mejor utilizar?
Abrir en Google Colab
Descargar notebook