En éste artículo se desarrolla un clasificador Naive Bayes en Python, al que, una vez entrenado, podemos pasarle un titular de noticias y deducirá a qué categoría (ocio, tecnología, cultura) pertenece la noticia.
Los clasificadores Naive Bayes son ampliamente usados en machine learning debido a su eficiencia y capacidad para analizar datos con una gran cantidad de características (Manning, 1999).
A continuación crearemos un modelo que utilice Naive Bayes en Python para aprender a clasificar noticias. Se le proporciona un dataset con noticias ya clasificadas en tres categorías: ocio, tecnología y cultura.
Realizaremos éste modelo en tres pasos: 1) obtención de datos, filtrado y vectorización. 2) Implementar un transformador, para convertir a array los datos. 3) Crear el modelo de clasificador Naive Bayes en Python con distribución Gaussiana y guardarlo en formato Pickle para su posterior uso.
Teniendo ya nuestro modelo entrenado podremos hacer pruebas con cualquier noticia.
Vamos a utilizar un dataset disponible en: https://drive.google.com/file/d/1v8VgIp5Dbhz0f_-aPfA4DELz7ru1LwQI/view?usp=sharing
Consiste en noticias clasificadas que nos servirán para entrenar nuestro modelo.
También vamos a utilizar un listado de palabras que deseamos eliminar pues aportan poco o ningún significado a la interpretación de las noticias. Esas palabras, conocidas como stop-words, están disponibles en el siguiente archivo:
https://drive.google.com/file/d/1bL46-MfwN0nKqfL8fRNqQ-aAjqYCuz5a/view?usp=sharing
import pandas as pd from sklearn.feature_extraction.text import TfidfVectorizer import json noticias = pd.read_csv("noticias.csv") # Eliminar stopwords: palabras cuyo contenido no es muy relevante with open("stopwords-es.json") as fname: stopwords_es = json.load(fname) # Debido a que trabajamos con texto, tenemos que vectorizar, usaremos Tf-idf vectorizador = TfidfVectorizer(stop_words=stopwords_es, max_features=50000) # La transformamos en una matriz dispersa vectorizador.fit_transform(noticias.descripcion)
Explicación: Utilizamos pandas para la obtención de datos, y json para cargar las stopwords. Se crea un vectorizador utilizando un algoritmo Tfidf. Posteriormente se le pasa al vectorizador los datos con los que deseamos trabajar. Ésto nos creará una matriz dispersa. Según la cantidad escrita en max_features es la cantidad de palabras que puede registrar lo que repercute en el tiempo de procesamiento.
Creamos una clase DenseTransformer, que nos permite convertir una matriz dispersa en un array.
from sklearn.base import BaseEstimator from scipy.sparse import issparse # http://rasbt.github.io/mlxtend/ class DenseTransformer(BaseEstimator): def __init__(self, return_copy=True): self.return_copy = return_copy self.is_fitted = False def transform(self, X, y=None): if issparse(X): return X.toarray() elif self.return_copy: return X.copy() else: return X def fit(self, X, y=None): self.is_fitted = True return self def fit_transform(self, X, y=None): return self.transform(X=X, y=y)
# Importamos el clasificador naive bayes, este tiene tres distribuciones Gausiano, Bernoulli, Multinomial from sklearn.naive_bayes import GaussianNB # Un pipeline es un conjunto de tuberias o flujos que parten de una entrada (datos) # hacia una salida (modelo) from sklearn.pipeline import make_pipeline pipeline_gaussiano = make_pipeline( vectorizador, DenseTransformer(), GaussianNB() ) pipeline_gaussiano.fit(X=noticias.descripcion, y=noticias.categoria) import pickle pickle.dump(pipeline_gaussiano, open("naive_noticias_model.pickle", "wb")) print ("Modelo Creado")
Explicación: En éste paso se crea un pipeline. Lo primero que recibe es el vectorizador que contiene una matriz dispersa que representa cada palabra asignada a cada noticia. Ésta matriz es pasada a DenseTransformer que la convierte a un array. Éste array es pasado a GaussianNB con lo que se crea un clasificador Naive Bayes. Se ajusta el modelo pasando como X (dato de entrada) la descripción de la noticia, y como y (dato de salida) la categoría. Utilizando pickle se guarda el modelo en un archivo que se puede utilizar más adelante. Éste proceso puede tardar varios minutos.
Una vez creado nuestro modelo, podemos utilizarlo para clasificar una o miles de noticias.
import pickle from sklearn.base import BaseEstimator from scipy.sparse import issparse class DenseTransformer(BaseEstimator): def __init__(self, return_copy=True): self.return_copy = return_copy self.is_fitted = False def transform(self, X, y=None): if issparse(X): return X.toarray() elif self.return_copy: return X.copy() else: return X def fit(self, X, y=None): self.is_fitted = True return self def fit_transform(self, X, y=None): return self.transform(X=X, y=y) pipeline_gaussiano = pickle.load(open("naive_noticias_model.pickle", "rb")) n1 = ["¿Cansado de que te roben Internet? Aqui puedes darte cuenta de quienes tienen tu wifi"] n2 = ["Los cineastas mexicanos se unen para crear un fondo de emergencia ante la contingencia sanitaria"] n3 = ["10 películas y series de terror en Netflix para ver este fin de semana"] r1=pipeline_gaussiano.predict(n1) r2=pipeline_gaussiano.predict(n2) r3=pipeline_gaussiano.predict(n3) print ("=====================") print ("Noticia: " + str(n1)) print ("Categoría probable: " + str(r1)) print ("Noticia: " + str(n2)) print ("Categoría probable: " + str(r2)) print ("Noticia: " + str(n3)) print ("Categoría probable: " + str(r3))
Lo probamos cargando el modelo creado en archivo pickle y dandole una noticia. El resultado es la categoría en la que el clasificador pone a la noticia que introducimos.
1. Manning (1999). Foundations of Statistical Natural Language Processing.