{"id":2279,"date":"2020-10-17T16:56:29","date_gmt":"2020-10-17T21:56:29","guid":{"rendered":"https:\/\/naps.com.mx\/blog\/?p=2279"},"modified":"2021-11-11T22:07:49","modified_gmt":"2021-11-12T04:07:49","slug":"naive-bayes-en-python-ejemplo-explicado","status":"publish","type":"post","link":"https:\/\/naps.com.mx\/blog\/naive-bayes-en-python-ejemplo-explicado\/","title":{"rendered":"Naive Bayes en Python: Ejemplo explicado"},"content":{"rendered":"<p>En \u00e9ste art\u00edculo se desarrolla un clasificador Naive Bayes en Python, al que, una vez entrenado, podemos pasarle un titular de noticias y deducir\u00e1 a qu\u00e9 categor\u00eda (ocio, tecnolog\u00eda, cultura) pertenece la noticia.<\/p>\n<p><!--more--><\/p>\n<p><a href=\"https:\/\/naps.com.mx\/blog\/wp-content\/uploads\/2020\/10\/naive-bayes-en-python.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2281\" src=\"https:\/\/naps.com.mx\/blog\/wp-content\/uploads\/2020\/10\/naive-bayes-en-python.jpg\" alt=\"naive bayes en python\" width=\"640\" height=\"389\" srcset=\"https:\/\/naps.com.mx\/blog\/wp-content\/uploads\/2020\/10\/naive-bayes-en-python.jpg 640w, https:\/\/naps.com.mx\/blog\/wp-content\/uploads\/2020\/10\/naive-bayes-en-python-300x182.jpg 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>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\u00edsticas (Manning, 1999).<\/p>\n<p>A continuaci\u00f3n 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\u00edas: ocio, tecnolog\u00eda y cultura.<\/p>\n<p>Realizaremos \u00e9ste modelo en tres pasos: 1) obtenci\u00f3n de datos, filtrado y vectorizaci\u00f3n. 2) Implementar un transformador, para convertir a array los datos. 3) Crear el modelo de clasificador Naive Bayes en Python con distribuci\u00f3n Gaussiana y guardarlo en formato Pickle para su posterior uso.<\/p>\n<p>Teniendo ya nuestro modelo entrenado podremos hacer pruebas con cualquier noticia.<\/p>\n<h2>Naive Bayes en Python: Paso 1.<\/h2>\n<h2>Obtenci\u00f3n de datos, filtrado y vectorizaci\u00f3n<\/h2>\n<p>Vamos a utilizar un dataset disponible en:\u00a0<a href=\"https:\/\/drive.google.com\/file\/d\/1v8VgIp5Dbhz0f_-aPfA4DELz7ru1LwQI\/view?usp=sharing\" target=\"_blank\" rel=\"noopener\">https:\/\/drive.google.com\/file\/d\/1v8VgIp5Dbhz0f_-aPfA4DELz7ru1LwQI\/view?usp=sharing<\/a><\/p>\n<p>Consiste en noticias clasificadas que nos servir\u00e1n para entrenar nuestro modelo.<\/p>\n<p>Tambi\u00e9n vamos a utilizar un listado de palabras que deseamos eliminar pues aportan poco o ning\u00fan significado a la interpretaci\u00f3n de las noticias. Esas palabras, conocidas como stop-words, est\u00e1n disponibles en el siguiente archivo:<\/p>\n<p><a href=\"https:\/\/drive.google.com\/file\/d\/1bL46-MfwN0nKqfL8fRNqQ-aAjqYCuz5a\/view?usp=sharing\" target=\"_blank\" rel=\"noopener\">https:\/\/drive.google.com\/file\/d\/1bL46-MfwN0nKqfL8fRNqQ-aAjqYCuz5a\/view?usp=sharing<\/a><\/p>\n<pre class=\"lang:python decode:true\">import pandas as pd\r\nfrom sklearn.feature_extraction.text import TfidfVectorizer\r\nimport json\r\n\r\nnoticias = pd.read_csv(\"noticias.csv\")\r\n\r\n# Eliminar stopwords: palabras cuyo contenido no es muy relevante\r\nwith open(\"stopwords-es.json\") as fname:\r\n    stopwords_es = json.load(fname)\r\n\r\n# Debido a que trabajamos con texto, tenemos que vectorizar, usaremos Tf-idf\r\nvectorizador = \tTfidfVectorizer(stop_words=stopwords_es, max_features=50000)\r\n\r\n# La transformamos en una matriz dispersa\r\nvectorizador.fit_transform(noticias.descripcion)<\/pre>\n<p><strong>Explicaci\u00f3n<\/strong>: Utilizamos pandas para la obtenci\u00f3n 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. \u00c9sto nos crear\u00e1 una matriz dispersa. Seg\u00fan la cantidad escrita en max_features es la cantidad de palabras que puede registrar lo que repercute en el tiempo de procesamiento.<\/p>\n<h2>Naive Bayes en Python: Paso 2.<\/h2>\n<h2>Convertir una matriz dispersa en array<\/h2>\n<p>Creamos una clase DenseTransformer, que nos permite convertir una matriz dispersa en un array.<\/p>\n<pre class=\"lang:python decode:true\">from sklearn.base import BaseEstimator\r\nfrom scipy.sparse import issparse\r\n\r\n# http:\/\/rasbt.github.io\/mlxtend\/\r\nclass DenseTransformer(BaseEstimator):\r\n    def __init__(self, return_copy=True):\r\n        self.return_copy = return_copy\r\n        self.is_fitted = False\r\n\r\n    def transform(self, X, y=None):\r\n        if issparse(X):\r\n            return X.toarray()\r\n        elif self.return_copy:\r\n            return X.copy()\r\n        else:\r\n            return X\r\n\r\n    def fit(self, X, y=None):\r\n        self.is_fitted = True\r\n        return self\r\n\r\n    def fit_transform(self, X, y=None):\r\n        return self.transform(X=X, y=y)<\/pre>\n<h2>Naive Bayes en Python: Paso 3.<\/h2>\n<h2>Crear un pipeline que utilice los pasos anteriores, e incluya un clasificador Naive Bayes con distribuci\u00f3n Gaussiana.<\/h2>\n<pre class=\"lang:python decode:true \"># Importamos el clasificador naive bayes, este tiene tres distribuciones Gausiano, Bernoulli, Multinomial\r\nfrom sklearn.naive_bayes import GaussianNB\r\n# Un pipeline es un conjunto de tuberias o flujos que parten de una entrada (datos) \r\n# hacia una salida (modelo)\r\nfrom sklearn.pipeline import make_pipeline\r\npipeline_gaussiano = make_pipeline(\r\n    vectorizador,\r\n    DenseTransformer(),\r\n    GaussianNB()\r\n)\r\npipeline_gaussiano.fit(X=noticias.descripcion, y=noticias.categoria)\r\nimport pickle\r\npickle.dump(pipeline_gaussiano, open(\"naive_noticias_model.pickle\", \"wb\"))\r\nprint (\"Modelo Creado\")<\/pre>\n<p><strong>Explicaci\u00f3n<\/strong>: En \u00e9ste 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. \u00c9sta matriz es pasada a DenseTransformer que la convierte a un array. \u00c9ste 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\u00f3n de la noticia, y como y (dato de salida) la categor\u00eda. Utilizando pickle se guarda el modelo en un archivo que se puede utilizar m\u00e1s adelante. \u00c9ste proceso puede tardar varios minutos.<\/p>\n<h2>Uso del modelo creado<\/h2>\n<p>Una vez creado nuestro modelo, podemos utilizarlo para clasificar una o miles de noticias.<\/p>\n<pre class=\"lang:python decode:true \">import pickle\r\nfrom sklearn.base import BaseEstimator\r\nfrom scipy.sparse import issparse\r\n\r\n\r\nclass DenseTransformer(BaseEstimator):\r\n    def __init__(self, return_copy=True):\r\n        self.return_copy = return_copy\r\n        self.is_fitted = False\r\n\r\n    def transform(self, X, y=None):\r\n        if issparse(X):\r\n            return X.toarray()\r\n        elif self.return_copy:\r\n            return X.copy()\r\n        else:\r\n            return X\r\n\r\n    def fit(self, X, y=None):\r\n        self.is_fitted = True\r\n        return self\r\n\r\n    def fit_transform(self, X, y=None):\r\n        return self.transform(X=X, y=y)\r\n\r\n\r\npipeline_gaussiano = pickle.load(open(\"naive_noticias_model.pickle\", \"rb\"))\r\n\r\nn1 = [\"\u00bfCansado de que te roben Internet? Aqui puedes darte cuenta de quienes tienen tu wifi\"]\r\nn2 = [\"Los cineastas mexicanos se unen para crear un fondo de emergencia ante la contingencia sanitaria\"]\r\nn3 = [\"10 pel\u00edculas y series de terror en Netflix para ver este fin de semana\"]\r\nr1=pipeline_gaussiano.predict(n1)\r\nr2=pipeline_gaussiano.predict(n2)\r\nr3=pipeline_gaussiano.predict(n3)\r\nprint (\"=====================\")\r\nprint (\"Noticia: \" + str(n1))\r\nprint (\"Categor\u00eda probable: \" + str(r1))\r\nprint (\"Noticia: \" + str(n2))\r\nprint (\"Categor\u00eda probable: \" + str(r2))\r\nprint (\"Noticia: \" + str(n3))\r\nprint (\"Categor\u00eda probable: \" + str(r3))\r\n\r\n<\/pre>\n<p>Lo probamos cargando el modelo creado en archivo pickle y dandole una noticia. El resultado es la categor\u00eda en la que el clasificador pone a la noticia que introducimos.<\/p>\n<p><a href=\"https:\/\/naps.com.mx\/blog\/wp-content\/uploads\/2020\/10\/naive-bayes-python.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2309\" src=\"https:\/\/naps.com.mx\/blog\/wp-content\/uploads\/2020\/10\/naive-bayes-python.png\" alt=\"naive bayes python\" width=\"2430\" height=\"378\" srcset=\"https:\/\/naps.com.mx\/blog\/wp-content\/uploads\/2020\/10\/naive-bayes-python.png 2430w, https:\/\/naps.com.mx\/blog\/wp-content\/uploads\/2020\/10\/naive-bayes-python-300x47.png 300w, https:\/\/naps.com.mx\/blog\/wp-content\/uploads\/2020\/10\/naive-bayes-python-768x119.png 768w, https:\/\/naps.com.mx\/blog\/wp-content\/uploads\/2020\/10\/naive-bayes-python-1024x159.png 1024w\" sizes=\"auto, (max-width: 2430px) 100vw, 2430px\" \/><\/a><\/p>\n<h2>Referencias:<\/h2>\n<p>1. Manning (1999).\u00a0<a href=\"https:\/\/books.google.com.mx\/books?id=YiFDxbEX3SUC&amp;lpg=PA237&amp;dq=naive%20bayes&amp;pg=PA237#v=onepage&amp;q=naive%20bayes&amp;f=false\" target=\"_blank\" rel=\"noopener\">Foundations of Statistical Natural Language Processing.\u00a0<\/a><\/p>\n<h2>Te puede servir:<\/h2>\n<p><iframe loading=\"lazy\" width=\"726\" height=\"408\" src=\"https:\/\/www.youtube.com\/embed\/Ok6n0ys5Edc\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen=\"allowfullscreen\"><\/iframe><\/p>\n","protected":false},"excerpt":{"rendered":"<p>En \u00e9ste art\u00edculo se desarrolla un clasificador Naive Bayes en Python, al que, una vez entrenado, podemos pasarle un titular de noticias y deducir\u00e1 a qu\u00e9 categor\u00eda (ocio, tecnolog\u00eda, cultura) pertenece la noticia.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"amp_status":"","footnotes":""},"categories":[315],"tags":[316,310,284],"class_list":["post-2279","post","type-post","status-publish","format-standard","hentry","category-machine-learning","tag-aprendizaje-supervisado","tag-inteligencia-artificial","tag-machine-learning"],"_links":{"self":[{"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/posts\/2279","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/comments?post=2279"}],"version-history":[{"count":7,"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/posts\/2279\/revisions"}],"predecessor-version":[{"id":2431,"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/posts\/2279\/revisions\/2431"}],"wp:attachment":[{"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/media?parent=2279"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/categories?post=2279"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/tags?post=2279"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}