Комментарии 46
Зашел в профиль плюсануть, а там уже.
Хороший топик, читал с интересом.
Хороший топик, читал с интересом.
Идея хорошая, но написать такое когда УЖЕ идет ддос атака практически нереально ( сроки маленькие + стресс ). Раскопаю ка я свой диплом… нейросеть на питоне для управления металлургическим печами )))
Если давление во времмя DDoS'а мешает программировать, то конечно нужно блокировать старыми добрыми методами, однако потом ничто не мешает собрать логи и уже в спокойной обстановке попробовать написать что-нибудь интересное.
А можно подробнее про Ваш диплом? Что делали, для чего нейронную сеть использовали, получилось ли что-то живое в итоге, или все только на бумаге?
Не учитывается самое важное — поведение бота. То есть анализировать надо не одну строчку, а последовательность строк с одного IP…
Мне кажется, поведение клиента — это вообще единственный критерий, где нейронная сеть могла бы пригодиться. Для простого отсева клиентов по их IP сеть практически бесполезна.
Да, я по началу тоже думал принимать решения базируясь не на конкретном запросе, а на блоках, сгруппированных по IP или лучше session_id. Но потом пришла ещё пара мыслей:
1) Строить некий call-graph для каждой сессии и анализировать его.
2) Использовать js для записи и анализировать поведение пользователей.
Но это уже тема для отдельного поста или даже полноценного ПО.
1) Строить некий call-graph для каждой сессии и анализировать его.
2) Использовать js для записи и анализировать поведение пользователей.
Но это уже тема для отдельного поста или даже полноценного ПО.
Да, вот цитата из статьи: «Также этот код не самодостаточен. Ему всё равно нужна скриптовая обвязка. Например, если IP сделал N плохих запросов в течение X минут, то банить его на firewall'е.»
Нужно найти способ алгоритмизировать анализ поведения во времени, тогда будет интеллектуальная система! Хотя, для отсева IP-адресов явных ботов, предложенная методика отлично подойдет.
Нужно найти способ алгоритмизировать анализ поведения во времени, тогда будет интеллектуальная система! Хотя, для отсева IP-адресов явных ботов, предложенная методика отлично подойдет.
Можно заранее обучить сеть определять хороших посетителей (то есть тех, кто уже посещал сайт). Пока дела идут хорошо, мы ее не используем, но при этом постоянно переучиваем. При начале DDoS'а мы ее задействуем. Очевидно, что она не избавит от всех атакующих, но может серьезно урезать их число.
Такая идея определенно защитит, но не пропустит новых пользователей. Мне кажется такой принцип является наиболее дешевым и простым.
К сожалению такая нейронная сеть скорее всего сойдётся на том, что будет любой запрос классифицировать как хороший, поэтому такой метод недееспособен.
Если не писать в белый список данные во время атаки, то все будет нормально.
Наверное, вы имели ввиду обратное, что любой запрос, кроме тех, что у нее были в обучающем множестве, сеть будет определять как плохой. Но ведь для того и существует тестирующее множество, чтобы сеть не переобучилась.
Нет, я имел в виду именно то, что написал.
Давайте поясню:
Давайте отбросим всю математику за процессом обучения и представим нейронную сеть как чёрный ящик. Вы в него кидаете данные, а он выдаёт класс этих данных. При обучении только «хорошими» запросами вы научите нейронную сеть говорить, что запрос хороший, на ЛЮБЫЕ входные данные, ведь именно такое поведение будет выдавать наименьшие ошибки на training и test set'ах.
Давайте поясню:
Давайте отбросим всю математику за процессом обучения и представим нейронную сеть как чёрный ящик. Вы в него кидаете данные, а он выдаёт класс этих данных. При обучении только «хорошими» запросами вы научите нейронную сеть говорить, что запрос хороший, на ЛЮБЫЕ входные данные, ведь именно такое поведение будет выдавать наименьшие ошибки на training и test set'ах.
По поводу «наименьших ошибок на training и test set'ах». Вы совершенно правы, что на обучающем множестве с каждым пробегом ошибка будет падать. Но на тестовом множестве с определенного момента она начнет расти. В этот момент сеть обучилась, и обучение необходимо остановить, поскольку дальше пойдет переобучение.
Давайте для примера упростим задачу. Будем считать, что у нас есть только данные GeoIP (широта и долгота). Аудитория нашего сайта — территория России. После обучения на «хороших» запросах наша сеть с определенной погрешностью определяет запросы с территории России. Начинается DDoS. Большинство запросов с территории России сеть пропускает, а все остальные запросы — блокирует.
При таком обучении тоже идет классификация, но неявная. «Хорошие» запросы противопоставляются «всем остальным возможным».
Давайте для примера упростим задачу. Будем считать, что у нас есть только данные GeoIP (широта и долгота). Аудитория нашего сайта — территория России. После обучения на «хороших» запросах наша сеть с определенной погрешностью определяет запросы с территории России. Начинается DDoS. Большинство запросов с территории России сеть пропускает, а все остальные запросы — блокирует.
При таком обучении тоже идет классификация, но неявная. «Хорошие» запросы противопоставляются «всем остальным возможным».
«Но на тестовом множестве с определенного момента она(ошибка) начнет расти.»
Моё утверждение было таково: Нейронная сеть обученая только хорошими запросами сойдётся к тому, что будет выдавать «хорошо» на любой ввод. Теперь вопрос: как сеть которая выдаёт на любые входные данные «хорошо» может хоть раз ошибится на тестовом множестве?
ПС. Ещё вопрос: а вы пробовали сами проделать вышеописаный вами эксперимент? Можно и без эксперимента, просто расписав формулы на листочке.
Просто чтобы Вы не считали меня «человеком с улицы» скажу, что в 2001 году я защитил магистерскую диссертацию в ГУ-ВШЭ по теме «Нейросетевые технологии в финансовом анализе».
Мои утверждения:
1) Нейронная сеть, обученная на «хороших» запросах без тестирующего множества («переученная»), будет на любой запрос (кроме тех, что ей были представлены на обучение) отвечать, что он «плохой». Все потому, что она «запомнила» исходные данные.
2) Нейронная сеть, обученная на «хороших» запросах с тестирующим множеством, будет на «хороший» запрос отвечать, что он «хороший», а на «все остальные», что они «не хорошие». При этом если «плохой» запрос неотличим от «хорошего», то сеть его также будет считать «хорошим». В примере, приведенном выше, если «плохой» запрос будет идти из России, а не из Китая, то сеть его пропустит.
Непонимание возникло потому, что Вы фокусируетесь на «плохих» запросах. А я говорю о «хороших». Есть аналогия из мира электронной почты и борьбы со спамом — «черный» и «белый» списки. Приведенный Вами метод аналогичен «черному», упомянутый мною — «белому».
Мои утверждения:
1) Нейронная сеть, обученная на «хороших» запросах без тестирующего множества («переученная»), будет на любой запрос (кроме тех, что ей были представлены на обучение) отвечать, что он «плохой». Все потому, что она «запомнила» исходные данные.
2) Нейронная сеть, обученная на «хороших» запросах с тестирующим множеством, будет на «хороший» запрос отвечать, что он «хороший», а на «все остальные», что они «не хорошие». При этом если «плохой» запрос неотличим от «хорошего», то сеть его также будет считать «хорошим». В примере, приведенном выше, если «плохой» запрос будет идти из России, а не из Китая, то сеть его пропустит.
Непонимание возникло потому, что Вы фокусируетесь на «плохих» запросах. А я говорю о «хороших». Есть аналогия из мира электронной почты и борьбы со спамом — «черный» и «белый» списки. Приведенный Вами метод аналогичен «черному», упомянутый мною — «белому».
Хммм, всё равно не могу понять: как без «плохих» примеров, даже при наличии test set'а, запрретить сети отвечать на всё запросы «хороший». Ведь именно такой подход обеспечит ей 0% ошибок на Training set и Test set.
Ммм… Для того чтобы она действительно смогла «запомнить» все feature vector'а нужно очень большое количество нейронов (= кол-во features * кол-во запросов). Так же скорее всего придётся вводить какие-то ограничения на количество одновременно активных нейронов (sparsity), иначе сеть опять сойдётся на «всё хорошо». Ещё к этому нужно добавить, что я не очень хорошо понимаю как поощрять сеть за удачные «запоминания» и наказывать за неудавшиеся. Хотя, логично предположить, что обучить нейронную сеть запоминать возможно — яркий тому пример наш мозг.
ПС. Так же я не понял разницу между вашими 1) и 2).
Все потому, что она «запомнила» исходные данные.
Ммм… Для того чтобы она действительно смогла «запомнить» все feature vector'а нужно очень большое количество нейронов (= кол-во features * кол-во запросов). Так же скорее всего придётся вводить какие-то ограничения на количество одновременно активных нейронов (sparsity), иначе сеть опять сойдётся на «всё хорошо». Ещё к этому нужно добавить, что я не очень хорошо понимаю как поощрять сеть за удачные «запоминания» и наказывать за неудавшиеся. Хотя, логично предположить, что обучить нейронную сеть запоминать возможно — яркий тому пример наш мозг.
ПС. Так же я не понял разницу между вашими 1) и 2).
Во-первых, по поводу «0% ошибок на Training set и Test set». По ссылкам вы найдете два графика — в теории и на практике (ссылка на статью). На графиках видно, что ошибка на тестовом множестве с определенного момента начинает расти.
Во-вторых, не имея «плохих» примеров, их можно сконструировать из «хороших», инвертируя булевы значения и интервалы. Очевидно, что это будут не «плохие» значения в вашем понимании, а просто «все остальные возможные».
В-третьих, «запомнить» для нейронной сети, если это само не является целью, — это самое плохое, что с ней может случиться. Ее цель — «обобщать».
P.S. Позвольте проиллюстрировать разницу на этом графике (ссылка на статью). Когда сеть не переучена (нижний рисунок), новое наблюдение классифицируется как принадлежащее «зеленой области». Когда сеть переучена (верхний правый рисунок), новое наблюдение не попадает в зеленую область. Тестовое множество помогает нам эмулировать поступление новых данных и не давать сети переучиваться.
Во-вторых, не имея «плохих» примеров, их можно сконструировать из «хороших», инвертируя булевы значения и интервалы. Очевидно, что это будут не «плохие» значения в вашем понимании, а просто «все остальные возможные».
В-третьих, «запомнить» для нейронной сети, если это само не является целью, — это самое плохое, что с ней может случиться. Ее цель — «обобщать».
P.S. Позвольте проиллюстрировать разницу на этом графике (ссылка на статью). Когда сеть не переучена (нижний рисунок), новое наблюдение классифицируется как принадлежащее «зеленой области». Когда сеть переучена (верхний правый рисунок), новое наблюдение не попадает в зеленую область. Тестовое множество помогает нам эмулировать поступление новых данных и не давать сети переучиваться.
1) Она может начать расти только если в тестовом наборе есть «плохие» примеры, иначе ошибка будет 0% и там и там.
2) Вот это уже интересно. То есть «плохие» примеры всё же есть, но они генерируются из «хороших». Правда похоже это возможно делать только имея на руках единовременно все «хорошие», иначе сложно ответить на вопрос: не встречался/встретится ли только что сгенерированный «плохой» пример в «хорошем» наборе. Также, пока не очень понимаю как генерировать словарь для создания feature vector'ов и рассчитывать размер input layer без наличия на руках всех запросов единовременно. Впрочем, некоторыи идеи на этот счёт есть.
3) С этим согласен.
2) Вот это уже интересно. То есть «плохие» примеры всё же есть, но они генерируются из «хороших». Правда похоже это возможно делать только имея на руках единовременно все «хорошие», иначе сложно ответить на вопрос: не встречался/встретится ли только что сгенерированный «плохой» пример в «хорошем» наборе. Также, пока не очень понимаю как генерировать словарь для создания feature vector'ов и рассчитывать размер input layer без наличия на руках всех запросов единовременно. Впрочем, некоторыи идеи на этот счёт есть.
3) С этим согласен.
Нейросетевые технологии могут быть применены не только к задаче классификации (то, что вы описали в обсуждаемой статье), но и к задаче кластеризации (то, о чем я безуспешно пытаюсь вам сказать). Для решения первой нам нужно не менее двух классов, для решения последней — просто набор данных.
Давайте вернемся к вышеупомянутому примеру, где все «хорошие» запросы шли с территории России, а про «плохие» мы и слыхом не слыхивали.
Сеть будем обучать только на «хороших» запросах. На вход будем подавать вектор [lat, lng]. На выходе будем получать значения из интервала (0, 1). Ошибкой для нас будет разность между единицей и фактическим выходом из сети (не стандартное отклонение — для наглядности). Разделим все наши «запросы» на два множества — обучающее и тестовое. Начнем обучение сети.
Средняя ошибка на первом прогоне будет в районе 0.5 — для обоих множеств. С каждым прогоном эти ошибки будут падать, так как мы заставляем сеть выдавать результат все более близкий к единице. Но на определенном этапе ошибка обучающего множества упадет, а ошибка тестового множества — вырастет. Почему?
К примеру, потому, что в обучающем множестве не было ни одного запроса из Надыма, а в тестовом множестве он был.
Обучение только на «хороших» данных — это нетипичное решение типичной задачи кластеризации.
Давайте вернемся к вышеупомянутому примеру, где все «хорошие» запросы шли с территории России, а про «плохие» мы и слыхом не слыхивали.
Сеть будем обучать только на «хороших» запросах. На вход будем подавать вектор [lat, lng]. На выходе будем получать значения из интервала (0, 1). Ошибкой для нас будет разность между единицей и фактическим выходом из сети (не стандартное отклонение — для наглядности). Разделим все наши «запросы» на два множества — обучающее и тестовое. Начнем обучение сети.
Средняя ошибка на первом прогоне будет в районе 0.5 — для обоих множеств. С каждым прогоном эти ошибки будут падать, так как мы заставляем сеть выдавать результат все более близкий к единице. Но на определенном этапе ошибка обучающего множества упадет, а ошибка тестового множества — вырастет. Почему?
К примеру, потому, что в обучающем множестве не было ни одного запроса из Надыма, а в тестовом множестве он был.
Обучение только на «хороших» данных — это нетипичное решение типичной задачи кластеризации.
Я в вашем примере не могу понять одну вещь: откуда в тестовой выборке появится Надым, ведь он не «хороший»?
К примеру, всего «хороших» запросов у нас было 100 (в том числе Надым). Четверь из них (25 запросов, в том числе Надым) мы отобрали случайным образом и сформировали из них тестовое множество. Оставшиеся три четверти (75 запросов) — это наше обучающее множество.
В данной постановке задачи у нас вообще нет понятия «плохие» запросы. Когда начинается DDoS, мы блокируем все, что не узнается.
В данной постановке задачи у нас вообще нет понятия «плохие» запросы. Когда начинается DDoS, мы блокируем все, что не узнается.
/* На случай, если кто-то, всё же, до сюда дочитал */
avrelian Натолкнул меня на интересную мысль: Как можно использовать Нейронную Сеть для кластеризации данных?
После прочтения нескольких десятков pdf'ок по Clusterization using Neural Networks стали выделятся некоторые алгоритмы для unsupervised обучения нейронных сетей. Особо можно выделить SOTA (Self Organising Tree Algorithm — Развитие идеи SOM — Self-Organized Maps) и семейство алгоритмов ART*. Остановлюсь подробнее на последних, ибо они более напоминают устройство нашего мозга: алгоритм устроен на сравнении ожиданий с данными от сенсоров. Если посмотреть на матчасть, то видно, как алгоритм умудряется балансировать между обучением и запоминанием. Так же, довольно интересной для новичков в ML будет являться структура нейронной сети используемой в ART*/SOTA алгоритмах.
В общем будет с чем поиграться на досуге.
«Можно поразмыслить на тему распараллеливания обучения нейронной сети. Простое решение — тренировать сразу несколько нейронных сетей параллельно и из них выбирать лучшую, но это создаст дополнительную нагрузку на память, что тоже не очень хорошо.»
Совсем не хорошо, по сути, будут растрачиваться ресурсы на обучение 2 разных сетей, вместо одной.
Оптимальным вариантом считается параллельное вычисление изменения весовых коэффициентов, к примеру, такой модификации легко подвергаются алгоритмы обучения QuickProp и PRProp, где при вычислении весовых коэффициентов используются:
- — их значения на предыдущей итерации
- — прошлое изменение коэффициента
- — значение градиента на текущей и предыдущей итерации
Следовательно, вычисление каждого коэффициента можно распараллелить.
Эта моя фраза говорила примерно о следующем: запускать параллельно несколько однопоточных обучений или последовательно запускать многопоточные обучения — это почти одно и тоже. А нам похоже всё равно придётся несколько сетей тренировать, ибо никто не гарантирует, что мы при обучении не упрёмся в локальный минимум. Так же дополнительные нейронные сети нужны для выбора констант — weightdecay и momentum. Но это конечно если я правильно понял теорию.
ПС. А так да, подход с многопоточным обучением одной нейронной сети более масштабируем, чем несколько паралельных однопоточных обучений.
ППС. ИМХО, первым кандидатом на распараллеливание является этап перемножения матриц.
ПППС. За QuickProp и PRProp отдельное спасибо, пойду про них почитаю…
ПС. А так да, подход с многопоточным обучением одной нейронной сети более масштабируем, чем несколько паралельных однопоточных обучений.
ППС. ИМХО, первым кандидатом на распараллеливание является этап перемножения матриц.
ПППС. За QuickProp и PRProp отдельное спасибо, пойду про них почитаю…
Решение жизнеспособное, как функция обнаружения критериев, но практически ненужная.
Отфильтровывать бота по единичным запросам гораздо проще обычным grep по известным критериям, их немного. Строить для этого НС нецелесообразно. У НС есть еще один минус, боты могут получить команду на изменение типа атаки. Поправить скрипты фильтрации просто, переобучить НС в общем случае сложно (дорого по времени и вычислительным ресурсам).
НС имела бы смысл, если бы вы реализовали обнаружение бота по истории его запросов, т.е. поведенческий анализ, но это уже значительно сложнее и MLP тут не выручит.
Резюмируя, подход рабочий, необычный, но практически невостребованый. Данную задачу при конкретных указанных условиях grep выполняет быстрее, проще и гибче.
Отфильтровывать бота по единичным запросам гораздо проще обычным grep по известным критериям, их немного. Строить для этого НС нецелесообразно. У НС есть еще один минус, боты могут получить команду на изменение типа атаки. Поправить скрипты фильтрации просто, переобучить НС в общем случае сложно (дорого по времени и вычислительным ресурсам).
НС имела бы смысл, если бы вы реализовали обнаружение бота по истории его запросов, т.е. поведенческий анализ, но это уже значительно сложнее и MLP тут не выручит.
Резюмируя, подход рабочий, необычный, но практически невостребованый. Данную задачу при конкретных указанных условиях grep выполняет быстрее, проще и гибче.
Вы не поверите, как вы вовремя. Я через неделю защищаю диплом именно по этой теме.
По образованию я — специалист по информационной безопасности.
По образованию я — специалист по информационной безопасности.
Отличная статья. И как раз для Хабра.
Для улучшения результатов разрешите посоветовать небольшие усовершенствования:
1) После первого MPL легко определить значимость входов (меняем один вход в возможном диапазоне, смотрим как меняется выход). Незначимые входы — зло.
2) На отобранных значимых входах учим новую сеть — она будет меньше и точнее (т.к. убили часть шума)
3) Пр обучении второго MPL лучше использовать функционал Тихонова — интеллект сети (умение обобщать) будет выше.
А вообще для данной задачи дерево решений наверное было бы лучше — быстрее и возможно точнее. имхо.
Для улучшения результатов разрешите посоветовать небольшие усовершенствования:
1) После первого MPL легко определить значимость входов (меняем один вход в возможном диапазоне, смотрим как меняется выход). Незначимые входы — зло.
2) На отобранных значимых входах учим новую сеть — она будет меньше и точнее (т.к. убили часть шума)
3) Пр обучении второго MPL лучше использовать функционал Тихонова — интеллект сети (умение обобщать) будет выше.
А вообще для данной задачи дерево решений наверное было бы лучше — быстрее и возможно точнее. имхо.
НЛО прилетело и опубликовало эту надпись здесь
Проблема нейронки — переучивание — долгий процесс.
Не проще ли байзанов фильтр имплементировать? Он быстрее будет в плане переучивания.
И да, обязательно нужен интерфейс.
Не проще ли байзанов фильтр имплементировать? Он быстрее будет в плане переучивания.
И да, обязательно нужен интерфейс.
Насчёт байесовского фильтра — интересная идея на подумать, спасибо.
Какой-то уж через-чур простой и прямолинейный ботнет вам попался.
А что бы вы делали, если ботнет был заточен под ваш сайт и был обучен
1) на поведении реальных юзеров и посылал «хорошие» заголовки
2) на структуре вашего сайта
?
А что бы вы делали, если ботнет был заточен под ваш сайт и был обучен
1) на поведении реальных юзеров и посылал «хорошие» заголовки
2) на структуре вашего сайта
?
Ой, промахнулся — коммент ниже приедназначен вам.
Не поверите, но нейронную сеть начал писать только после того как не смог сходу «нагрепать» запросы от ботов, вот, например, угадайте какой из запросов тут от бота:
Так что с заголовками было всё ок.
Как я понимаю, нейронная сеть мне хорошо помогла «поймать» продвинутый, но всё же ограниченный генератор User-agent'ов аттакующего.
0.0.0.0 - - [20/Dec/2011:18:13:08 +0400] "GET /forum/index.php HTTP/1.1" 200 25364 "-" "Opera/9.80 (Windows NT 5.1; U; ru) Presto/2.9.168 Version/11.52"
0.0.0.0 - - [20/Dec/2011:15:56:40 +0400] "GET /forum/index.php HTTP/1.1" 200 25364 "-" "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.10.229 Version/11.60"
Так что с заголовками было всё ок.
Как я понимаю, нейронная сеть мне хорошо помогла «поймать» продвинутый, но всё же ограниченный генератор User-agent'ов аттакующего.
Вопрос по производительности.
Ясно, что есть проблемы, но не указан их порядок.
Т.е. хочется узнать
1. размер тренировочного массива данных (приблизительное количество записей в логах)
2. сколько времени заняла тренировка сети.
Ясно, что есть проблемы, но не указан их порядок.
Т.е. хочется узнать
1. размер тренировочного массива данных (приблизительное количество записей в логах)
2. сколько времени заняла тренировка сети.
Производительность очень сильно зависит от реализации. Цифры я не озвучивал специально, ибо это всего лишь набросок, темболее на питоне. Любые числа названные мной будут на порядки отличаться от продакш системы.
Тем не менее интересен сам порядок цифр. Я до этого не сталкивался с практическим machine learning. Есть только базовые теоретические знания и желание перейти к практике (есть ряд подходящих задач). Всюду говорят, что обучение может занять значительное время, но непонятно: значительное — это сколько?
20 секунд для массива из миллиона элементов и 100 features — это нормально, много, мало? Или при использовании неоптимизированнных однопотоковых алгоритмов для подобных массивов следует ожидать часов и дней на тренировку сети?
Поэтому производительность контретно этого случая может быть показательной (алгоритм, библиотеки, и особенности реализации известены, нужно лишь сделать поправку на железо).
P.S. Кстати, сколько всего признаков получилось?
20 секунд для массива из миллиона элементов и 100 features — это нормально, много, мало? Или при использовании неоптимизированнных однопотоковых алгоритмов для подобных массивов следует ожидать часов и дней на тренировку сети?
Поэтому производительность контретно этого случая может быть показательной (алгоритм, библиотеки, и особенности реализации известены, нужно лишь сделать поправку на железо).
P.S. Кстати, сколько всего признаков получилось?
Было интересно, спасибо. Я тоже, когда проходил обучение, задавался вопросом на тему фильтрации ботов при ддос атаках и рассматривал в том числе и нейросеть. Помнится тогда мне показалось, что anomaly detection более органично подошло бы под эту задачу — много положительных примеров и заранее не известны отрицательные.
Я тоже думал по началу это сделать на определении аномалий, но там есть нюанс: нужно вводить дополнительные features являющиеся комбинацией существующих, чтобы ловить запросы с OS Windows ME и referer'ом fc-zenit.ru, а это очень сильно увеличивает их кол-во. Например, из 100 признаков мы получим 5050, если захотим ловить по комбинации двух признаков, а если по трём, то все 171700.
Можно попробовать зайти с другой стороны. Например в качестве features брать количество заголовков у запроса, количество разных агентов (useragent) для одного ip за определенный период времени (за час, например), высчитывать общую частоту запросов для разных агентов (вдруг появится слишком частый или наоборот — много уникальных), тоже самое с запрашиваемыми страницами (url), наличием или отсутствием кук, рефереров (и их частота появления) и т.д. По идее наберется разумное количество features.
Плюсанул бы карму, да у самого не хватает по новым правилам. Хороший топик, спасибо. У самого диплом по нейронным сетям)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Нейронная сеть против DDoS'а