Archivos de la categoría Data Mining

Solventamos los peligros del análisis cluster con SVM

Retomamos un asunto tratado en días anteriores, los peligros de realizar un análisis de agrupamiento basado en las distancias entre observaciones. ¿Cómo podemos evitar este problema? Empleando máquinas de vectores de soporte, traducción de Support Vector Machines (SVM). Esta técnica de clasificación de la que ya hablamos en otra entrada nos permite separar observaciones en base la creación de hiperplanos que las separan. Una función kernel será la que nos permita crear estos hiperplanos, en el caso que nos ocupa tenemos sólo dos variables, necesitamos crear líneas de separación entre observaciones. En la red tenéis una gran cantidad de artículos sobre estas técnicas.

Para ilustrar como funciona retomamos el ejemplo anterior:


#GRUPO 1
x = runif(500,70,90)
y = runif(500,70,90)
grupo1 = data.frame(cbind(x,y))
grupo1$grupo = 1


#GRUPO 2
x = runif(1000,10,40)
y = runif(1000,10,40)
grupo2 = data.frame(cbind(x,y))
grupo2$grupo = 2


#GRUPO 3
x = runif(3000,0,100)
y = runif(3000,0,100)
grupo3.1 = data.frame(cbind(x,y))
grupo3.1$separacion=(x+y)
grupo3.1 = subset(grupo3.1,separacion>=80 & separacion <=140,select=-separacion)
grupo3.1 = subset(grupo3.1,y>0)
grupo3.1$grupo = 3


#UNIMOS TODOS LOS GRUPOS
total=rbind(grupo1,grupo2,grupo3.1)
plot(total$x,total$y,col=c(1,2,3)[total$grupo])

El paquete de R que vamos a emplear es kernlab, Sigue leyendo Solventamos los peligros del análisis cluster con SVM

Un peligro del análisis cluster

Quería plantearos un ejemplo de análisis cluster para observar el peligro que tiene agrupar observaciones en base a grupos homogéneos creados con distancias multivariantes. Para ilustrar el ejemplo trabajamos con R, creamos grupos en base a 2 variables, esto nos facilita los análisis gráficos. Simulamos el conjunto de datos con el que trabajamos:


#GRUPO 1
x = runif(500,70,90)
y = runif(500,70,90)
grupo1 = data.frame(cbind(x,y))
grupo1$grupo = 1


#GRUPO 2
x = runif(1000,10,40)
y = runif(1000,10,40)
grupo2 = data.frame(cbind(x,y))
grupo2$grupo = 2


#GRUPO 3
x = runif(3000,0,100)
y = runif(3000,0,100)
grupo3.1 = data.frame(cbind(x,y))
grupo3.1$separacion=(x+y)
grupo3.1 = subset(grupo3.1,separacion>=80 & separacion <=140,select=-separacion)
grupo3.1 = subset(grupo3.1,y>0)
grupo3.1$grupo = 3


#UNIMOS TODOS LOS GRUPOS
total=rbind(grupo1,grupo2,grupo3.1)
plot(total$x,total$y,col=c(1,2,3)[total$grupo])

Los grupos parecen claros:

linealidad_cluster1.png

Cabe preguntarse: ¿qué sucede si segmentamos en base a centroides? Para responder a esta pregunta hacemos un análisis no jerárquico, empleamos el algoritmos de las k-medias del que ya se ha hablado en este blog en alguna ocasión:


distancias = dist(total)
clus = kmeans(distancias,3)
total$grupo_nuevo = clus$cluster
plot(total$x,total$y,col=c(1,2,3)[total$grupo_nuevo])

linealidad_cluster2.png
Necesitamos un objeto con las distancias y sobre él utilizamos la función kmeans que es la más popular y sencilla. El objeto resultante de la realización del modelo tiene una variable cluster que añadimos a nuestros datos y tras graficar vemos que es evidente que no ha funcionado muy correctamente, nos ha creado los 3 grupos homogéneos en base a la distancia entre observaciones, pero no son los segmentos deseados… Mucho cuidado cuando utilicemos este tipo de técnicas.

