Mostrando entradas con la etiqueta Text Mining. Mostrar todas las entradas
Mostrando entradas con la etiqueta Text Mining. Mostrar todas las entradas

jueves, 7 de enero de 2021

Clasificador con Word2Vec

El siguiente ejemplo utiliza un dataset de productos de supermercado, y crear un clasificador para predecir la categoría del producto usando el nombre. 

El dataset proviene de un web-scraping realizado en una página de un supermercado, y tiene la siguiente estructura:












Para lograr esto se utiliza el algoritmo de word2vec para transformar el texto en una matriz que represente los features o variables. En este ejemplo no se explica la teoría de word2vec, luego haré otro post sobre eso.


El proceso sigue estos pasos:


PASO 1: Entrenar Word2vec

Se entrena un modelo usando Word2vec,  y se genera un diccionario (word vector) que tiene un vector numérico por cada palabra.  Conceptualmente sería así:


















sábado, 10 de noviembre de 2018

Identificar genero de un nombre

El siguiente script identifica el genero de un nombre dado, utilizando una lista de nombres+genero. Los valores que devuelve son: {m, f, a}, correspondientes a masculino, femenino o ambiguo.

La lista contiene más de 46mil nombres + genero, unificados de las siguientes fuentes:
  • Lista de nombres de la librería nltk
  • Lista nombres de la librería gender_guesser
  • Lista de nombres argentinos publicados aqui

También se hicieron otras modificaciones para nombres hispanos, como borrar apellidos, agregar diminutivos, nombres cortos, alias, entre otros.

Script:
import pandas as pd 
import operator
import re 

def clean_text(txt):
    txt = re.sub("[^a-záéíóúñüäë]", " ", txt.lower())
    txt = re.sub(' +',' ', txt)
    return txt.strip().split()

def df_to_dict(df, key_column, val_column):
    """convierte dos pandas series en un diccionario"""
    xkey = df[key_column].tolist()
    xval = df[val_column].tolist()
    return dict(zip(xkey,xval))

def get_gender2(names):
    names = clean_text(names)
    names = [x for x in names if gender_list.get(x,'a') != 'a']
    gender ={'m':0, 'f':0, 'a':0}
    for i, name in enumerate(names):
        g = gender_list.get(name,'a')
        gender[g] += 1
        gender[g] += 2 if len(names) > 1 and i == 0 and g != 'a' else 0 
    gender['a'] = 0 if (gender['f']+gender['m']) > 0 else 1
    return max(gender.items(), key=operator.itemgetter(1))[0]

if __name__ == '__main__':
    path = 'https://www.dropbox.com/s/edm5383iffurv4x/nombres.csv?dl=1'
    gender_list = pd.read_csv(path)
    gender_list = df_to_dict(gender_list, key_column='nombre', val_column='genero')
    print(get_gender2('lopez jose maria'))
    print(get_gender2('santos contreras'))
    print(get_gender2('maria isabel lopez garcia rodriguez'))
    print(get_gender2('cami lopez'))
    print(get_gender2('majo garcia'))
    print(get_gender2('colon cristobal'))
    print(get_gender2('Cristóbal Colón'))
    print(get_gender2('Cristoforo Colombo'))

end


miércoles, 29 de agosto de 2018

Funcion fonetica para faltas ortograficas


La siguiente función reemplaza letras con similitud fonética en idioma español. Esto para reducir la vectorización de texto en escenarios de documentos con faltas ortográficas (como texto de redes sociales).

Para otras técnicas ver:
How to Write a Spelling Corrector, by Peter Norvin
Fuzzy matching (Soundex, NYSIIS, Metaphone)



script python:
import re 

