Mejor Filtrado Bayesiano

Enero de 2003

(Este artículo fue presentado como una charla en la Conferencia sobre Spam de 2003. Describe el trabajo que he realizado para mejorar el rendimiento del algoritmo descrito en Un Plan contra el Spam, y lo que planeo hacer en el futuro.)

El primer descubrimiento que me gustaría presentar aquí es un algoritmo para la evaluación perezosa de artículos de investigación. Simplemente escribe lo que quieras y no cites ningún trabajo anterior, y los lectores indignados te enviarán referencias a todos los artículos que deberías haber citado. Descubrí este algoritmo después de que "Un Plan contra el Spam" [1] estuviera en Slashdot.

El filtrado de spam es un subconjunto de la clasificación de texto, que es un campo bien establecido, pero los primeros artículos sobre filtrado bayesiano de spam per se parecen haber sido dos presentados en la misma conferencia en 1998, uno por Pantel y Lin [2], y otro por un grupo de Microsoft Research [3].

Cuando me enteré de este trabajo, me sorprendió un poco. Si la gente había estado al tanto del filtrado bayesiano hace cuatro años, ¿por qué no lo usaba todo el mundo? Cuando leí los artículos, me di cuenta de por qué. El filtro de Pantel y Lin era el más efectivo de los dos, pero solo atrapaba el 92% del spam, con un 1.16% de falsos positivos.

Cuando intenté escribir un filtro de spam bayesiano, atrapó el 99.5% del spam con menos del 0.03% de falsos positivos [4]. Siempre es alarmante cuando dos personas que intentan el mismo experimento obtienen resultados muy divergentes. Es especialmente alarmante aquí porque esos dos conjuntos de números podrían arrojar conclusiones opuestas. Los diferentes usuarios tienen diferentes requisitos, pero creo que para muchas personas una tasa de filtrado del 92% con un 1.16% de falsos positivos significa que el filtrado no es una solución aceptable, mientras que el 99.5% con menos del 0.03% de falsos positivos significa que sí lo es.

Entonces, ¿por qué obtuvimos números tan diferentes? No he intentado reproducir los resultados de Pantel y Lin, pero al leer el artículo veo cinco cosas que probablemente explican la diferencia.

Una es simplemente que entrenaron su filtro con muy pocos datos: 160 correos de spam y 466 correos legítimos. El rendimiento del filtro debería seguir aumentando con conjuntos de datos tan pequeños. Por lo tanto, sus números pueden no ser una medida precisa del rendimiento de su algoritmo, y mucho menos del filtrado bayesiano de spam en general.

Pero creo que la diferencia más importante es probablemente que ignoraron las cabeceras de los mensajes. Para cualquiera que haya trabajado en filtros de spam, esto parecerá una decisión perversa. Y sin embargo, en los primeros filtros que intenté escribir, también ignoré las cabeceras. ¿Por qué? Porque quería mantener el problema ordenado. No sabía mucho sobre las cabeceras de correo en ese entonces, y me parecían llenas de cosas aleatorias. Hay una lección aquí para los escritores de filtros: no ignoren los datos. Uno pensaría que esta lección sería demasiado obvia para mencionarla, pero he tenido que aprenderla varias veces.

Tercero, Pantel y Lin aplicaron stemming a los tokens, lo que significa que redujeron, por ejemplo, tanto "mailing" como "mailed" a la raíz "mail". Puede que sintieran que estaban obligados a hacer esto por el pequeño tamaño de su corpus, pero si es así, esto es una especie de optimización prematura.

Cuarto, calcularon las probabilidades de manera diferente. Usaron todos los tokens, mientras que yo solo uso los 15 más significativos. Si usas todos los tokens, tenderás a perderte los spams más largos, del tipo en que alguien te cuenta su historia de vida hasta el punto en que se hizo rico con algún esquema de marketing multinivel. Y un algoritmo así sería fácil de falsificar para los spammers: simplemente agrega un gran bloque de texto aleatorio para contrarrestar los términos de spam.