¿Cómo podemos realizar una segmentación más apropiada para estos datos? ¿Qué técnica podemos utilizar? La respuesta en breve. Espero que esto sirva para  desordenar alguna conciencia.

Data mining, Business intelligence (y/o la nube)

Hace tiempo que quería publicar una entrada en respuesta a estos comentarios escritos en el blog. Se trata de analizar las búsquedas en Google a través de Google Trends de los términos: Business Intelligence, Data Mining, Cloud Computing y NOSQL. El resultado es más que interesante:

busquedas_google.png

En rojo tenemos Data Mining, en azul tenemos Business Intelligence, en naranja Cloud Computing y en verde NOSQL. A la vista de este gráfico cabe preguntarse ¿es R en la nube el futuro de la profesión? 

Sobremuestreo y pesos a las observaciones. Ahora con R

De nuevo volvemos a la entrada de ayer para replicar el código SAS utilizado en R. Se trata de realizar 3 modelos de regresión logística con R para estudiar como influyen en los parámetros el uso de un conjunto de datos con sobremuestreo o el uso de un conjunto de datos donde asignamos pesos a las observaciones. El programa es sencillo pero tiene un uso interesante de la librería de R sampling. Aquí tenéis el código:

#Regresión logística perfecta
num = 100000
x = rnorm(num); y=rnorm(num)
p=1/(1+exp(-(-5.5+2.55*x-1.2*y)))
z=rbinom(num,1,p)
datos_ini=data.frame(cbind(x,y,z))
table(datos_ini$z)

modelo.1 = glm(z~x+y,data=datos_ini,family=binomial)
summary(modelo.1)

El mismo modelo que planteamos con SAS en la anterior entrada nos permite realizar una regresión logística perfecta. Veamos como se plantea la realización del sobremuestreo con R:

#Realizamos el sobremuestreo con la librería sampling
library( sampling )
selec <- strata( datos_ini, stratanames = c("z"), size = c(50000,50000), method = "srswr" ) table(selec$z)

modelo.2 = glm(z~x+y,data=datos_ini[selec$ID_unit,],
family=binomial)
summary(modelo.2)

Habrá que volver sobre el tema del muestreo para analizar las posibilidades de la librería sampling, en este caso realizamos muestreo estratificado con la función strata y muestreo aleatorio con reemplazamiento. Replicamos el proceso asignando pesos:

#Realizamos el proceso asignando pesos
pct=sum(datos_ini$z)/num
datos_ini$peso = ifelse(datos_ini$z==1, 0.5/pct, 0.5/(1-pct))
tapply(datos_ini$peso,datos_ini$z,sum)

modelo.3 = glm(z~x+y,data=datos_ini,
family=binomial, weights=peso)
summary(modelo.3)

Y obtenemos los mismos resultados (que sorpresa). Saludos.

En la regresión logística ¿el sobremuestreo es lo mismo que asignar pesos a las observaciones?

Hoy vamos a volver sobre el tema del sobremuestreo. Respondemos a un lector, Roberto, que hace mucho tiempo planteó una duda al respecto. La duda se puede resumir: En un modelo logístico, ¿equivale entrenar un modelo con las observaciones sobremuestreadas a entrenar el modelo poniendo un peso a cada observación? Esta cuestión nunca me la había planteado. Siempre había realizado un sobremuestreo de las observaciones adecuando la población de casos negativos a la población de casos positivos. Si estás habituado a trabajar con Enterprise Miner de SAS es habitual asignar pesos a las observaciones para realizar el proceso de sobremuestreo. ¿Obtendremos distintos resultados?

Vamos a estudiar un ejemplo con SAS y analizar que está pasando:

*REGRESION LOGISTICA PERFECTA;
data logistica;
do i=1 to 100000;
  x=rannor(8);
  y=rannor(2);
  prob=1/(1+exp(-(-5.5+2.55*x-1.2*y)));
  z=ranbin(8,1,prob);
  output;
end;
drop i;
run;

