Naive Bayes, o cómo las matemáticas te permiten filtrar el spam

Hola En este artículo hablaré sobre el clasificador bayesiano como una de las opciones para filtrar correos electrónicos no deseados. Repasemos la teoría, luego la arreglemos con la práctica, y al final daré mi boceto del código en mi querido idioma R. Trataré de exponer lo más levemente posible con expresiones y formulaciones. ¡Empecemos!

imagen

No hay fórmulas en ningún lado, bueno, una breve teoría


El clasificador bayesiano pertenece a la categoría de aprendizaje automático. La conclusión es esta: el sistema que se enfrenta a la tarea de determinar si la siguiente letra es spam ha sido entrenado previamente por un cierto número de letras que saben exactamente dónde "spam" y dónde "no spam". Ya ha quedado claro que esto es enseñar con un maestro, donde desempeñamos el papel de un maestro. El clasificador bayesiano presenta un documento (en nuestro caso, una letra) en forma de un conjunto de palabras que supuestamente no dependen entre sí (y esta ingenuidad se deduce de aquí).

Es necesario calcular la calificación para cada clase (spam / no spam) y elegir la que sea máxima. Para hacer esto, use la siguiente fórmula:

arg max[P(Qk) prodi=1nP(xi|Qk)]


P(Qk)= cfrac textnúmerodedocumentosdelaclase$Qk$ textnúmerototaldedocumentos
P(xi|Qk)= cfrac alpha+Nik alphaM+Nk- palabra ocurrencia xien el documento de clase Qk(con suavizado) *
Nk- el número de palabras incluidas en el documento de clase Qk
M - el número de palabras del conjunto de entrenamiento
Nik- el número de ocurrencias de la palabra xien el documento de clase Qk
 alpha- parámetro para alisar

Cuando el volumen del texto es muy grande, debe trabajar con números muy pequeños. Para evitar esto, puede convertir la fórmula de acuerdo con la propiedad logaritmo **:

 logab= loga+ logb


Sustituir y obtener:

arg max[ logP(Qk)+ sumi=1n logP(xi|Qk)]


* Durante los cálculos, puede encontrar una palabra que no estaba en la etapa de capacitación del sistema. Esto puede llevar a que la evaluación sea igual a cero y el documento no puede asignarse a ninguna de las categorías (spam / no spam). No importa cómo lo desee, no le enseña a su sistema todas las palabras posibles. Para hacer esto, es necesario aplicar suavizado, o más bien, hacer pequeñas correcciones a todas las probabilidades de que las palabras ingresen al documento. Se selecciona el parámetro 0 <α≤1 (si α = 1, este es el suavizado de Laplace)

** El logaritmo es una función monotónicamente creciente. Como se puede ver en la primera fórmula, estamos buscando el máximo. El logaritmo de la función alcanzará su punto máximo en el mismo punto (abscisa) que la función misma. Esto simplifica el cálculo, porque solo cambia el valor numérico.

De la teoría a la práctica.


Deje que nuestro sistema aprenda de las siguientes letras, conocidas de antemano dónde “spam” y dónde “no spam” (muestra de capacitación):

Spam

  • “Vales a bajo precio”
  • "Promoción! Compre una barra de chocolate y obtenga un teléfono como regalo »

No es spam:

  • “La reunión se realizará mañana”
  • "Compre un kilogramo de manzanas y una barra de chocolate"

Asignación: determine a qué categoría pertenece la siguiente letra:

  • “La tienda tiene una montaña de manzanas. Compre siete kilogramos y una barra de chocolate ”

Solución:

Hacemos una mesa. Eliminamos todas las "palabras de detención", calculamos las probabilidades, tomamos el parámetro para suavizar como uno.

imagen

Valoración para la categoría Spam:

 frac24 cdot frac223 cdot frac223 cdot frac123 cdot frac123 cdot frac123 cdot frac123 cdot frac123 aprox0,000000000587( texto5.87E10)


Clasificación para la categoría "No spam":

 frac24 cdot frac221 cdot frac221 cdot frac221 cdot frac221 cdot frac121 cdot frac121 cdot frac121 aprox0,00000000444( texto4.44E9)


Respuesta: La calificación de "No es spam" es más que la calificación de "Spam". ¡Entonces la carta de verificación no es spam!

Calculamos lo mismo con la ayuda de una función transformada por la propiedad del logaritmo:
Valoración para la categoría Spam:

 log frac24+ log frac223+ log frac223+ log frac123+ log frac123+ log frac123+ log frac123+ log frac123 aprox$21.2


