Better Bayesian Filtering

Оригинал

Январь 2003

(Эта статья была представлена в качестве доклада на конференции по спаму 2003 года. В ней описывается работа, которую я проделал для улучшения производительности алгоритма, описанного в "A Plan for Spam", и то, что я планирую сделать в будущем).

Первое открытие, которое я хотел бы представить здесь, - это алгоритм для ленивой оценки научных статей. Просто напишите все, что хотите, и не ссылайтесь на предыдущие работы, и возмущенные читатели пришлют вам ссылки на все работы, на которые вы должны были ссылаться. Я обнаружил этот алгоритм после того, как на Slashdot появился "A Plan for Spam" [1].

Фильтрация спама - это подмножество классификации текстов, которая является хорошо разработанной областью, но первыми работами о байесовской фильтрации спама как таковой, похоже, были две, представленные на одной конференции в 1998 году, одна Пантелом и Лином [2], а другая - группой из Microsoft Research [3].

Когда я услышал об этой работе, я был немного удивлен. Если люди познакомились с байесовской фильтрацией четыре года назад, почему все еще не используют ее? Когда я прочитал статьи, я понял, почему. Фильтр Пантела и Лина был более эффективным из двух, но он отлавливал только 92% спама с 1,16% ложных срабатываний.

Когда я попробовал написать байесовский фильтр спама, он поймал 99,5% спама при менее чем .03% ложных срабатываний [4]. Всегда тревожно, когда два человека, проводящие один и тот же эксперимент, получают сильно расходящиеся результаты. В данном случае это особенно тревожно, потому что эти два набора цифр могут привести к противоположным выводам. У разных пользователей разные требования, но я думаю, что для многих людей показатель фильтрации в 92% при 1,16% ложных срабатываний означает, что фильтрация не является приемлемым решением, в то время как 99,5% при менее чем .03% ложных срабатываний означает, что она является таковым.

Почему же мы получили такие разные цифры? Я не пытался воспроизвести результаты Пантеля и Лина, но, читая статью, я вижу пять моментов, которые, вероятно, объясняют разницу.

Первая заключается в том, что они обучали свой фильтр на очень небольшом количестве данных: 160 спамовых и 466 не спамовых писем. Производительность фильтра все равно должна расти при таких маленьких наборах данных. Так что их цифры могут даже не быть точным показателем эффективности их алгоритма, не говоря уже о байесовской фильтрации спама в целом.

Но я думаю, что самое важное отличие, вероятно, заключается в том, что они игнорировали заголовки сообщений. Всем, кто работал над спам-фильтрами, это покажется извращенным решением. И все же в самых первых фильтрах, которые я пробовал писать, я тоже игнорировал заголовки. Почему? Потому что я хотел, чтобы проблема была решена аккуратно. Тогда я мало что знал о почтовых заголовках, и они казались мне полными случайных вещей. Здесь есть урок для авторов фильтров: не игнорируйте данные. Казалось бы, этот урок слишком очевиден, чтобы о нем упоминать, но мне приходилось учить его несколько раз.

В-третьих, Пантел и Лин сократили лексемы, то есть, например, "mailing" и "mail" до корня "mail". Возможно, они посчитали, что их вынуждает сделать это небольшой размер корпуса, но если это так, то это своего рода преждевременная оптимизация.

В-четвертых, они по-другому рассчитывали вероятности. Они использовали все лексемы, в то время как я использую только 15 наиболее значимых. Если вы используете все маркеры, вы будете склонны пропускать более длинные спамы, такие, где кто-то рассказывает вам историю своей жизни вплоть до того момента, когда он разбогател на какой-то многоуровневой маркетинговой схеме. И такой алгоритм спамерам было бы легко подделать: просто добавьте большой кусок случайного текста, чтобы уравновесить спамные термины.