title "Logistica con un 5% aprox de casos positivos";
proc freq data=logistica;
tables z;
quit;

Tenemos un conjunto de datos SAS con 100000 observaciones aleatorias y dos variables independientes (x e y) con distribución normal y creamos una variable dependiente z que toma valores 0 o 1 en función de la probabilidad de un modelo logístico. Es decir, podemos modelizar una regresión logística perfecta con parámetros Z=5.5 - 2.55x + 1.2y Esta distribución nos ofrece aproximadamente un 5% de casos positivos. A ser un modelo logístico perfecto Sigue leyendo En la regresión logística ¿el sobremuestreo es lo mismo que asignar pesos a las observaciones?

Da comienzo la lectura de “The Elements of Statistical Learning”

Interesante iniciativa de Juanjo Gibaja y Carlos Gil Bellosta consistente en leer el libro “The Elements of Statistical Learning”. La idea es crear un grupo de trabajo que lea de forma coordinada el libro, pero además van a implementar en R los ejercicios y ejemplos. Desde esta bitácora no vamos a colaborar en la lectura pero si vamos a colaborar en la divulgación de resultados. Seguiremos muy de cerca este proyecto.

El sobremuestreo ¿mejora mi estimación?

El sobremuestreo (oversampling) es una técnica de muestreo que se emplea habitualmente cuando tenemos una baja proporción de casos positivos en clasificaciones binomiales. Los modelos pueden “despreciar” los casos positivos por ser muy pocos y nuestro modelo no funcionaría. Para incrementar el número de casos positivos se emplea el sobremuestreo. Ejemplos habituales pueden ser los modelos de fraude, un 99% de las compras son correctas, un 1% son fraudulentas. Si realizo un modelo puedo estar seguro al 99% de que todas mis compras son correctas, en este caso hemos de realizar un sobremuestreo para incrementar nuestros casos de fraude y poder detectar los patrones.

Personalmente no sabría deciros el porcentaje de casos positivos a partir del cual sería necesario llevar a cabo un proceso de remuestreo. A mi particularmente me gusta hacerlo siempre. Por lo menos realizar algunas pruebas para identificar aquellas variables que son más influyentes y comenzar a eliminar aquellas que no van a funcionar. Busco exagerar. Tampoco me quiero mojar mucho sobre la proporción de casos positivos y negativos, pero si estamos realizando un nuevo muestreo podemos emplear perfectamente un 50% para ambos, aquí si que dependemos del número de registros con el que estemos trabajando ya que al final el sobremuestreo será la repetición de los casos positivos sobre la tabla de entrada del modelo.

Sin embargo, cuando ya tengo decidido como va a ser mi modelo no me gusta realizar sobremuestreo. Lo considero un paso previo (algún lector del blog considerará estas palabras incoherentes). Después de toda esta exposición teórico-práctica de malos usos de un dinosaurio  en realidad lo que cabepreguntarse es ¿mejora la estimación un modelo con sobremuestreo?

Abrimos R y Tinn-R y manos a la obr Sigue leyendo El sobremuestreo ¿mejora mi estimación?

Árboles de decisión con SAS Base (con R por supuesto)

Con SAS Base podemos hacer árboles de decisión porque tenemos R. Así de sencillo. Vamos a utilizar SAS para gestionar nuestros datos y R será la herramienta que utilicemos para la realización del modelo de árbol de decisión. Posteriormente emplearemos las reglas generadas por el modelo para etiquetar a nuestros clientes en SAS. Con esta entrada pretendo ilustrar una serie de ejemplos en los que comunico SAS con R. Una herramienta nos sirve para el tratamiento de datos y la otra la utilizaremos para realizar modelos que no están al alcance de SAS. Para realizar esta comunicación SAS-R os planteo la creación en SAS de ficheros de texto con las instrucciones en R y la ejecución en modo batch de R con ese código creado en SAS. Aquí tenéis punto por punto el ejemplo:

El primer paso, como es habitual, es crear un conjunto de datos SAS con datos aleatorios que nos sirva de ejemplo Sigue leyendo Árboles de decisión con SAS Base (con R por supuesto)