Clasificación para la categoría "No spam":

 log frac24+ log frac221+ log frac221+ log frac221+ log frac221+ log frac121+ log frac121+ log frac121 aprox$19.2


Respuesta: similar a la respuesta anterior. Correo electrónico de verificación: ¡sin spam!

Implementación del lenguaje de programación R


Comentó sobre casi todas las acciones, porque sé con qué frecuencia no quiero entender el código de otra persona, así que espero que leer el mío no te cause ninguna dificultad. (oh como espero)

Y aquí, de hecho, el código mismo
library("tm") #  stopwords library("stringr") #     #    : spam <- c( '   ', '!       ' ) #     : not_spam <- c( '  ', '    ' ) #   test_letter <- "   .     " #---------------- -------------------- #    spam <- str_replace_all(spam, "[[:punct:]]", "") #    spam <- tolower(spam) #    spam_words <- unlist(strsplit(spam, " ")) # ,      stopwords spam_words <- spam_words[! spam_words %in% stopwords("ru")] #        unique_words <- table(spam_words) # data frame main_table <- data.frame(u_words=unique_words) #  names(main_table) <- c("","") #---------------  ------------------ not_spam <- str_replace_all(not_spam, "[[:punct:]]", "") not_spam <- tolower(not_spam) not_spam_words <- unlist(strsplit(not_spam, " ")) not_spam_words <- not_spam_words[! not_spam_words %in% stopwords("ru")] #--------------- ------------------ test_letter <- str_replace_all(test_letter, "[[:punct:]]", "") test_letter <- tolower(test_letter) test_letter <- unlist(strsplit(test_letter, " ")) test_letter <- test_letter[! test_letter %in% stopwords("ru")] #--------------------------------------------- #        main_table$_ <- 0 for(i in 1:length(not_spam_words)){ #   need_word <- TRUE for(j in 1:(nrow(main_table))){ # " "  ,      +1 if(not_spam_words[i]==main_table[j,1]) { main_table$_[j] <- main_table$_[j]+1 need_word <- FALSE } } #    ,      data frame    if(need_word==TRUE) { main_table <- rbind(main_table,data.frame(=not_spam_words[i],=0,_=1)) } } #------------- #    ,    -  main_table$_ <- NA #    ,    -   main_table$__ <- NA #------------- #      Xi    Qk formula_1 <- function(N_ik,M,N_k) { (1+N_ik)/(M+N_k) } #------------- #      quantity <- nrow(main_table) for(i in 1:length(test_letter)) { #    ,     need_word <- TRUE for(j in 1:nrow(main_table)) { #               if(test_letter[i]==main_table$[j]) { main_table$_[j] <- formula_1(main_table$[j],quantity,sum(main_table$)) main_table$__[j] <- formula_1(main_table$_[j],quantity,sum(main_table$_)) need_word <- FALSE } } #  ,      data frame,    /  if(need_word==TRUE) { main_table <- rbind(main_table,data.frame(=test_letter[i],=0,_=0,_=NA,__=NA)) main_table$_[nrow(main_table)] <- formula_1(main_table$[nrow(main_table)],quantity,sum(main_table$)) main_table$__[nrow(main_table)] <- formula_1(main_table$_[nrow(main_table)],quantity,sum(main_table$_)) } } #     "" probability_spam <- 1 #     " " probability_not_spam <- 1 for(i in 1:nrow(main_table)) { if(!is.na(main_table$_[i])) { # 1.1   ,   -  probability_spam <- probability_spam * main_table$_[i] } if(!is.na(main_table$__[i])) { # 1.2   ,   -   probability_not_spam <- probability_not_spam * main_table$__[i] } } # 2.1   ,   -  probability_spam <- (length(spam)/(length(spam)+length(not_spam)))*probability_spam # 2.2   ,   -   probability_not_spam <- (length(not_spam)/(length(spam)+length(not_spam)))*probability_not_spam #   -    ifelse(probability_spam>probability_not_spam,"  - !","  -  !") 


Muchas gracias por tu tiempo leyendo mi artículo. Espero que hayas aprendido algo nuevo para ti, o simplemente arrojes luz sobre momentos que no te quedan claros. Buena suerte

Fuentes:
  1. Un muy buen artículo sobre el ingenuo clasificador de Bayes
  2. Conocimiento derivado del Wiki: aquí , aquí y aquí
  3. Conferencias sobre minería de datos Chubukova I.A.

Source: https://habr.com/ru/post/es415963/


All Articles