Finalmente, no introdujeron un sesgo contra los falsos positivos. Creo que cualquier algoritmo de filtrado de spam debería tener una perilla conveniente que puedas girar para disminuir la tasa de falsos positivos a expensas de la tasa de filtrado. Yo hago esto contando las ocurrencias de tokens en el corpus de correos legítimos el doble.

No creo que sea una buena idea tratar el filtrado de spam como un problema de clasificación de texto directo. Puedes usar técnicas de clasificación de texto, pero las soluciones pueden y deben reflejar el hecho de que el texto es correo electrónico, y el spam en particular. El correo electrónico no es solo texto; tiene estructura. El filtrado de spam no es solo clasificación, porque los falsos positivos son mucho peores que los falsos negativos, por lo que deberías tratarlos como un tipo de error diferente. Y la fuente del error no es solo la variación aleatoria, sino un spammer humano activo que trabaja para derrotar tu filtro.

Tokens

Otro proyecto del que oí hablar después del artículo de Slashdot fue el CRM114 [5] de Bill Yerazunis. Este es el contraejemplo del principio de diseño que acabo de mencionar. Es un clasificador de texto directo, pero tan asombrosamente efectivo que logra filtrar el spam casi perfectamente sin siquiera saber lo que está haciendo.

Una vez que entendí cómo funcionaba CRM114, parecía inevitable que eventualmente tendría que pasar de filtrar basándome en palabras individuales a un enfoque como este. Pero primero, pensé, veré hasta dónde puedo llegar con palabras individuales. Y la respuesta es, sorprendentemente lejos.

Principalmente he estado trabajando en una tokenización más inteligente. En el spam actual, he podido lograr tasas de filtrado que se acercan a las de CRM114. Estas técnicas son en su mayoría ortogonales a las de Bill; una solución óptima podría incorporar ambas.

"Un Plan contra el Spam" utiliza una definición muy simple de token. Las letras, los dígitos, los guiones, los apóstrofes y los signos de dólar son caracteres constituyentes, y todo lo demás es un separador de tokens. También ignoré las mayúsculas y minúsculas.

Ahora tengo una definición más complicada de token:

  1. Se conservan las mayúsculas y minúsculas.

  2. Los signos de exclamación son caracteres constituyentes.

  3. Los puntos y las comas son constituyentes si aparecen entre dos dígitos. Esto me permite obtener direcciones IP y precios intactos.

  4. Un rango de precios como $20-25 produce dos tokens, $20 y $25.

  5. Los tokens que ocurren dentro de las líneas To, From, Subject y Return-Path, o dentro de las URLs, se marcan en consecuencia. Por ejemplo, "foo" en la línea Subject se convierte en "Subject*foo". (El asterisco podría ser cualquier carácter que no permitas como constituyente.)

Tales medidas aumentan el vocabulario del filtro, lo que lo hace más discriminatorio. Por ejemplo, en el filtro actual, "free" en la línea Subject tiene una probabilidad de spam del 98%, mientras que el mismo token en el cuerpo tiene una probabilidad de spam de solo el 65%.

Aquí están algunas de las probabilidades actuales [6]:

SubjectFREE 0.9999 free!! 0.9999 Tofree 0.9998 Subjectfree 0.9782 free! 0.9199 Free 0.9198 Urlfree 0.9091 FREE 0.8747 From*free 0.7636 free 0.6546

En el filtro de "Un Plan contra el Spam", todos estos tokens habrían tenido la misma probabilidad, .7602. Ese filtro reconocía alrededor de 23,000 tokens. El actual reconoce alrededor de 187,000.

La desventaja de tener un universo de tokens más grande es que hay más posibilidades de fallos. Repartir tu corpus en más tokens tiene el mismo efecto que hacerlo más pequeño. Si consideras los signos de exclamación como constituyentes, por ejemplo, entonces podrías terminar sin tener una probabilidad de spam para "free" con siete signos de exclamación, ¡aunque sepas que "free" con solo dos signos de exclamación tiene una probabilidad del 99.99%!