def clean_fonetic(xtext, py='py3'):
  xtext = str(xtext)
  xtext = xtext.lower()
  
  xtext = re.sub('w', 'u', xtext)

  xtext = re.sub('np', 'mp', xtext) 
  xtext = re.sub('nb', 'mb', xtext)

  xtext = re.sub('ce', 'se', xtext)
  xtext = re.sub('ci', 'si', xtext)

  xtext = re.sub('v', 'b', xtext) 

  xtext = re.sub('z', 's', xtext) 

  xtext = re.sub('lla', 'ya', xtext)
  xtext = re.sub('lle', 'ye', xtext)
  xtext = re.sub('lli', 'yi', xtext)
  xtext = re.sub('llo', 'yo', xtext)
  xtext = re.sub('llu', 'yu', xtext)

  xtext = re.sub('ka', 'ca', xtext)
  xtext = re.sub(r'\bk\b', 'que', xtext)  
  xtext = re.sub(r'\bq\b', 'que', xtext)  
  xtext = re.sub('ke', 'que', xtext)
  xtext = re.sub('ki', 'qui', xtext)
  xtext = re.sub('ko', 'co', xtext)
  xtext = re.sub('ku', 'cu', xtext)

  xtext = re.sub('kra', 'cra', xtext)
  xtext = re.sub('kre', 'cre', xtext)
  xtext = re.sub('kri', 'cri', xtext)
  xtext = re.sub('kro', 'cro', xtext)
  xtext = re.sub('kru', 'cru', xtext)

  xtext = re.sub('ga', 'ga', xtext)
  xtext = re.sub('ge', 'je', xtext)
  xtext = re.sub('gi', 'ji', xtext)
  xtext = re.sub('go', 'go', xtext)
  xtext = re.sub('gu', 'gu', xtext)

  xtext = re.sub(r'\bha', 'a', xtext)
  xtext = re.sub(r'\bhe', 'e', xtext)
  xtext = re.sub(r'\bhi', 'i', xtext)
  xtext = re.sub(r'\bho', 'o', xtext)
  xtext = re.sub(r'\bhu', 'u', xtext)

  xtext = re.sub(r'\bexp', 'esp', xtext)
  xtext = re.sub(r'\bexc', 'ese', xtext)
  xtext = re.sub(r'\bexs', 'ese', xtext)
  xtext = re.sub(r'\bext', 'est', xtext)
  # empiezan por ex+[vocal]
  xtext = re.sub(r'\bexa', 'esa', xtext)
  xtext = re.sub(r'\bexe', 'ese', xtext)
  xtext = re.sub(r'\bexi', 'esi', xtext)
  xtext = re.sub(r'\bexo', 'eso', xtext)
  xtext = re.sub(r'\bexu', 'esu', xtext)
  # termian en exion ixion 
  xtext = re.sub(r'exion\b', 'esion', xtext)
  xtext = re.sub(r'ixion\b', 'ision', xtext)
  xtext = re.sub(r'axion\b', 'asion', xtext)

  xtext = re.sub(r'\be\b', 'y', xtext)
  xtext = re.sub(r'\bi\b', 'y', xtext)
  xtext = re.sub(r'\bu\b', 'o', xtext)

  xtext = re.sub(r'\bx\b', 'por', xtext)

  xtext = re.sub(r'([a-z])\1+', r'\1', xtext) 

  return unicode(xtext) if py=='py2' else str(xtext)

txt = 'verguenza, berguenza, berguensa, berrrrrguensaaa'
clean_fonetic(txt)
# berguensa, berguensa, berguensa, berguensa

lunes, 7 de agosto de 2017

Crear variables dummy de un texto

Para identificar la secuencia de palabras mas repetidas en un texto, y luego hacer variables dummy en SQL, teniendo algo como:















domingo, 16 de octubre de 2016

Sentiment Analysis

El siguiente ejemplo utiliza texto de twitter clasificado previamente como POS, NEG o SEM para predecir si un tweet es positivo, negativo o imparcial sobre amazon. La técnica usada para representar el texto es bag-of-words, donde se mide la aparición de la palabra y no su orden. Estos tweets fueron copiados de la cuenta pública de @amazon. Para mismo ejemplo con R ver nota publicada AQUI

