En primer lugar, ¿qué es la clasificación de texto?
La clasificación de texto es un proceso automatizado de clasificación de texto en categorías predefinidas. Podemos clasificar los correos electrónicos en spam o no spam, los artículos de noticias en diferentes categorías, como Política, Bolsa, Deportes, etc.
Esto se puede hacer con la ayuda del procesamiento del lenguaje natural y diferentes algoritmos de clasificación como Naive Bayes, Máquinas de Vectores de Soporte e incluso redes neuronales en Python.
¿Qué es el procesamiento del lenguaje natural?
El procesamiento del lenguaje natural (NLP) es un campo de inteligencia artificial (AI) que permite que los programas de computadora reconozcan, interpreten y manipulen los lenguajes humanos.
Si bien una computadora puede ser bastante buena para encontrar patrones y resumir documentos, debe transformar palabras en números antes de darles sentido. Esta transformación es necesaria porque las máquinas “aprenden” gracias a las matemáticas, y las matemáticas no funcionan muy bien con las palabras. Antes de transformar las palabras en números, a menudo se limpian de elementos como caracteres especiales y puntuación, y se modifican en formas que las hacen más uniformes e interpretables.
Paso 1: Agregar las bibliotecas requeridas.
Paso 2: Establecer una semilla aleatoria. Esto se usa para reproducir el mismo resultado cada vez si el script se mantiene consistente; de lo contrario, cada ejecución producirá resultados diferentes. La semilla se puede establecer en cualquier número.
Paso 3: Cargar el conjunto de datos.
Paso 4: Preprocesar el contenido de cada texto. Este es un paso muy importante.
Los datos del mundo real a menudo son incompletos, inconsistentes y/o carecen de ciertos comportamientos o tendencias, y es probable que contengan muchos errores. El preprocesamiento de datos es un método comprobado para resolver tales problemas. Esto ayudará a obtener mejores resultados a través de los algoritmos de clasificación. Puede ver el detalle del proceso de limpieza a continuación en "Detalle de los pasos de preprocesamiento de datos".
Paso 5: Separar los conjuntos de datos de entrenamiento y prueba.
Paso 6: Codificación del objetivo.
La etiqueta codifica la variable de destino para transformar su tipo de cadena, si es así, en valores numéricos que el modelo pueda entender. Esto también se puede hacer como uno de sus primeros pasos, pero asegúrese de convertirlo antes de dividir los datos en entrenamiento y prueba.
Paso 7: Bolsa de palabras (vectorización)
Es el proceso de convertir palabras de oraciones en vectores de características numéricas. Es útil ya que los modelos requieren que los datos estén en formato numérico. Entonces, si la palabra está presente en esa oración en particular, pondremos 1; de lo contrario, 0. El método más popular se llama TF-IDF. Significa "Frecuencia de término - Frecuencia de documento inverso". TF-IDF son puntajes de frecuencia de palabras que intentan resaltar palabras que son más interesantes, por ejemplo, frecuentes en un documento pero no entre documentos.
Esto ayudará a TF-IDF a construir un vocabulario de palabras que ha aprendido de los datos del corpus y asignará un número entero único a cada una de estas palabras. De acuerdo con el siguiente código, habrá un máximo de 5000 palabras únicas. Finalmente, transformaremos X_train y X_test en X_train_Tfidf y X_test_Tfidf vectorizados. Estos ahora contendrán para cada fila una lista de números enteros únicos y su importancia asociada según lo calculado por TF-IDF.
1Tfidf_vect = TfidfVectorizer(max_features=5000) 2Tfidf_vect.fit(news_df['text_final']) 3 4X_train_Tfidf = Tfidf_vect.transform(X_train) 5X_test_Tfidf = Tfidf_vect.transform(X_test)
Las siguientes partes del proceso de limpieza tendrán diferentes ejemplos de implementación de código. Siempre puede agregar o eliminar los pasos que mejor se adapten al conjunto de datos con el que está tratando:
1. Quita las filas en blanco o duplicadas de los datos. Podemos hacer esto usando dropna y drop_duplicates respectivamente.
2. Cambia todo el texto a minúsculas porque Python interpreta mayúsculas y minúsculas de manera diferente. Aquí un ejemplo de cómo convertir entradas a minúsculas. Recuerda que puedes incluir este paso como parte de una función de limpieza.
1news_df['text'] = [entry.lower() for entry in news_df['text']]
3. Elimina texto no alfabético, tags y caracteres de puntuación. Esto se puede hacer con la ayuda de expresiones regulares.
4. Elimina palabras vacías. Elimina todas las palabras de uso frecuente, como "yo, o ella, tengo, hiciste, tú, para".
Los pasos 3 y 4 del proceso de limpieza (eliminación de caracteres especiales y palabras vacías) se pueden lograr fácilmente usando los módulos nltk y string. Veamos un ejemplo de la puntuación y las palabras vacías que ya han definido estos módulos.
1import string 2import nltk 3 4nltk.download('stopwords') 5nltk.download('punkt') 6 7stopwords = nltk.corpus.stopwords.words('english') 8punctuation = string.punctuation 9 10print(stopwords[:5]) 11print(punctuation) 12>>> ['i', 'me', 'my', 'myself', 'we'] 13>>> !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ 14 15# Creación de funciones para eliminar la puntuación y las palabras vacías 16 17def remove_punctuation(text): 18 no_punct=[words for words in text if words not in string.punctation] 19 words_wo_punct=''.join(no_punct) 20 return words_wo_punct 21news_df['title_wo_punct'] = news_df['title'].apply(lambda x: remove_punctuation(x)) 22 23def remove_stopwords(text): 24 text=[word for word in text if word not in stopword] 25 return text 26news_df['title_wo_punct_split_wo_stopwords'] = news_df['title_wo_punct_split'].apply(lambda x: remove_stopwords(x)) 27
También podemos decidir eliminar las palabras vacías agregando un parámetro llamado "stop_words" en el "TFidfVectorizer" del paso de vectorización.
5. Tokenización de palabras. Es el proceso de dividir un flujo de texto en palabras, frases, símbolos u otros elementos significativos llamados tokens. La lista de tokens se convierte en entrada para su posterior procesamiento. La biblioteca NLTK tiene word_tokenize y sent_tokenize para dividir fácilmente un flujo de texto en una lista de palabras u oraciones, respectivamente. Aquí un par de ejemplos. El segundo ejemplo es una función que tokeniza y convierte a minúsculas al mismo tiempo.
1# Ejemplo 1 2news_df['text']= [word_tokenize(entry) for entry in news_df['text']] 3 4# Ejemplo 2 : 5def tokenize(text): 6 split=re.split("\W+",text) #--->\W+” se divide en uno o más caracteres que no son palabras 7 return split 8news_df['title_wo_punct_split']=news_df['title_wo_punct'].apply(lambda x: tokenize(x.lower())) #---> La nueva columna ha creado una lista, al dividir todos los caracteres que no son palabras.
6. Lematización/Derivación. Es el proceso de reducir las formas flexivas de cada palabra a una base o raíz común. El objetivo principal es reducir las variaciones de una misma palabra, reduciendo así el corpus de palabras que incluimos en el modelo. La diferencia entre la derivación y la lematización es que la derivación corta el final de la palabra sin tener en cuenta el contexto de la palabra. Mientras que la Lematización considera el contexto de la palabra y la acorta a su forma raíz según la definición del diccionario. La Derivación es un proceso más rápido en comparación con la Lematización. Por lo tanto, es un compromiso entre velocidad y precisión. Por ejemplo, si el mensaje contiene alguna palabra de error como "frei" que podría estar mal escrita para "gratis". La Derivación reducirá esa palabra de error a su palabra raíz, es decir, "fre". Como resultado, “fre” es la raíz de la palabra tanto para “free” como para “frei”.
1print(ps.stem('believe')) 2print(ps.stem('believing')) 3print(ps.stem('believed')) 4print(ps.stem('believes'))
Los resultados del tallo para todo lo anterior es believ
1print(wn.lemmatize(“believe”)) 2print(wn.lemmatize(“believing”)) 3print(wn.lemmatize(“believed”)) 4print(wn.lemmatize(“believes”))
Los resultados de la lematización en el orden de las declaraciones impresas son: creer, creyendo, creyó y creencia. La lematización produce el mismo resultado si la palabra no está en el corpus. Creer está lematizado a creencia (la raíz de la palabra)
¿Qué es una nube de palabras?
Las nubes de palabras son una forma útil de visualizar datos de texto porque facilitan la comprensión de las frecuencias de las palabras. Las palabras que aparecen con más frecuencia dentro del texto del correo electrónico aparecen más grandes en la nube. Las nubes de palabras facilitan la identificación de "palabras clave".
1# Importación de bibliotecas 2import pandas as pd 3import sqlite3 4import regex as re 5import matplotlib.pyplot as plt 6from wordcloud import WordCloud 7 8# Cargando conjunto de datos 9df = pd.read_csv('emails.csv') 10 11# Visualizar primeras filas 12 13df.head()
1# EDA: eliminar las filas duplicadas y establecer algunos recuentos de referencia. 2print("spam count: " +str(len(df.loc[df.spam==1]))) 3print("not spam count: " +str(len(df.loc[df.spam==0]))) 4print(df.shape) 5df['spam'] = df['spam'].astype(int) 6 7df = df.drop_duplicates() 8df = df.reset_index(inplace = False)[['text','spam']]
Todo el texto debe estar en minúsculas y sin signos de puntuación ni caracteres especiales, para facilitar su análisis. Usando expresiones regulares, es fácil limpiar el texto usando un bucle. El siguiente código crea una lista vacía clean_desc, luego usa un bucle for para recorrer el texto línea por línea, poniéndolo en minúsculas, eliminando la puntuación y los caracteres especiales, y agregándolo a la lista. Finalmente, reemplaza la columna de texto con los datos en la lista clean_desc.
1clean_desc = [] 2 3for w in range(len(df.text)): 4 desc = df['text'][w].lower() 5 6 # Eliminar puntuación 7 desc = re.sub('[^a-zA-Z]', ' ', desc) 8 9 # Eliminar tags 10 desc=re.sub("</?.*?>"," <> ",desc) 11 12 # Eliminar dígitos y caracteres especiales 13 desc=re.sub("(\\d|\\W)+"," ",desc) 14 15 clean_desc.append(desc) 16 17# Asignar las descripciones limpias al marco de datos 18df['text'] = clean_desc 19 20df.head(3)
Eliminar palabras vacías del texto del correo electrónico permite que se destaquen las palabras frecuentes más relevantes. ¡Eliminar palabras vacías es una técnica común! Algunas bibliotecas de Python como NLTK vienen precargadas con una lista de palabras vacías, pero es fácil crear una desde cero. El siguiente código incluye algunas palabras relacionadas con el correo electrónico como "re" y "asunto", pero depende del analista determinar qué palabras deben incluirse o excluirse.
1stop_words = ['is','you','your','and', 'the', 'to', 'from', 'or', 'I', 'for', 'do', 'get', 'not', 'here', 'in', 'im', 'have', 'on', 're', 'new', 'subject']
Ahora, ¿cómo podemos construir una nube de palabras?
Hay una biblioteca de Python para crear nubes de palabras. Podemos usar pip para instalarlo. La nube de palabras se puede configurar con varios parámetros como alto y ancho, palabras vacías y palabras máximas, y se puede mostrar usando Matplotlib.
1pip install wordcloud 2 3wordcloud = WordCloud(width = 800, height = 800, background_color = 'black', stopwords = stop_words, max_words = 1000 4 , min_font_size = 20).generate(str(df['text'])) 5 6# Trazar la nube de palabras 7fig = plt.figure(figsize = (8,8), facecolor = None) 8plt.imshow(wordcloud) 9plt.axis('off') 10plt.show()
Cuando observas una nube de palabras, fíjate que se trata principalmente de palabras sueltas. Cuanto mayor sea la palabra, mayor será su frecuencia. Para evitar que la nube de palabras genere oraciones, el texto pasa por un proceso llamado tokenización. Es el proceso de dividir una oración en palabras individuales. Las palabras individuales se llaman tokens.
Fuente:
https://projectgurukul.org/spam-filtering-machine-learning/
https://www.youtube.com/watch?v=VDg8fCW8LdM
https://towardsdatascience.com/nlp-in-python-data-cleaning-6313a404a470