Una solución a esto es lo que llamo degeneración. Si no puedes encontrar una coincidencia exacta para un token, trátalo como si fuera una versión menos específica. Considero que los signos de exclamación terminales, las letras mayúsculas y el hecho de ocurrir en uno de los cinco contextos marcados hacen que un token sea más específico. Por ejemplo, si no encuentro una probabilidad para "Subjectfree!", busco las probabilidades para "Subjectfree", "free!", y "free", y tomo la que esté más lejos de .5.

Aquí están las alternativas [7] que se consideran si el filtro ve "FREE!!!" en la línea Subject y no tiene una probabilidad para ello.

SubjectFree!!! Subjectfree!!! SubjectFREE! SubjectFree! Subjectfree! SubjectFREE SubjectFree Subjectfree FREE!!! Free!!! free!!! FREE! Free! free! FREE Free free

Si haces esto, asegúrate de considerar las versiones con mayúscula inicial, así como todas las mayúsculas y todas las minúsculas. Los spams tienden a tener más oraciones en modo imperativo, y en ellas la primera palabra es un verbo. Por lo tanto, los verbos con mayúscula inicial tienen probabilidades de spam más altas que si estuvieran en minúsculas. En mi filtro, la probabilidad de spam de "Act" es del 98% y para "act" solo del 62%.

Si aumentas el vocabulario de tu filtro, puedes terminar contando la misma palabra varias veces, según tu antigua definición de "misma". Lógicamente, ya no son el mismo token. Pero si esto todavía te molesta, permíteme añadir por experiencia que las palabras que parecen estar contando varias veces son exactamente las que querrías contar.

Otro efecto de un vocabulario más grande es que cuando miras un correo entrante encuentras más tokens interesantes, es decir, aquellos con probabilidades lejanas a .5. Yo uso los 15 más interesantes para decidir si un correo es spam. Pero puedes encontrarte con un problema cuando usas un número fijo como este. Si encuentras muchos tokens máximamente interesantes, el resultado puede terminar decidiéndose por cualquier factor aleatorio que determine el orden de tokens igualmente interesantes. Una forma de lidiar con esto es tratar algunos como más interesantes que otros.

Por ejemplo, el token "dalco" ocurre 3 veces en mi corpus de spam y nunca en mi corpus legítimo. El token "Url*optmails" (que significa "optmails" dentro de una url) ocurre 1223 veces. Y sin embargo, como solía calcular las probabilidades para los tokens, ambos tendrían la misma probabilidad de spam, el umbral de .99.

Eso no se siente bien. Hay argumentos teóricos para dar a estos dos tokens probabilidades sustancialmente diferentes (Pantel y Lin lo hacen), pero aún no lo he intentado. Al menos parece que si encontramos más de 15 tokens que solo ocurren en uno u otro corpus, deberíamos dar prioridad a los que ocurren mucho. Así que ahora hay dos valores umbral. Para los tokens que solo se encuentran en el corpus de spam, la probabilidad es .9999 si ocurren más de 10 veces y .9998 en caso contrario. Lo mismo en el otro extremo de la escala para los tokens que solo se encuentran en el corpus legítimo.

Puede que más adelante escale sustancialmente las probabilidades de los tokens, pero esta pequeña cantidad de escalado al menos asegura que los tokens se ordenen de la manera correcta.

Otra posibilidad sería considerar no solo 15 tokens, sino todos los tokens por encima de un cierto umbral de interés. Steven Hauser hace esto en su filtro de spam estadístico [8]. Si usas un umbral, hazlo muy alto, o los spammers podrían falsificarte empaquetando mensajes con más palabras inocentes.

Finalmente, ¿qué se debe hacer con el html? He probado toda la gama de opciones, desde ignorarlo hasta analizarlo por completo. Ignorar el html es una mala idea, porque está lleno de signos útiles de spam. Pero si lo analizas todo, tu filtro podría degenerar en un mero reconocedor de html. El enfoque más efectivo parece ser el curso intermedio, notar algunos tokens pero no otros. Me fijo en las etiquetas a, img y font, e ignoro el resto. Los enlaces e imágenes ciertamente deberías mirarlos, porque contienen urls.