Trucos R. Llevar a SAS las reglas de un árbol de decisión

Vuelvo hoy con el uso de rpart para la creación de árboles de decisión con R. Pero hoy, además de realizar un modelo de árbol con R quiero presentaros una función que nos permite guardar las reglas generadas con nuestro modelo en un fichero de texto para su posterior utilización con SAS. Retomamos un ejemplo visto con anterioridad en la bitácora con ligeras modificaciones:
#Inventamos un objeto para realizar el modelo
#En una cartera de clientes nuestro modelo tiene que identificar
#cuales contratan un PVI
#
clientes=20000
saldo_vista=runif(clientes,0,1)*10000
saldo_ppi=(runif(clientes,0.1,0.2)*rpois(clientes,1))*100000
saldo_fondos=(runif(clientes,0.1,0.9)*(rpois(clientes,1)-1>0))*100000
edad=rpois(clientes,60)
datos_ini<-data.frame(cbind(saldo_vista,saldo_ppi,saldo_fondos,edad))
datos_ini$saldo_ppi=(edad<=68)*datos_ini$saldo_ppi
#Creamos la variable objetivo a partir de un potencial
datos_ini$potencial=runif(1,0,1)+
(log(edad)/(log(68))/100) +
runif(1,0,0.001)*(saldo_vista>5000)+
runif(1,0,0.001)*(saldo_fondos>10000)+
runif(1,0,0.007)*(saldo_ppi>10000)-
runif(1,0,0.2)
datos_ini$pvi=as.factor((datos_ini$potencial>=quantile(datos_ini$potencial,
0.90))*1)
#
#Empleamos rpart para la realización del modelo
#
library(rpart)
arbol=rpart(as.factor(pvi)~edad+saldo_ppi+saldo_fondos,
data=datos_ini,method="anova",
control=rpart.control(minsplit=30, cp=0.0008) )

Tenemos un objeto rpart llamado arbol. En este punto necesitamos disponer de las reglas generadas por el modelo para SAS, donde el módulo específico para poder realizar determinados modelos tiene un precio muy alto. Buscando en Google encontraremos este link. En él tenemos una genial función de R list.rules.rpart que nos permite identificar las reglas que ha generado el modelo Sigue leyendo Trucos R. Llevar a SAS las reglas de un árbol de decisión

El debate político o como analizar textos con WPS

¿Qué hacen los políticos españoles en el Congreso de los Diputados? Las tertulias radiofónicas están llenas de analístas políticos que podrán opinar sobre la labor del Congreso mejor que yo. Sin embargo yo tengo WPS, sé programar en SAS y en la web del Congreso están todas las sesiones y todas las intervenciones de la democracia. Pues con estos elementos vamos a iniciar un proceso de text mining, aunque no llegaremos a realizar ningún análisis complejo. Para comenzar, como siempre, necesito datos. Me he guardado la sesión del Congreso de los Diputados del día 26/01/2011 como web y posteriormente con Word la he salvado como fichero de texto (ojo con las codificaciones). De todos modos podéis descargaros aquí el fichero.

Comienza nuestro trabajo con WPS y lo primero es crear una tabla con la sesión:

filename sesion "D:\raul\wordpress\text mining WPS\PopUpCGI.txt" ;
data sucio;
infile sesion RECFM=V LRECL=10000;
informat linea1 $10000.;
format linea1 $10000.;
input linea1 $10000. ;
run;

Comenzamos con lo más sencillo pero considero necesario realizar unos comentarios. Cuando hacemos el INFILE la longitud de registro es mejor que sea variable, así aprovechamos los saltos de línea, como longitud de registro 10000 caracteres me parecen suficientes, esto no tiene mucha ciencia pero considero que las intervenciones no habrían de tener más de 10000 caracteres. Ahora tenemos una tabla de frases y yo quiero llegar a una tabla de palabras, será necesario un bucle que recorra caracter a caracter y separe las palabras Sigue leyendo El debate político o como analizar textos con WPS