И, наконец, они не учитывали ложные срабатывания. Я считаю, что любой алгоритм фильтрации спама должен иметь удобную ручку, которую можно крутить, чтобы снизить процент ложных срабатываний за счет скорости фильтрации. Я делаю это, подсчитывая количество повторных вхождений лексем в корпус не-спама.

Я не думаю, что это хорошая идея - рассматривать фильтрацию спама как проблему классификации текста. Можно использовать методы классификации текста, но решения могут и должны отражать тот факт, что текст - это электронная почта, и спам в частности. Электронная почта - это не просто текст; она имеет структуру. Фильтрация спама - это не просто классификация, поскольку ложные срабатывания настолько хуже, чем ложные отрицания, что их следует рассматривать как другой вид ошибок. И источником ошибки является не просто случайная вариация, а живой человек-спамер, активно работающий над тем, чтобы победить ваш фильтр.

Токены

Еще один проект, о котором я узнал после статьи на Slashdot, - CRM114 Билла Йеразуниса [5]. Это контрпример принципа проектирования, о котором я только что говорил. Это прямой классификатор текста, но настолько потрясающе эффективный, что ему удается почти идеально фильтровать спам, даже не подозревая, что он это делает.

Когда я понял, как работает CRM114, казалось неизбежным, что со временем мне придется перейти от фильтрации на основе отдельных слов к подобному подходу. Но сначала, подумал я, посмотрю, как далеко я смогу зайти с помощью отдельных слов. И ответ: на удивление далеко.

В основном я работал над более умной токенизацией. На текущем спаме я смог добиться скорости фильтрации, приближающейся к скорости CRM114. Эти методы в основном ортогональны методам Билла; оптимальное решение может включать оба.

В "A Plan for Spam" используется очень простое определение маркера. Буквы, цифры, тире, апострофы и знаки доллара являются составляющими символами, а все остальное - разделителями токенов. Я также игнорировал регистр.

Теперь у меня есть более сложное определение токена:

Такие меры увеличивают словарный запас фильтра, что делает его более разборчивым. Например, в текущем фильтре "бесплатно" в строке темы имеет вероятность спама 98%, в то время как та же лексема в теле письма имеет вероятность спама только 65%.

Вот некоторые из текущих вероятностей [6]:

			Предмет*БЕСПЛАТНО 0.9999
			бесплатно!!! 0.9999
			К*бесплатно 0.9998
			Предмет*бесплатно 0.9782
			бесплатно! 0.9199
			Бесплатно 0.9198
			Url*бесплатно 0.9091
			БЕСПЛАТНО 0.8747
			от*бесплатно 0.7636
			бесплатно 0.6546
			

В фильтре Plan for Spam все эти лексемы имели бы одинаковую вероятность - .7602. Тот фильтр распознал около 23 000 лексем. Нынешний фильтр распознает около 187 000.

Недостатком большего количества лексем является большая вероятность промахов. Распределение корпуса по большему количеству лексем имеет тот же эффект, что и уменьшение его размера. Если вы, например, рассматриваете восклицательные знаки как составляющие, то в итоге у вас может не оказаться вероятности спама для free с семью восклицательными знаками, даже если вы знаете, что free с двумя восклицательными знаками имеет вероятность 99,99%.

Одним из решений этой проблемы является то, что я называю дегенерацией. Если вы не можете найти точное соответствие для маркера, обращайтесь с ним так, как будто это менее конкретная версия. Я считаю, что восклицательные знаки, заглавные буквы и встречаемость в одном из пяти отмеченных контекстов делают лексему более специфичной. Например, если я не нахожу вероятность для "Subject*free!", я ищу вероятности для "Subject*free", "free!" и "free", и беру ту, которая дальше всего от .5.