Probablemente podría ser más inteligente al tratar con html, pero no creo que valga la pena dedicarle mucho tiempo. Los spams llenos de html son fáciles de filtrar. Los spammers más inteligentes ya lo evitan. Por lo tanto, el rendimiento en el futuro no debería depender mucho de cómo trates el html.

Rendimiento

Entre el 10 de diciembre de 2002 y el 10 de enero de 2003 recibí aproximadamente 1750 spams. De estos, 4 se colaron. Eso es una tasa de filtrado de aproximadamente el 99.75%.

Dos de los cuatro spams que me perdí se colaron porque casualmente usaron palabras que ocurren a menudo en mi correo legítimo.

El tercero fue uno de esos que explotan un script cgi inseguro para enviar correos a terceros. Son difíciles de filtrar basándose solo en el contenido porque las cabeceras son inocentes y tienen cuidado con las palabras que usan. Aun así, normalmente puedo atraparlos. Este se coló con una probabilidad de .88, justo por debajo del umbral de .9.

Por supuesto, mirar secuencias de múltiples tokens lo atraparía fácilmente. "Abajo está el resultado de tu formulario de comentarios" es una entrega instantánea.

El cuarto spam fue lo que llamo un spam del futuro, porque esto es en lo que espero que evolucione el spam: texto completamente neutral seguido de una url. En este caso, fue de alguien que decía que finalmente había terminado su página de inicio y que si podía ir a verla. (La página era, por supuesto, un anuncio de un sitio pornográfico.)

Si los spammers tienen cuidado con las cabeceras y usan una url nueva, no hay nada en el spam del futuro para que los filtros lo noten. Podemos contrarrestar, por supuesto, enviando un rastreador para ver la página. Pero eso podría no ser necesario. La tasa de respuesta para el spam del futuro debe ser baja, o todos lo estarían haciendo. Si es lo suficientemente baja, no valdrá la pena que los spammers lo envíen, y no tendremos que trabajar demasiado en filtrarlo.

Ahora, las noticias realmente impactantes: durante ese mismo período de un mes, tuve tres falsos positivos.

En cierto modo, es un alivio tener algunos falsos positivos. Cuando escribí "Un Plan contra el Spam", no había tenido ninguno, y no sabía cómo serían. Ahora que he tenido algunos, me alivia descubrir que no son tan malos como temía. Los falsos positivos producidos por filtros estadísticos resultan ser correos que suenan mucho a spam, y estos tienden a ser los que menos te importaría perderte [9].

Dos de los falsos positivos fueron boletines informativos de empresas a las que les he comprado cosas. Nunca pedí recibirlos, así que se podría argumentar que eran spams, pero los cuento como falsos positivos porque antes no los había estado eliminando como spams. La razón por la que los filtros los atraparon fue que ambas empresas cambiaron en enero a proveedores de correo electrónico comerciales en lugar de enviar los correos desde sus propios servidores, y tanto las cabeceras como los cuerpos se volvieron mucho más spammys.

El tercer falso positivo fue malo, sin embargo. Era de alguien de Egipto y estaba escrito en mayúsculas. Esto fue un resultado directo de hacer los tokens sensibles a mayúsculas; el filtro de "Un Plan contra el Spam" no lo habría atrapado.

Es difícil decir cuál es la tasa general de falsos positivos, porque estamos en el ruido, estadísticamente. Cualquiera que haya trabajado en filtros (al menos, filtros efectivos) será consciente de este problema. Con algunos correos electrónicos es difícil decir si son spam o no, y estos son los que terminas mirando cuando ajustas los filtros realmente bien. Por ejemplo, hasta ahora el filtro ha atrapado dos correos que se enviaron a mi dirección debido a un error tipográfico, y uno que se me envió creyendo que yo era otra persona. Se podría argumentar que estos no son ni mi spam ni mi correo legítimo.

