domingo, 16 de abril de 2017

Creación de variables de grupo

Si se tiene un dataset para predecir una clase, y dentro de las variables existen algunas que son discretas (como ciudad, empresa, rubro, etc), puede usarse esta variable discreta para crear nuevas variables "dummies" que agrupen los valores que mejor ajusten la clase a predecir.

En este ejemplo se transforma la variable discreta "state" para crear una matriz dispersa con valores dummies, luego se ajusta un modelo usando el algoritmo ExtraTreesClassifier para predecir la clase "churn". Después de tener el modelo se extrae la importancia de las variables para identificar (usando percentiles) las nuevas variables dummies a crear.

Nota: Para la importancia de la variable, el algoritmo ExtraTreesClassifier usa la medida "Mean Decrease Impurity Importance", también llamado "Gini importance", "Mean Decrease Gini", etc. Para detalles, ver Referencia No.1. Para detalles sobre sesgos en el calculo de la importancia, ver Referencia No.2. Para ver las imágenes, estas se pueden descargar AQUI


El proceso conceptual sigue estos pasos:

PASO 1
Cargar el dataset que contiene la variable a predecir (churn en este caso) y la variable discreta a descomponer. Seria algo así:
















PASO 2
Transoformar variable discreata en matriz dispersa, usando la función get_dummies de la librería pandas, quedando así:





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 @amazonPara 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..

















sábado, 20 de agosto de 2016

Encontrar lambda de Box-Cox

El siguiente script calcula el valor lambda que hace que una variable, al ser elevada a este valor, tenga una distribucion mas cercana a una distribucion normal, segun tecnica Box-Cox. Esto con el objetivo de identificar cuales son las variables de un dataset que no tienen una distribución normal y que pueden transformarse para obtener mayor información de ellas.

NOTA: Este script es un ejemplo de busqueda, existe una funcion para esto en la librería scipy. Ver Referencia 1.

El script sigue estos paso:
1. carga el dataset boston.csv desde dropbox
2. crea la funcion is_not_normal que devuelve True si la asimetria de la variable es menor a -1 o mayor a 1, y si ademas el coeficiente de variacion (std/avg) es mayor a 1.
3. crea la funcion find_lambda que recibe el dataset en formato pandas.DataFrame y busca las variables que no son normales (usando la funcion is_not_normal) para luego imprimir los valores lambda de esas variables no normales.



Conceptualmente, la busqueda de el valor lambda seria así:

















las formas generales de exponentes son estas:










Para el dataset boston, una de las variables que no tiene una distribucion normal es crim,
y la salida del script seria algo así:





si graficamos la variable crim vs la crim^-0.05, queda así:



lunes, 15 de agosto de 2016

Apuntes sobre DataFrame con PANDAS

El siguiente script reune funcionalidades de un DataFrame de pandas:
  • Crear un DataFrame
  • Join / Concatenar / Group by
  • Agregar/Editar Columna
  • Filtrar Datos
  • Explorar






Ensamble: Random Forest + Regresion Logistica

El siguiente script hace un ensamble de dos algoritmos: Random Forest y Regresion Logistica. Esto para predecir la variable survived del data set titanic.

El Scrip sigue estos pasos:
1. Carga csv desde dropbox
2. Divide el data set en train (70%) y test (30%)
3. Convierte los set de train y test en matriz numpy, solo por performance.
4. Crea una lista_algoritmos a utilizar, para luego crear los modelos y predecir a través de un loop.
5. Hace el promedio de las dos predicciones, y luego clasifica como verdadero los valores mayor a 0.5, de lo contrario, clasifica como falso.
6. Imprime las metricas de eficiencia de la prediccion del modelo ensamblado.


domingo, 14 de agosto de 2016

Random Forest

El siguiente script utiliza el algoritmo Random Forest para predecir la variable survived del data set titanic. Para detalle del algoritmo Random Forest, ver paper de su creador, Leo Breiman, publicado AQUI, y también AQUI.

En forma resumida, el algoritmo sigue este proceso (copiado de nota publicada AQUI):
  1. Selecciona individuos al azar (usando muestreo con reemplazo) para crear diferentes set de datos.
  2. Crea un árbol de decisión con cada set de datos, obteniendo diferentes arboles, ya que cada set contiene diferentes individuos y diferentes variables.
  3. Al crear los arboles se eligen variables al azar en cada nodo del arbol, dejando crecer el arbol en profundidad (sin podar).
  4. Predice los nuevos datos usando el "voto mayoritario", donde clasificará como "positivo" si la mayoría de los arboles predicen la observación como positiva.


Este script tiene las siguientes salidas:


Matriz de Confusión:








Métricas:









donde:
precision = (predicciones acertadas de laclase_x) / (total casos predichos para clase_x)
recall        = (predicciones acertadas de la clase_x) / (total de casos existentes en clase_x)
f1-score    = (2 * precision * recall) / (precision + recall)
support   = total casos en cada fila


Importancia de Variables:













Regresion Logistica con DataFrame

El siguiente script utiliza DataFrame para ajustar un modelo de regresión logística.
Para mismo ejemplo con numpy.matrix y detalle de regresión logística, ver nota publicada AQUI.


script:
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn import metrics
import pandas as pd

# DATA
#---------------------------------------------------------------------------------------------
data = pd.read_csv('https://dl.dropboxusercontent.com/u/59930995/dataset/titanic2.csv?dl=1')
clase_name = 'survived' # nombre de variable a predecir
headers = data.columns.values.tolist()
headers.remove(clase_name)

# TRAIN TEST
#---------------------------------------------------------------------------------------------
np.random.seed(123)
m_train    = np.random.rand(len(data)) < 0.5
data_train = data.iloc[m_train,]
data_test  = data.iloc[~m_train,]

# MODELO
modelo = LogisticRegression(random_state=1)
modelo.fit(data_train[headers], data_train["survived"])

# PREDICCION
#---------------------------------------------------------------------------------------------
prediccion = modelo.predict(data_test[headers])

# METRICAS
#---------------------------------------------------------------------------------------------
print(metrics.classification_report(y_true=data_test["survived"], y_pred=prediccion))
print(pd.crosstab(data_test["survived"], prediccion, rownames=['REAL'], colnames=['PREDICCION']))