El correo electrónico es una herramienta vital para la comunicación en el mundo actual; sin embargo, los correos electrónicos no deseados se han convertido en un gran desafío. Estos mensajes no solicitados de fuentes desconocidas a menudo llenan las bandejas de entrada, lo que altera la comunicación y la productividad. Este artículo investiga el uso de varias técnicas de aprendizaje automático para clasificar los correos electrónicos como "spam" o "ham" (no spam).
Se evalúan modelos de clasificación como K-Nearest Neighbors (KNN), regresión logística, máquinas de vectores de soporte (SVM) y Naïve Bayes, y se compara su eficacia en la clasificación de correos electrónicos. El rendimiento de cada modelo se evalúa en función de métricas como exactitud, precisión, recuperación y puntuación F1 para determinar qué enfoque es el más adecuado para esta tarea.
En 2023, se enviarán 347.300 millones de correos electrónicos cada día, de los cuales el 45 % del tráfico total corresponde a correos electrónicos no deseados. Estos correos electrónicos no deseados le cuestan a las empresas 20.500 millones de dólares cada año. Teniendo en cuenta esto, siempre será necesario garantizar que el correo no deseado se clasifique correctamente y no interfiera con el tráfico legítimo de correo electrónico. Esta es una forma útil de comprender el potencial y la aplicación del aprendizaje automático.
En el caso de la detección de spam, un usuario humano familiarizado con el correo electrónico puede determinar fácilmente si se trata de spam casi inmediatamente después de verlo. Como resultado, creo que este trabajo confirma que la identificación de spam es una aplicación útil para un clasificador de aprendizaje automático. Para clasificar un correo electrónico como spam o no deseado, hay muchos pasos de preprocesamiento involucrados: preparar los datos para que sean aceptables para un clasificador lineal, luego tokenizar y derivar cada línea para convertirla en una tabla TF-IDF (frecuencia de término – frecuencia inversa de documento).
Se seleccionó KNN con K=3 como modelo de referencia. También se probaron la regresión logística con regularización L1, el modelo Naïve Bayes y los modelos SVM antes de decidir el mejor modelo. Para el propósito de este proyecto, se ha utilizado un conjunto de datos de Kaggle, que tiene 2551 archivos de correo electrónico "ham" y 501 archivos de correo electrónico spam y el modelado se ha realizado utilizando el lenguaje de programación R.
El siguiente gráfico ayudará a comprender el flujo de los distintos pasos seguidos:
Pasos de preprocesamiento
Dado que se utiliza un gran volumen de datos de texto, fue necesario preprocesar los datos para limpiarlos y obtener un formato que pueda ser utilizado por los modelos de clasificación. A continuación, se explicará el proceso paso a paso que se siguió como parte del preprocesamiento de datos:
Los datos de texto deben ser aceptables para un clasificador lineal. Esto significa que el conjunto de datos debe transformarse mediante métodos de extracción de características de texto en características numéricas.
En primer lugar, cada línea del texto se convierte en un símbolo y se le asigna la siguiente forma. El proceso de derivación acorta las palabras eliminando las terminaciones flexivas. Por ejemplo, workers se convierte en worker en el siguiente ejemplo.
A continuación, los datos tokenizados se convierten en una tabla TF-IDF (frecuencia de término - frecuencia inversa de documento). TF-IDF es un enfoque de análisis de texto que establece cada n-grama de un documento en términos de su frecuencia de término-frecuencia inversa de documento. La frecuencia de término es simplemente la frecuencia de un término determinado dentro de un documento (en este caso, un correo electrónico). La frecuencia inversa de documento generalmente se establece como:
log ((Número total de documentos/Número de documentos con plazo)
Esto sirve para dar más peso a los términos significativos que a los términos muy frecuentes y, por tanto, menos importantes.
Esto produce un total de 1.130 términos en el conjunto de datos de entrenamiento.
Es importante tener en cuenta que la estrategia para utilizar TF-IDF con el conjunto de prueba será realizar únicamente el entrenamiento del modelo en el TF-IDF de entrenamiento y, luego, volver a calcular el TF-IDF con los datos completos para probar la precisión. Esto es necesario porque el TF-IDF depende de la frecuencia en todo el conjunto de datos de un término determinado y también para no incorporar los datos de prueba durante el entrenamiento.
Finalmente, solo se seleccionan los 1000 términos principales por frecuencia general de términos en el conjunto de entrenamiento.
Código para los pasos de preprocesamiento -
#tokenize word_tokens <- complete_tbl %>% unnest_tokens(word,content) #stemming word_tokens<-word_tokens %>% mutate(word_stem=SnowballC::wordStem(word)) #remove any words with numbers word_tokens <- word_tokens[-grep('^\\d+$', word_tokens$word_stem),] #remove any words with . word_tokens <- word_tokens[-grep('[.]', word_tokens$word_stem),] #remove any single character words word_tokens <- word_tokens[-grep('.\\b[az]\\b.', word_tokens$word_stem),] #remove tokens which match stop words word_tokens <- word_tokens %>% filter(!word %in% stopWords) word_tokens <- word_tokens %>% filter(!word_stem %in% stopWords) #split into training and test word_tokens_train <- word_tokens %>% filter(document %in% ind) #create tfidf for training and then a complete tfidf for testing tfidf_train<-word_tokens_train %>% count(document,word_stem,sort=TRUE) %>% bind_tf_idf(word_stem,document,n) tfidf_complete<-word_tokens %>% count(document,word_stem,sort=TRUE) %>% bind_tf_idf(word_stem,document,n)
Modelos utilizados
El modelo logra una especificidad razonable pero una sensibilidad extremadamente baja, lo que significa que muchos correos electrónicos falsos se predicen erróneamente como spam. Tenga en cuenta que en cada uno de los resultados siguientes, la clase positiva es "radioaficionado". Este es realmente el peor resultado posible para un usuario, ya que se perderían muchos correos electrónicos reales que se clasifican como spam.
Código para el modelo KNN -
##train a model library(e1071) library(caret) library(class) library(LiblineaR) ##remove document number since this is indicative of spam or ham wide_feat_train<-subset(wide_feat_train, select=-c(document)) wide_feat_test<-subset(wide_feat_test,select=-c(document)) #Base model is a knn attempt knn_pred<-knn(train=wide_feat_train,test=wide_feat_test,cl=labels_train$label,k=3) knn_results<-confusionMatrix(knn_pred,labels_test$label) knn_results knn_results$byClass["F1"] knn_results$byClass["Precision"] knn_results$byClass["Recall"]
Después de obtener malos resultados del modelo KNN, el siguiente modelo utilizado fue la regresión logística.
Para los fines de este escenario,
Se aplicó la regresión logística con los siguientes hiperparámetros:
Este modelo proporciona los siguientes resultados en el conjunto de datos de prueba, lo que ya supone una mejora significativa respecto del modelo KNN. La precisión general es bastante alta, pero la especificidad muestra que todavía hay margen de mejora. Un usuario de este modelo descubriría que algunos radioaficionados se predicen como spam.
Código para el modelo de regresión logística -
#Next is a logistic regression usin the below hyperparameters grid_logit <- expand.grid(loss="L1",cost=2,epsilon=0.1) lr <- train(x=wide_feat_train,y=labels_train$label,method="regLogistic",tuneGrid=grid_logit) lr_results<-confusionMatrix(as.factor(predict(lr,wide_feat_test)),labels_test$label) lr_results p_lr = predict(lr,wide_feat_test) prednum_lr<-ifelse(p_lr=="spam",0,1) roc_lr<-roc(labels_test$label,prednum_lr) plot(roc_lr) roc_lr$auc p1_lr<- prediction(as.numeric(p_lr),as.numeric(labels_test$label)) pr_lr <- performance(p1_lr, "prec", "rec") plot(pr_lr) lr_results$byClass["F1"] lr_results$byClass["Precision"] lr_results$byClass["Recall"]
El siguiente modelo que se probó fue el modelo Naive Bayes. Para este modelo, se realizó una validación cruzada para encontrar los hiperparámetros óptimos con un enfoque quíntuple. Esto da como resultado los siguientes parámetros para Naive-Bayes:
Este modelo también consigue buenos resultados tanto en especificidad como en sensibilidad.
Código para el modelo Naive Bayes -
##naive bayes main model nb_cv <- train( x=wide_feat_train, y=labels_train$label, method = "naive_bayes", trControl = train_control, tuneGrid = grid ) nb <- naiveBayes(wide_feat_train,labels_train$label,adjust=1,laplace=0,usekernel=FALSE) nb_results<-confusionMatrix(as.factor(predict(nb,wide_feat_test)),labels_test$label) nb_results p = predict(nb,wide_feat_test) prednum<-ifelse(p=="spam",0,1) roc_nb<-roc(labels_test$label,prednum) plot(roc_nb) roc_nb$auc p1<- prediction(as.numeric(p),as.numeric(labels_test$label)) pr <- performance(p1, "prec", "rec") plot(pr) nb_results$byClass["F1"] nb_results$byClass["Precision"] nb_results$byClass["Recall"]
4. Máquina de vectores de soporte (SVM)
El modelo final es una validación cruzada de SVM con un núcleo lineal. Las máquinas de vectores de soporte intentan encontrar de forma óptima el hiperplano de separación máxima para separar los datos entre dos clases.
Aquí se realiza un CV de 5 pasos utilizando la biblioteca R caret para identificar los hiperparámetros óptimos. Estos hiperparámetros se muestran a continuación:
Los resultados de este modelo cuando se aplica al conjunto de datos de prueba retenido se muestran a continuación:
Código para SVM -
#svm train_control <- trainControl( method = "cv", number = 5 ) svm <- train(x=wide_feat_train,y=labels_train$label,method="svmLinearWeights2",trControl=train_control) svm$bestTune svm_results<-confusionMatrix(as.factor(predict(svm,wide_feat_test)),labels_test$label) svm_results p_svm = predict(svm,wide_feat_test) prednum_svm<-ifelse(p_svm=="spam",0,1) roc_svm<-roc(labels_test$label,prednum_svm) plot(roc_svm,colorize=T,lwd=3, main=" ROC curve for SVM model") roc_svm$auc p1_svm<- prediction(as.numeric(p_svm),as.numeric(labels_test$label)) pr <- performance(p1_svm, "prec", "rec") plot(pr) svm_results$byClass["F1"] svm_results$byClass["Precision"] svm_results$byClass["Recall"]
La siguiente tabla resume las medidas que se consideraron para seleccionar el mejor modelo:
Modelo | Exactitud | Puntuación F1 | Precisión | Recordar |
---|---|---|---|---|
KNN | 0,252 | 0,2293 | 0,8947 | 0,1315 |
Regresión logística | 0,9624 | 0,9781 | 0,9591 | 0,998 |
Bayes ingenuo | 0,9722 | 0,9834 | 0,9882 | 0,9787 |
SVM | 0,9885 | 0,9932 | 0,9886 | 1 |
De la tabla anterior se puede ver que SVM tiene el mejor rendimiento en comparación con los otros modelos.
Para confirmar aún más, se trazaron curvas ROC y se calcularon los valores de AUC.
Modelo | KNN | Regresión logística | Bayes ingenuo | SVM |
---|---|---|---|---|
AUC | .5232 | .882 | .9574 | .9628 |
Fig.: Valores AUC para los 4 modelos
A partir de las métricas anteriores, se puede concluir que el SVM con validación cruzada de 5 pasos tiene el mejor rendimiento en el conjunto de datos al clasificar los correos electrónicos como spam y correo no deseado.
El filtrado de spam siempre será un campo en continua evolución, ya que los spammers encuentran constantemente métodos nuevos e innovadores para enviar mensajes de spam. Es posible que ninguna solución antispam sea la correcta. En este proyecto, se utilizaron algunas de las herramientas de aprendizaje automático para ver cómo funcionan como clasificadores de correos electrónicos de spam y de correo no deseado. Se presentan descripciones de los cálculos, así como una comparación de sus rendimientos.
De los cuatro modelos de aprendizaje automático que se han probado, se ha comprobado que SVM es el mejor en términos de rendimiento. Los modelos de regresión logística y Naïve Bayes también muestran resultados prometedores.