Otro falso positivo fue de un vicepresidente de Virtumundo. Les escribí fingiendo ser un cliente, y como la respuesta volvió a través de los servidores de correo de Virtumundo, tenía las cabeceras más incriminatorias imaginables. Se podría argumentar que esto tampoco es un falso positivo real, sino una especie de efecto de incertidumbre de Heisenberg: solo lo obtuve porque estaba escribiendo sobre filtrado de spam.

Sin contar estos, he tenido un total de cinco falsos positivos hasta ahora, de aproximadamente 7740 correos legítimos, una tasa del 0.06%. Los otros dos fueron un aviso de que algo que compré estaba agotado, y un recordatorio de fiesta de Evite.

No creo que este número pueda ser de confianza, en parte porque la muestra es muy pequeña, y en parte porque creo que puedo arreglar el filtro para que no atrape algunos de estos.

Los falsos positivos me parecen un tipo de error diferente a los falsos negativos. La tasa de filtrado es una medida de rendimiento. Los falsos positivos los considero más como errores. Abordo la mejora de la tasa de filtrado como optimización, y la disminución de los falsos positivos como depuración.

Así que estos cinco falsos positivos son mi lista de errores. Por ejemplo, el correo de Egipto fue atrapado porque el texto en mayúsculas hizo que pareciera spam nigeriano para el filtro. Esto es realmente una especie de error. Al igual que con el html, que el correo esté completamente en mayúsculas es realmente conceptualmente una característica, no una por cada palabra. Necesito manejar las mayúsculas y minúsculas de una manera más sofisticada.

Entonces, ¿qué hacer con este 0.06%? No mucho, creo. Podrías tratarlo como un límite superior, teniendo en cuenta el pequeño tamaño de la muestra. Pero en esta etapa es más una medida de los errores en mi implementación que una tasa intrínseca de falsos positivos del filtrado bayesiano.

Futuro

¿Qué sigue? El filtrado es un problema de optimización, y la clave de la optimización es el perfilado. No intentes adivinar dónde tu código es lento, porque adivinarás mal. Mira dónde tu código es lento y arréglalo. En filtrado, esto se traduce en: mira los spams que te pierdes y averigua qué podrías haber hecho para atraparlos.

Por ejemplo, los spammers ahora están trabajando agresivamente para evadir filtros, y una de las cosas que están haciendo es dividir y escribir mal las palabras para evitar que los filtros las reconozcan. Pero trabajar en esto no es mi primera prioridad, porque todavía no tengo problemas para atrapar estos spams [10].

Hay dos tipos de spams con los que actualmente tengo problemas. Uno es el tipo que pretende ser un correo electrónico de una mujer invitándote a chatear con ella o a ver su perfil en un sitio de citas. Estos se cuelan porque son el único tipo de oferta de ventas que puedes hacer sin usar lenguaje de ventas. Usan el mismo vocabulario que el correo electrónico normal.

El otro tipo de spams que tengo problemas para filtrar son los de empresas en, por ejemplo, Bulgaria que ofrecen servicios de programación por contrato. Estos se cuelan porque yo también soy programador, y los spams están llenos de las mismas palabras que mi correo real.

Probablemente me centraré primero en el tipo de anuncio personal. Creo que si miro más de cerca podré encontrar diferencias estadísticas entre estos y mi correo real. El estilo de escritura es ciertamente diferente, aunque puede que se necesite filtrado de múltiples palabras para captarlo. Además, noto que tienden a repetir la url, y alguien que incluya una url en un correo legítimo no haría eso [11].

Los del tipo de externalización serán difíciles de atrapar. Incluso si enviaras un rastreador al sitio, no encontrarías una prueba estadística concluyente. Quizás la única respuesta sea una lista central de dominios anunciados en spams [12]. Pero no puede haber tantos de este tipo de correo. Si los únicos spams que quedan fueran ofertas no solicitadas de servicios de programación por contrato de Bulgaria, todos podríamos pasar a trabajar en otra cosa.