El proceso general sigue estos pasos:

1. Cargar Datos de Dropbox
Para este ejemplo, los datos se cargan de un archivo csv en Dropbox, el cual tiene dos columnas: el texto y la clase a predecir. Queda así:
















2. Crear Corpus

El corpus es el conjunto de documentos, que pueden ser artículos periodisticos, noticias, currículos, tweets, chat, o cualquier colección de textos que se vaya a utilizar para predecir/clasificar textos futuros. En este ejemplo se usan tweets, y la columna "texto" del csv será el corpus. Antes de convertir el texto en una matriz numérica, se hacen la siguiente limpieza/transformación: 
   - Se convierte todo el texto en minúscula
   - Se eliminan todos los caracteres que no son letras (números, signos puntuación, etc.)
   - Se elimina el doble espacio entre las palabras


3. Crear Train y Test

En este paso, se divide el dataset en train y test. Esto se hace tanto para el corpus como para la clase a predecir. Conceptualmente queda así:





















4a. Tokenización 
La Tokenización consiste en dividir el texto a su unidad mínima de significado, esto puede ser la palabra o la oración (o token). Para este ejemplo se utilizó la tokenizacion de palabras usando la función "word_tokenize" de la librería nltk. Estos son algunos de los procesos que hace:
• Stopword: utiliza un diccionario de palabras sin significado, como pronombres, artículos, preposiciones, etc. para eliminar estas palabras de los tweets. A este diccionario le dicen stopword, y se utiliza uno especifico según el idioma del corpus. En este ejemplo se usa el stopword que trae la librería nltk para el idioma ingles.
• Stemming: usa una técnica para reducir las palabras a su raíz (o stems en ingles). Un ejemplo de este proceso puede ser la reducción de las palabras "connected", "connecting", "connection", "connections"; todas estas se sustituyen por su palabra raíz: "connect". En este ejemplo se utilizó el algoritmo PorterStemmer de la librería nltk, que usa una lista de sufijos específicos y condiciones especificas para cada sufijo que evaluarán si este debe eliminarse o no, para así obtener la raíz de la palabra. Para detalle del algoritmo PorterStemmer y su creador (Martin Porter), ver referencia Nro.3. Para otros algoritmos de stemming, ver Ref. Nro 4.



4b. Vectorizacion
Luego que se tiene el texto dividido por palabras con significado, se procede a crear un vector que mida la presencia de cada palabra en el tweet, formando una matriz que le dicen "medelo vectorial". Para medir la presencia de una palabra en un texto existen varias métricas. Algunas son estas:
TF: (Time Frecuenci): es la frecuencia de la palabra en un texto, es decir, cuantas veces aparece una palabra en un tweet.
IDF (Inverse document frequency): esta medida se calcula para cada palabra, realizando el N/log(n), donde N es el total de documentos (o tweet) y n es la cantidad de veces que aparece la palabra en todos los documentos. Esto mide la presencia de una palabra en el corpus, haciéndola menos importante si aparece en la mayoría de los documentos. Es decir, mide qué tan única es la palabra en la colección de documentos.
TF * IDF: Multiplicación de las dos medidas anteriores. Es una forma de identificar la importancia de cada palabra en cada documento, penalizando palabras que son muy comunes.
FLAG: Esta medida marca 1 si la palabra aparece 1 o mas veces en un tweets, sino marca 0.

Conceptualmente la tokenizacion y vectoriacon quedan así:










5. Modelo
Para este ejemplo se utilizó el algoritmo SVM de la librería sklearn. Para detalle de parámetros y funciones, ver referencia nro.6.


6. Predicción
Para saber que tan bueno es el modelo, se utilizó la matriz de confusión para calcular la eficiencia del modelo en test. 

Al evaluar el modelo se tienen estos resultados. En una siguiente nota, veré como ajustar un modelo a este mismo problema para tener mejores resultados..