Вот альтернативные варианты [7], рассматриваемые, если фильтр видит "FREE!!!" в строке Subject и не имеет для него вероятности.

			Предмет*Бесплатно!!!
			Предмет*бесплатно!!!
			Предмет*БЕСПЛАТНО!
			Предмет*Бесплатно!
			Предмет*бесплатно!
			Предмет*БЕСПЛАТНО
			Предмет*Бесплатно
			Предмет*бесплатно
			БЕСПЛАТНО!!!
			Бесплатно!!!
			бесплатно!!!
			БЕСПЛАТНО!
			Бесплатно!
			бесплатно!
			БЕСПЛАТНО
			Бесплатно
			бесплатно         
			

Если вы это сделаете, обязательно рассмотрите варианты с начальными заглавными буквами, а также со всеми прописными и всеми строчными. В спаме больше предложений в повелительном наклонении, а в них первое слово - глагол. Поэтому глаголы с прописными буквами имеют более высокую вероятность спама, чем глаголы со строчными буквами. В моем фильтре вероятность спама для "Act" составляет 98%, а для "act" - только 62%.

Если вы увеличите словарный запас своего фильтра, вы можете в итоге посчитать одно и то же слово несколько раз, согласно вашему старому определению "одно и то же". Логично, что это уже не одно и то же слово. Но если это все еще беспокоит вас, позвольте мне добавить из своего опыта, что слова, которые, как вам кажется, вы считаете несколько раз, как правило, именно те, которые вы бы хотели.

Еще один эффект от увеличения словарного запаса заключается в том, что при просмотре входящей почты вы находите больше интересных маркеров, то есть тех, вероятность которых далека от .5. Я использую 15 самых интересных, чтобы решить, является ли письмо спамом. Но вы можете столкнуться с проблемой, если будете использовать фиксированное число. Если вы найдете много максимально интересных маркеров, результат может быть решен любым случайным фактором, определяющим порядок одинаково интересных маркеров. Один из способов решения этой проблемы - рассматривать некоторые из них как более интересные, чем другие.

Например, лексема "dalco" встречается 3 раза в моем корпусе спама и ни разу в моем легитимном корпусе. Токен "Url*optmails" (то есть "optmails" внутри url) встречается 1223 раза. И все же, как я привык вычислять вероятности для токенов, оба они будут иметь одинаковую вероятность спама, пороговое значение .99.

Это кажется неправильным. Есть теоретические аргументы в пользу того, чтобы дать этим двум токенам существенно разные вероятности (Пантел и Лин так и делают), но я еще не пробовал. По крайней мере, кажется, что если мы находим более 15 лексем, которые встречаются только в одном корпусе или в другом, мы должны отдать предпочтение тем, которые встречаются часто. Итак, теперь есть два пороговых значения. Для лексем, которые встречаются только в корпусе спама, вероятность равна .9999, если они встречаются более 10 раз, и .9998 в противном случае. То же самое на другом конце шкалы для лексем, встречающихся только в легитимном корпусе.

Возможно, позже я существенно изменю масштаб вероятностей лексем, но это небольшое масштабирование, по крайней мере, гарантирует, что лексемы будут отсортированы правильным образом.

Другая возможность - рассматривать не только 15 лексем, но и все лексемы, превышающие определенный порог интересности. Стивен Хаузер делает это в своем статистическом фильтре спама [8]. Если вы используете порог, сделайте его очень высоким, иначе спамеры могут подделать вас, упаковав сообщения более невинными словами.

Наконец, что делать с html? Я перепробовал весь спектр вариантов, от игнорирования до разбора. Игнорировать html - плохая идея, потому что он полон полезных признаков спама. Но если вы будете разбирать его целиком, ваш фильтр может превратиться в простой распознаватель html. Наиболее эффективным кажется средний подход - замечать одни лексемы, но не замечать другие. Я смотрю на теги a, img и font, а остальное игнорирую. На ссылки и изображения, конечно, нужно смотреть, потому что они содержат урлы.