¿El filtrado estadístico realmente nos llevará a ese punto? No lo sé. Ahora mismo, para mí personalmente, el spam no es un problema. Pero los spammers aún no han hecho un esfuerzo serio para falsificar filtros estadísticos. ¿Qué sucederá cuando lo hagan?

No soy optimista sobre los filtros que funcionan a nivel de red [13]. Cuando hay un obstáculo estático que vale la pena superar, los spammers son bastante eficientes para superarlo. Ya hay una empresa llamada Assurance Systems que ejecutará tu correo a través de Spamassassin y te dirá si será filtrado.

Los filtros a nivel de red no serán completamente inútiles. Pueden ser suficientes para eliminar todo el spam "opt-in", es decir, spam de empresas como Virtumundo y Equalamail que afirman que realmente están ejecutando listas opt-in. Puedes filtrar esos basándote solo en las cabeceras, sin importar lo que digan en el cuerpo. Pero cualquiera que esté dispuesto a falsificar cabeceras o usar relés abiertos, presumiblemente incluyendo la mayoría de los spammers pornográficos, debería poder pasar algún mensaje a través de los filtros a nivel de red si quieren. (De ninguna manera el mensaje que les gustaría enviar, que es algo.)

El tipo de filtros sobre los que soy optimista son aquellos que calculan probabilidades basándose en el correo de cada usuario individual. Estos pueden ser mucho más efectivos, no solo para evitar falsos positivos, sino también para filtrar: por ejemplo, encontrar la dirección de correo electrónico del destinatario codificada en base64 en cualquier parte de un mensaje es un muy buen indicador de spam.

Pero la verdadera ventaja de los filtros individuales es que todos serán diferentes. Si los filtros de todos tienen diferentes probabilidades, hará que el bucle de optimización de los spammers, lo que los programadores llamarían su ciclo de edición-compilación-prueba, sea espantosamente lento. En lugar de simplemente ajustar un spam hasta que pase una copia de algún filtro que tengan en su escritorio, tendrán que hacer un envío de prueba por cada ajuste. Sería como programar en un lenguaje sin un entorno interactivo, y no le desearía eso a nadie.

Notas

[1] Paul Graham. "Un Plan contra el Spam." Agosto de 2002. http://paulgraham.com/spam.html.

Las probabilidades en este algoritmo se calculan utilizando un caso degenerado de la Regla de Bayes. Hay dos suposiciones simplificadoras: que las probabilidades de las características (es decir, las palabras) son independientes, y que no sabemos nada sobre la probabilidad a priori de que un correo electrónico sea spam.

La primera suposición es generalizada en la clasificación de texto. Los algoritmos que la utilizan se denominan "naive bayesian".

La segunda suposición la hice porque la proporción de spam en mi correo entrante fluctuaba tanto de un día a otro (de hecho, de una hora a otra) que la relación a priori general parecía inútil como predictor. Si asumes que P(spam) y P(no spam) son ambas .5, se cancelan y puedes eliminarlas de la fórmula.

Si estuvieras haciendo filtrado bayesiano en una situación donde la proporción de spam a no spam fuera consistentemente muy alta o (especialmente) muy baja, probablemente podrías mejorar el rendimiento del filtro incorporando probabilidades a priori. Para hacerlo correctamente, tendrías que rastrear las proporciones por hora del día, porque el volumen de spam y correo legítimo tienen patrones diarios distintos.

[2] Patrick Pantel y Dekang Lin. "SpamCop-- A Spam Classification & Organization Program." Actas del Taller AAAI-98 sobre Aprendizaje para la Categorización de Texto.

[3] Mehran Sahami, Susan Dumais, David Heckerman y Eric Horvitz. "A Bayesian Approach to Filtering Junk E-Mail." Actas del Taller AAAI-98 sobre Aprendizaje para la Categorización de Texto.

[4] En ese momento tenía cero falsos positivos de aproximadamente 4.000 correos legítimos. Si el siguiente correo legítimo fuera un falso positivo, esto nos daría un 0.03%. Estas tasas de falsos positivos no son confiables, como explico más adelante. Cito un número aquí solo para enfatizar que, sea cual sea la tasa de falsos positivos, es inferior al 1.16%.

