domingo, 14 de septiembre de 2014

Predecir Clientes con Naive Bayes

Una empresa quiere llamar a sus clientes para ofrecerles un nuevo producto, pero quiere contactar unicamente a los clientes con mayor probabilidad de compra, para ahorrar en el costo por llamada.

Si se tienen DATOS HISTÓRICOS (de campañas anteriores o pruebas pilotos) de clientes que SI aceptaron y clientes que NO aceptaron comprar un producto cuando fueron contactados, y también se tienen registros de NUEVOS CLIENTES a los que se le quiere calcular la probabilidad de compra, teniendo algo como:





Puede utilizarse el método Bayes Ingenuo (o Naive Bayes)  con la técnica Maximo a Posteriori (MAP) para clasificar a los clientes según su probabilidad de compra. Para esto se multiplica la probabilidad de Compra=Si de cada atributo (EstadoCvivil,Profesion, etc.) y el resultado se multiplica por la probabilidad total de Compra=Si. Luego se hace lo mismo con la probabilidad para Compra=No de cada atributo y se multiplica por la totalidad de Compra=No. El resultado que tenga mayor valor (Compra=Si, ó Compra=No), será el elegido por tener mayor probabilidad de compra.


El cálculo de la probabilidad de cada atributo y para cada cliente nuevo seria algo como:



El resultado es el siguiente archivo csv:







Los archivos Datos_Historicos.csv y Nuevos_Clientes.csv pueden descargarse AQUI


La programación en R sería la siguiente:

# --------------------------------------------------------------------------------
#  Crea las tablas (ó data frame) Datos_Historicos y Nuevos_Clientes
Datos_Historicos <- read.csv("C:/Archivos/Datos_Historicos.csv") # tabla de entrenamiento
Nuevos_Clientes <- read.csv("C:/Archivos/Nuevos_Clientes.csv") # tabla de test
 
# --------------------------------------------------------------------------------
# Crea  Probabilidades con Datos_Historicos  y asigna predicción a Nuevos_Clientes
library(e1071)  # librerias de naiveBayes
Probabilidades <- naiveBayes(Compra ~., data=Datos_Historicos[-1]) # crea tabla Probabilidades
Prediccion <- predict (Probabilidades , Nuevos_Clientes[,-6]); # crea prediccion a datos nuevos
 
# --------------------------------------------------------------------------------
# Adiciona columna de Prediccion a la tabla Nuevos_Clientes
Nuevos_Clientes$Prediccion_de_Compra <- Prediccion   
 
# ---------------------------------------------------------------------------------
# Guarda la tabla de Nuevos_Clientes con la predicción:
write.csv(Nuevos_Clientes,"C:/Archivos/Predict_NuevosClientes.csv")


33 comentarios:

  1. Buenas,

    Tengo curiosidad en saber cúales son las diferencias frente a utilizar técnicas como la regresión logística o árboles de decisión...

    Gracias y un saludo,

    Edurne.

    ResponderEliminar
    Respuestas
    1. fijate en este articulo que describe de forma clara cada algoritmo http://rayli.net/blog/data/top-10-data-mining-algorithms-in-plain-english/

      Eliminar
    2. Muchísimas gracias Enmanuel por tu rápida respuesta y por el enlace, ya lo tengo claro!

      Edurne.

      Eliminar
  2. Hola, Gracias por el Blog ya que en multiples ocaciones me ha salvado de muchas, pero esta vez necesito colaboracion si es posible de tu parte.

    Quisiera saber si tengo algo mal en esta ejecucion.

    Datos_Historios

    Edad,     Sueldo, Estrato,  Supermercado,  Estado Civil
    25,2000,4,Jumbo,Soltero
    34,1500,3,Éxito,Casado
    54,4000,4,Jumbo,Casado
    27,300,2,La 14,Viudo
    74,300,4,Jumbo,Casado
    23,400,2,Éxito,Soltero
    40,5000,2,Éxito,Viudo

    Nuevos_Clientes

    Edad,     Sueldo, Estrato,  Supermercado,  Estado Civil
    56,1400,?,La 14,Soltero
    14,210,?,Jumbo,Casado

    Codigo

    # --------------------------------------------------------------------------------
    # Crea las tablas (ó data frame) Datos_Historicos y Nuevos_Clientes
    Datos_Historicos <- read.csv("C:/Archivos_1/Datos_Historicos.csv") # tabla de entrenamiento
    Nuevos_Clientes <- read.csv("C:/Archivos_1/Nuevos_Clientes.csv") # tabla de test

    # --------------------------------------------------------------------------------
    # Crea Probabilidades con Datos_Historicos y asigna predicción a Nuevos_Clientes
    library(e1071) # librerias de naiveBayes
    Probabilidades <- naiveBayes(Estrato ~., data=Datos_Historicos[-1]) # crea tabla Probabilidades
    Prediccion <- predict (Probabilidades , Nuevos_Clientes[,-3]); # crea prediccion a datos nuevos

    # --------------------------------------------------------------------------------
    # Adiciona columna de Prediccion a la tabla Nuevos_Clientes
    Nuevos_Clientes$Prediccion_de_Compra <- Prediccion

    # ---------------------------------------------------------------------------------
    # Guarda la tabla de Nuevos_Clientes con la predicción:
    write.csv(Nuevos_Clientes,"C:/Archivos_1/Predict_NuevosClientes.csv")

    Te agradeceria mucho la ayuda.

    ResponderEliminar
    Respuestas
    1. Hola
      Cual es el error arroja al ejecutarlo? Fijate que la variable Estrato este como Factor, y no como numero, ya que naivebayes no predice numeros (no hace regresiones) solo datos categoricos (clase).

      Eliminar
  3. Muchas gracias este articulo me ayudo en mucho, solo que tengo una duda con respecto a esta linea de código: (Compra ~., data=Datos_Historicos[-1]), ¿Por que se le pone? ~. después de Compra y por que se le pone [-1]

    ResponderEliminar
  4. hola Rita
    El simbolo de quivalencia o tilde seguido de un punto (~.) indica que la variable Compra está definida por todas variables de la tabla Datos_Historicos.

    El parametro [-1] indica no usar la primera variable de la tabla Datos_Historicos (es decir la variable IdCliente) ya que no es una variable predictora, sino el identificador de cada caso.

    ResponderEliminar
  5. Justo lo que estabo buscando: un ejemplo practico y simple para entender el algoritmo. Genial! Muchas gracias Enmanuel!

    ResponderEliminar
  6. Sabes depronto como aplicarlo pero a una descripción de texto, necesito hacer clasificador de tecto.

    ResponderEliminar
    Respuestas
    1. para esto antes tienes que hacer preprocesamiento de los datos. fijate en esta discusión donde mencionan varias librerias y links: https://www.linkedin.com/groups/3984607

      la libreriamas usada es tm, te dejo link:
      https://cran.r-project.org/web/packages/tm/vignettes/tm.pdf

      si necesitas ayuda en el desarrollo de un clasificador, me escribes a mi corre de gmail: enmanuel.s

      suerte!


      Eliminar
    2. Buenas tardes,

      ya le he escrito al correo exponiendole mi caso, mil gracias por el interes prestado.

      Saludos!

      Eliminar
  7. Hola,
    Al ejecutar la línea

    Prediccion <- predict (Probabilidades , Nuevos_Clientes[,-6]) # crea prediccion a datos nuevos

    Me da el siguiente warning:

    Warning messages:
    1: In data.matrix(newdata) : NAs introduced by coercion
    2: In data.matrix(newdata) : NAs introduced by coercion
    3: In data.matrix(newdata) : NAs introduced by coercion
    4: In data.matrix(newdata) : NAs introduced by coercion

    ¿Por qué me lo rellena todo con NA?

    PD: He puesto os mismos datos que tu en el excel de Datos_Historicos.

    Gracias!

    ResponderEliminar
    Respuestas
    1. hola Patricia
      Al reproducir el ejemplo con los datos del link, no me arroja los NAs. Asegurate que todos los campos esten como factor, tanto en datos_historicos como en nuevos_clientes.

      espero te sirva

      surte

      Eliminar
  8. Hola, esta ha sido la mejor web donde he encontrado info mas clara del Entrenamiento con Naive Bayes ... pero existe algun modo alterno >>>library(e1071) # librerias de naiveBayes <<< por ejemplo , el procedimiento manual? , lo que quiero decir, es no utilizar librerias.
    Gracias de antemano.

    ResponderEliminar
    Respuestas
    1. Fijate en este link que tiene mismo ejemplo con script de qlikview:
      http://qlikviewapuntes.blogspot.com.ar/2014/08/predecir-clientes-con-bayes-ingenuo.html

      Eliminar
  9. Hola,
    Una pregunta, cómo podría obtener la probabilidad de compra de cada cliente, en vez de tener la predicción Sí o No.
    Gracias
    Marielena

    ResponderEliminar
    Respuestas
    1. Me respondo:
      Agregando type="raw"
      predict(modelo_bayes,conjunto_prueba_test, type="raw" )

      Eliminar
    2. Buen dia, estoy intentando correr Bayes en un modelo y quiero ver la probabiidad de la clase pero cuando corro el modelo con el type = "raw" me arroja un error. Como lo puedo hacer? Dejo codigo breve
      > results <- predict(object = NB, newdata = Validacion, type = "raw")
      > mc <- table(results,Validacion$Ganador)
      Error in table(results, Validacion$Ganador) :
      all arguments must have the same length
      > mc

      Gracias!

      Eliminar
  10. saludos, primero felicitarlo por este buen post. segundo me gustaria saber si a este modelo puedo agregarle cross valitadion, y mas o menos como se haria. muchas gracias.

    ResponderEliminar
    Respuestas
    1. hola Carlos
      Para validacion cruzada, fijate en este link, solo tendrias que cambiar la parte del modelado.
      http://apuntes-r.blogspot.com.ar/2014/11/validacion-cruzada.html

      Espero te sirva
      Suerte!

      Eliminar
  11. Muchas gracias le quedó muy agradecido por su pronta respuesta, voy a revisar y espero me pueda servir para lo que necesitó. Gracias.

    ResponderEliminar
  12. Hola no se puede descarga el set de datos

    ResponderEliminar
  13. Hola, excelente post, me gustaría saber que tan recomendable seria el naive para muestras muy pequeñas?

    ResponderEliminar
  14. Hola emanuel: muy buen blog... tengo una problemática por si pudieras orientarme:

    Tengo una tabla que contiene una cadena de caracteres, un identificador de cliente y un codigo que puede indicar una pista de que tipo de producto puede ser por. 1= refrigerador o lavadora, 2=estufa o tv o etc....
    en la cadena de caracteres viene una descripción de lo que podría ser pero puede estar escrito de diferentes formas por ej. podría decir televisor o TV dentro del texto.

    Entonces lo que necesito predecir es que producto es en función del identificador, el código y las palabras que vienen escritas en el texto.

    Gracias

    CS

    ResponderEliminar
  15. Hola emanuel: muy buen blog... tengo una problemática por si pudieras orientarme:

    Tengo una tabla que contiene una cadena de caracteres, un identificador de cliente y un codigo que puede indicar una pista de que tipo de producto puede ser por. 1= refrigerador o lavadora, 2=estufa o tv o etc....
    en la cadena de caracteres viene una descripción de lo que podría ser pero puede estar escrito de diferentes formas por ej. podría decir televisor o TV dentro del texto.

    Entonces lo que necesito predecir es que producto es en función del identificador, el código y las palabras que vienen escritas en el texto.

    Gracias

    CS

    ResponderEliminar
    Respuestas
    1. Hola Carlos
      Tendrías que aplicar algunas técnicas de "text mining" para crear "feature" relevantes y luego entrenar un clasificador. Fijate en esta nota donde hay algunas de estas técnicas. Si se te complica, enviame un ejemplo del dataset por mail y le doy una mirada.

      Eliminar
    2. https://apuntes-r.blogspot.com.ar/2016/11/text-mining-con-twiter.html

      Eliminar
  16. Gracias Emanuel!! Revisaré el material y te comento..

    ResponderEliminar
  17. Hola! como puedo aplicar la curva ROC a esto?

    ResponderEliminar
  18. Buen dia, estoy intentando correr Bayes en un modelo y quiero ver la probabiidad de la clase pero cuando corro el modelo con el type = "raw" me arroja un error. Como lo puedo hacer? Dejo codigo breve
    > results <- predict(object = NB, newdata = Validacion, type = "raw")
    > mc <- table(results,Validacion$Ganador)
    Error in table(results, Validacion$Ganador) :
    all arguments must have the same length
    > mc

    ResponderEliminar
  19. Buenas Tardes Emmanuel, muchas gracias por compartir tu conocimiento. Pero tengo problema, al ejecutar la linea de comando que crea una nueva predicción, me arroja la siguiente:

    > Nuevos_Clientes$Prediccion_de_Compra <- Prediccion
    Error in `$<-.data.frame`(`*tmp*`, Prediccion_de_Compra, value = integer(0)) :
    replacement has 0 rows, data has 3

    Estoy usando los mismos archivos que se pueden descargar. Por favor agradecería tu ayuda

    ResponderEliminar