Возможно, я мог бы быть умнее в работе с html, но не думаю, что стоит тратить на это много времени. Спам, содержащий html, легко отфильтровать. Более умные спамеры уже избегают этого. Так что производительность в будущем не должна сильно зависеть от того, как вы будете работать с html.

Производительность

В период с 10 декабря 2002 года по 10 января 2003 года я получил около 1750 спамов. Из них прошло 4. Таким образом, коэффициент фильтрации составил около 99,75%.

Два из четырех спамов я пропустил, потому что они использовали слова, которые часто встречаются в моей законной почте.

Третий был одним из тех, которые используют небезопасный cgi скрипт для отправки почты третьим лицам. Их трудно отфильтровать только по содержанию, потому что заголовки невинны и они тщательно выбирают слова, которые используют. Но даже в этом случае я обычно могу их поймать. Это письмо прошло мимо с вероятностью .88, чуть меньше порогового значения .9.

Конечно, если просмотреть несколько последовательностей лексем, его можно легко обнаружить. "Следующий результат вашей формы обратной связи" - это мгновенная подсказка.

Четвертый спам был тем, что я называю "спамом будущего", потому что я ожидаю, что именно в него превратится спам: какой-то совершенно нейтральный текст, за которым следует url. В данном случае это было письмо от кого-то, кто сообщал, что наконец-то закончил свою домашнюю страницу и просит меня взглянуть на нее. (Страница, конечно же, была рекламой порносайта).

Если спамеры внимательно относятся к заголовкам и используют свежий url, то в спаме будущего фильтрам нечего будет замечать. Мы, конечно, можем противодействовать, отправив краулер посмотреть на страницу. Но в этом может не быть необходимости. Скорость реакции на спам будущего должна быть низкой, иначе все бы этим занимались. Если он будет достаточно низким, то спамеры не будут платить за его рассылку, и нам не придется прилагать много усилий для его фильтрации.

Теперь о действительно шокирующих новостях: за тот же месячный период я получил три ложных срабатывания.

В каком-то смысле это облегчение - получить несколько ложных срабатываний. Когда я писал "A Plan for Spam", у меня их еще не было, и я не знал, какими они будут. Теперь, когда у меня их было несколько, я с облегчением обнаружил, что они не так плохи, как я опасался. Ложные срабатывания статистических фильтров оказываются письмами, которые очень похожи на спам, и это, как правило, те письма, которые вы меньше всего хотели бы пропустить [9].

Два ложных срабатывания были рассылками от компаний, у которых я покупал товары. Я никогда не просил их получать, так что, возможно, это спам, но я считаю их ложными срабатываниями, потому что раньше я не удалял их как спам. Причина, по которой фильтры поймали их, заключается в том, что обе компании в январе перешли на коммерческие почтовые отправители вместо того, чтобы отправлять письма со своих собственных серверов, и как заголовки, так и тела писем стали гораздо более спамерскими.

Однако третье ложное срабатывание было неудачным. Оно было от кого-то из Египта и написано в верхнем регистре. Это было прямым результатом того, что маркеры были чувствительны к регистру; фильтр Plan for Spam не смог бы его поймать.

Трудно сказать, каков общий процент ложных срабатываний, потому что мы находимся в шуме, статистически. Любой, кто работал над фильтрами (по крайней мере, над эффективными фильтрами), знает об этой проблеме. В отношении некоторых писем трудно сказать, являются ли они спамом или нет, и именно на них в конечном итоге обращают внимание, когда фильтры становятся очень жесткими. Например, на данный момент фильтр отловил два письма, которые были отправлены на мой адрес из-за опечатки, и одно письмо, отправленное мне в уверенности, что я - это кто-то другой. Спорно, что это не спам и не нежелательная почта.

Еще одно ложное срабатывание было получено от вице-президента компании Virtumundo. Я написал им, выдавая себя за клиента, и поскольку ответ пришел через почтовые серверы Virtumundo, он содержал самые инкриминирующие заголовки, какие только можно себе представить. Возможно, это не настоящее ложное срабатывание, а своего рода эффект неопределенности Гейзенберга: я получил его только потому, что писал о фильтрации спама.

Не считая этих случаев, на данный момент у меня было всего пять ложных срабатываний из примерно 7740 легитимных писем, что составляет 0,06%. Два других письма были уведомлением о том, что что-то, что я купил, было снято с заказа, и напоминанием о вечеринке от Evite.

Я не думаю, что этому числу можно доверять, отчасти потому, что выборка так мала, а отчасти потому, что я думаю, что могу исправить фильтр, чтобы не отлавливать некоторые из них.

Ложные срабатывания кажутся мне другим видом ошибок, нежели ложные отрицания. Скорость фильтрации - это мера эффективности. Ложные срабатывания я рассматриваю скорее как ошибки. Улучшение скорости фильтрации я рассматриваю как оптимизацию, а уменьшение количества ложных срабатываний - как отладку.

Так что эти пять ложных срабатываний - мой список ошибок. Например, письмо из Египта было прибито, потому что из-за текста в верхнем регистре оно показалось фильтру похожим на нигерийский спам. Это действительно своего рода ошибка. Как и в случае с html, письмо в верхнем регистре - это концептуально одна функция, а не одна для каждого слова. Мне нужно обрабатывать регистр более сложным способом.

Так что же делать с этими 0,06%? Думаю, ничего особенного. Можно рассматривать его как верхнюю границу, помня о малом размере выборки. Но на данном этапе это скорее показатель ошибок в моей реализации, чем какого-то присущего байесовской фильтрации коэффициента ложных срабатываний.

Будущее

Что дальше? Фильтрация - это проблема оптимизации, а ключ к оптимизации - профилирование. Не пытайтесь угадать, где ваш код работает медленно, потому что вы угадаете неправильно. Посмотрите, где ваш код работает медленно, и исправьте это. В фильтрации это означает: посмотрите на спамы, которые вы пропускаете, и выясните, что вы могли бы сделать, чтобы их поймать.

Например, спамеры сейчас активно работают над тем, чтобы обойти фильтры, и один из способов, которым они пользуются, - это разбивка и неправильное написание слов, чтобы фильтры не могли их распознать. Но работа над этим не является моей первоочередной задачей, потому что я по-прежнему без проблем ловлю эти спамы [10].

Есть два вида спама, с которыми у меня сейчас проблемы. Первый - это тип, который притворяется письмом от женщины, приглашающей вас пообщаться с ней или посмотреть ее анкету на сайте знакомств. Они проходят, потому что это единственный тип предложений о продаже, который можно сделать, не используя разговорную речь. В них используется та же лексика, что и в обычной электронной почте.

Другой вид спама, который мне трудно отфильтровать, - это письма от компаний, например, из Болгарии, предлагающих услуги программирования по контракту. Они проходят, потому что я тоже программист, а в спаме используются те же слова, что и в моей реальной почте.

Возможно, сначала я сосредоточусь на типах личных объявлений. Думаю, если я присмотрюсь, то смогу найти статистические различия между ними и моей реальной почтой. Стиль письма, безусловно, отличается, хотя для этого может потребоваться многословная фильтрация. Кроме того, я заметил, что они обычно повторяют url, а кто-то, включающий url в легитимное письмо, не стал бы этого делать [11].

Аутсорсинговые типы будет трудно поймать. Даже если бы вы послали краулер на сайт, вы бы не нашли дымящийся статистический пистолет. Возможно, единственный выход - это центральный список доменов, рекламируемых в спаме [12]. Но таких писем не может быть так много. Если бы в спаме оставались только незапрашиваемые предложения услуг программирования по контракту из Болгарии, мы все могли бы перейти к работе над чем-то другим.

Сможет ли статистическая фильтрация действительно привести нас к этому? Я не знаю. Сейчас, лично для меня, спам не является проблемой. Но спамеры еще не предпринимали серьезных усилий, чтобы подделать статистические фильтры. Что произойдет, когда они это сделают?

Я не испытываю оптимизма по поводу фильтров, работающих на сетевом уровне [13]. Когда есть статическое препятствие, которое стоит преодолеть, спамеры довольно эффективно его преодолевают. Уже существует компания Assurance Systems, которая прогонит вашу почту через Spamassassin и скажет вам, будет ли она отфильтрована.

Фильтры на уровне сети не будут полностью бесполезными. Их может быть достаточно, чтобы уничтожить весь "opt-in" спам, то есть спам от таких компаний, как Virtumundo и Equalamail, которые утверждают, что они действительно ведут списки opt-in. Их можно отфильтровать, основываясь только на заголовках, независимо от того, что написано в теле письма. Но любой, кто готов фальсифицировать заголовки или использовать открытые ретрансляторы, включая, предположительно, большинство порноспамеров, должен иметь возможность пропустить какое-либо сообщение через фильтры сетевого уровня, если захочет. (Однако это далеко не то сообщение, которое они хотели бы послать, а это уже кое-что).

Я с оптимизмом смотрю на фильтры, которые рассчитывают вероятности на основе почты каждого отдельного пользователя. Они могут быть гораздо более эффективными не только в плане предотвращения ложных срабатываний, но и в плане фильтрации: например, обнаружение адреса электронной почты получателя в кодировке base-64 в любом месте сообщения является очень хорошим индикатором спама.

Но реальное преимущество индивидуальных фильтров заключается в том, что все они будут разными. Если у всех фильтров будут разные вероятности, это сделает цикл оптимизации спамеров, который программисты назвали бы циклом редактирования-компиляции-тестирования, ужасающе медленным. Вместо того чтобы просто настраивать спам, пока он не пройдет через копию какого-то фильтра, который стоит у них на рабочем столе, им придется делать тестовую рассылку для каждой правки. Это было бы похоже на программирование на языке без интерактивного верхнего уровня, и я никому не пожелаю этого.

Примечания

[1] Пол Грэм. "A Plan for Spam". August 2002. http://paulgraham.com/spam.html.

Вероятности в этом алгоритме рассчитываются с помощью вырожденного случая правила Байеса. Есть два упрощающих предположения: что вероятности признаков (т.е. слов) независимы, и что мы ничего не знаем о предварительной вероятности того, что письмо является спамом.

Первое предположение широко распространено в классификации текстов. Алгоритмы, использующие его, называются "наивными байесовскими".

Второе предположение я сделал потому, что доля спама во входящей почте так сильно колебалась изо дня в день (более того, из часа в час), что общее предварительное соотношение казалось бесполезным в качестве предсказателя. Если вы предположите, что P(спам) и P(не спам) равны .5, они аннулируются, и вы можете убрать их из формулы.

Если бы вы выполняли байесовскую фильтрацию в ситуации, когда отношение спама к неспаму постоянно очень высокое или (особенно) очень низкое, вы, вероятно, могли бы улучшить эффективность фильтрации, включив в него предварительные вероятности. Чтобы сделать это правильно, вам придется отслеживать соотношение по времени суток, поскольку объем спама и легитимной почты имеет четкую суточную динамику.

[2] Patrick Pantel and Dekang Lin. "SpamCop-- Программа классификации и организации спама". Труды семинара AAAI-98 по обучению категоризации текста.

[3] Mehran Sahami, Susan Dumais, David Heckerman and Eric Horvitz. "Байесовский подход к фильтрации нежелательной почты". Proceedings of AAAI-98 Workshop on Learning for Text Categorization.

[4] В то время у меня было ноль ложных срабатываний из примерно 4 000 законных писем. Если бы следующее законное письмо было ложным срабатыванием, это дало бы нам .03%. Эти показатели ложных срабатываний не заслуживают доверия, как я объясню позже. Я привожу здесь число только для того, чтобы подчеркнуть, что каким бы ни был коэффициент ложных срабатываний, он меньше 1,16%.

[5] Bill Yerazunis. "Sparse Binary Polynomial Hash Message Filtering and The CRM114 Discriminator.". Proceedings of 2003 Spam Conference.

[6] В статье "A Plan for Spam" я использовал пороговые значения .99 и .01. Кажется оправданным использовать пороговые значения пропорционально размеру корпораций. Поскольку сейчас у меня порядка 10 000 писем каждого типа, я использую .9999 и .0001.

[7] Здесь есть недостаток, который, вероятно, следует исправить. В настоящее время, когда "Subject*foo" вырождается в просто "foo", это означает, что вы получаете статистику для вхождений "foo" в тело или заголовки строк, кроме тех, которые я помечаю. Что я должен делать, так это отслеживать статистику для "foo" в целом, а также для конкретных версий, и вырождаться из "Subject*foo" не в "foo", а в "Anywhere*foo". То же самое касается регистра: Я должен выродиться из прописного в любой регистр, а не в строчный.

Вероятно, было бы выигрышно сделать это и с ценами, например, выродить из "$129.99" в "$--9.99", "$--.99" и "$--".

Можно также выродить от слов к их основам, но это, вероятно, улучшит скорость фильтрации только на ранних этапах, когда у вас небольшие корпорации.

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

[9] Ложные срабатывания не все одинаковы, и мы должны помнить об этом при сравнении методов борьбы со спамом. В то время как многие ложные срабатывания, вызванные фильтрами, будут почти спамом, который вы не прочь пропустить, ложные срабатывания, вызванные черными списками, например, будут просто письмами от людей, которые выбрали неправильного провайдера. В обоих случаях вы отлавливаете почту, которая близка к спаму, но для черных списков близость - это физический фактор, а для фильтров - текстовый.

[10] Если спамеры достаточно хорошо умеют скрывать лексемы, чтобы это стало проблемой, мы можем ответить на это, просто удалив пробелы, точки, запятые и т.д. и используя словарь для выбора слов из полученной последовательности. И, конечно, обнаружение таким образом слов, которые не были видны в оригинальном тексте, само по себе будет свидетельствовать о спаме.

Выделение слов не будет тривиальным. Для этого потребуется не только восстановить границы слов; спамеры как добавляют ("xHot nPorn cSite"), так и опускают ("P#rn") буквы. Здесь может быть полезно исследование зрения, поскольку человеческое зрение - это предел, к которому приближаются такие трюки.

[11] В целом, спам более повторяющийся, чем обычная электронная почта. Они хотят донести это сообщение до адресата. В настоящее время я не допускаю дубликаты в 15 лучших лексемах, потому что вы можете получить ложное срабатывание, если отправитель случайно использует какое-нибудь плохое слово несколько раз. (В моем текущем фильтре "dick" имеет вероятность спама .9999, но это также имя). Кажется, что мы должны хотя бы замечать дублирование, поэтому я могу попробовать разрешить до двух повторений каждого слова, как это делает Брайан Бертон в SpamProbe.

[12] Именно в это превратятся подходы, подобные Brightmail, когда спамеры будут вынуждены использовать методы mad-lib для генерации всего остального в сообщении.

[13] Иногда утверждается, что мы должны работать над фильтрацией на сетевом уровне, потому что это более эффективно. Говоря это, люди обычно имеют в виду следующее: в настоящее время мы фильтруем на сетевом уровне, и мы не хотим начинать все с нуля. Но вы не можете диктовать проблему, чтобы она соответствовала вашему решению.

Исторически сложилось так, что в спорах о разработке программного обеспечения аргументы о дефиците ресурсов проигрывают. Люди склонны использовать их только для того, чтобы оправдать выбор (в частности, бездействие), сделанный по другим причинам.