[5] Bill Yerazunis. "Sparse Binary Polynomial Hash Message Filtering and The CRM114 Discriminator." Actas de la Conferencia sobre Spam de 2003.

[6] En "Un Plan contra el Spam" usé umbrales de .99 y .01. Parece justificable usar umbrales proporcionales al tamaño de los corpus. Dado que ahora tengo del orden de 10.000 de cada tipo de correo, uso .9999 y .0001.

[7] Hay un defecto aquí que probablemente debería arreglar. Actualmente, cuando "Subjectfoo" degenera a solo "foo", lo que significa es que obtienes las estadísticas de las ocurrencias de "foo" en el cuerpo o en líneas de cabecera distintas de las que marco. Lo que debería hacer es llevar un registro de las estadísticas de "foo" en general, así como de las versiones específicas, y degenerar de "Subjectfoo" no a "foo" sino a "Anywhere*foo". Lo mismo para las mayúsculas y minúsculas: debería degenerar de mayúsculas a cualquier caso, no a minúsculas.

Probablemente sería beneficioso hacer esto también con los precios, por ejemplo, degenerar de "$129.99" a "$--9.99", "$--.99" y "$--".

También podrías degenerar de palabras a sus raíces, pero esto probablemente solo mejoraría las tasas de filtrado al principio, cuando tuvieras corpus pequeños.

[8] Steven Hauser. "Statistical Spam Filter Works for Me." http://www.sofbot.com.

[9] Los falsos positivos no son todos iguales, y deberíamos recordarlo al comparar técnicas para detener el spam. Mientras que muchos de los falsos positivos causados por filtros serán casi-spams que no te importaría perderte, los falsos positivos causados por listas negras, por ejemplo, serán solo correos de personas que eligieron el ISP equivocado. En ambos casos, atrapas correos que son casi-spams, pero para las listas negras la cercanía es física, y para los filtros es textual.

[10] Si los spammers se vuelven lo suficientemente buenos en ocultar tokens para que esto sea un problema, podemos responder simplemente eliminando espacios en blanco, puntos, comas, etc. y usando un diccionario para extraer las palabras de la secuencia resultante. Y, por supuesto, encontrar palabras de esta manera que no eran visibles en el texto original sería en sí mismo evidencia de spam.

Extraer las palabras no será trivial. Requerirá más que solo reconstruir los límites de las palabras; los spammers agregan (xHot nPorn cSite'') y omiten (P#rn'') letras. La investigación en visión puede ser útil aquí, ya que la visión humana es el límite al que se acercarán tales trucos.

[11] En general, los spams son más repetitivos que el correo electrónico normal. Quieren machacar ese mensaje. Actualmente no permito duplicados en los 15 tokens principales, porque podrías obtener un falso positivo si el remitente usa alguna palabra mala varias veces. (En mi filtro actual, "dick" tiene una probabilidad de spam de .9999, pero también es un nombre.) Parece que al menos deberíamos notar la duplicación, así que puedo intentar permitir hasta dos de cada token, como hace Brian Burton en SpamProbe.

[12] Esto es en lo que enfoques como el de Brightmail degenerarán una vez que los spammers sean empujados a usar técnicas de "mad-lib" para generar todo lo demás en el mensaje.

[13] A veces se argumenta que deberíamos trabajar en el filtrado a nivel de red, porque es más eficiente. Lo que la gente suele querer decir cuando dice esto es: actualmente filtramos a nivel de red, y no queremos empezar de cero. Pero no puedes dictar el problema para que se ajuste a tu solución.

Históricamente, los argumentos de recursos escasos han estado en el lado perdedor en los debates sobre el diseño de software. La gente solo tiende a usarlos para justificar decisiones (inacción en particular) tomadas por otras razones.

Gracias a Sarah Harlin, Trevor Blackwell y Dan Giffin por leer borradores de este artículo, y a Dan nuevamente por la mayor parte de la infraestructura sobre la que se ejecuta este filtro.

Relacionado: