Что-то довольно интересное произошло с Lucene. Она начиналась как библиотека, затем ее разработчики начали добавлять новые проекты на ее основе. Они разработали еще один проект с открытым исходным кодом, который добавил бы в Lucene функции сканирования (среди прочих). На самом деле Nutch — это полнофункциональный движок веб-поиска, который каждый может использовать или модифицировать.
Вдохновленные в некоторых известных статьях Google о Map Reduce и файловой системе Google , новые функции для распространения индекса добавлены в Nutch и, в конце концов, эти функции стали их собственным проектом: Hadoop . С тех пор многие проекты разрабатываются через Hadoop. Мы находимся перед большим взрывом открытого исходного кода, который был зажжен искрой Lucene.
Все эти проекты так или иначе связаны с обработкой контента. Для всех вас, заинтересованных в поиске и поиске информации, теперь мы поговорим о другом проекте для домена, который находится за пределами строгого ограничения поиска, но может научить вас некоторым интересным вещам в области обработки контента.
Недавно я читал об этой новой библиотеке Mahout, которая предоставляет все эти неясные и загадочные алгоритмы машинного обучения, вместе в библиотеке. Многие современные веб-сайты используют методы машинного обучения. Эти алгоритмы довольно стары и хорошо известны, но в последнее время стали популярными благодаря широкому использованию их на сайтах социальных сетей (Facebook знает лучше, чем вы, кто может быть вашим лучшим другом) или в Google (читая ваши мысли и догадываясь, что вы хотели написать в окно поиска).
Проще говоря, мы можем сказать, что компьютерная программа, как говорят, извлекает уроки из опыта E в отношении некоторого класса задач T и показателя производительности P, если ее производительность при выполнении задач в T, измеряемая P, улучшается с опытом E.
Например, если вы хотите создать программу для распознавания капч, вы должны иметь:
T: распознавание капчи
P: процент правильно распознанных слов
E: база данных капч с правильными написаниями слов
Так что, похоже, все, что им было нужно, это вычислительная мощность. И им нужно много вычислительной мощности. Например, в контролируемом машинном обучении (я изучил этот термин месяц назад, не ожидайте, что я буду очень академичным), вы показываете машине некоторые примеры (опыт) того, что вы хотите, и машина извлекает из них некоторые шаблоны. Это почти то же самое, что делает человек, когда он учится: из некоторых примеров, показанных человеку, он использует свои прошлые знания, чтобы вывести какую-то модель, которая поможет ему классифицировать будущие события того же рода. Ну, компьютеры довольно глупы в изучении вещей, поэтому вам нужно показать им много примеров, чтобы вывести схему.
Классификация, однако, является лишь частью проблемы. Есть три больших области, на которые нацелен Mahout (и будет больше в будущем, потому что проект относительно новый). Классификация, кластеризация и рекомендации. Типичные примеры этого:
- Классификация: это контролируемое обучение, вы даете машине множество экземпляров… вещей (например, документов) вместе с их категорией. Из всего этого машина учится классифицировать будущие экземпляры по известным категориям.
- Кластеризация: похожа на классификацию в том смысле, что она создает группы вещей, но эта не контролируется. Вы даете машине много вещей, и машина делает группы похожих предметов.
- Рекомендация: это именно то, что IMDb или Amazon делает с рекомендованными фильмами или книгами внизу страницы. Основываясь на лайках других пользователей (которые измеряются звездочками рейтинга, за которые голосует пользователь) Amazon может сделать вывод, что «другим пользователям, которым понравилась эта книга, также понравились эти другие».
Автономный пример
Теперь я покажу вам простую программу, которая, на мой взгляд, является довольно очевидным примером классификации. Мы собираемся классифицировать почту как спам, а не как спам (то, что люди, изучающие его, называют это хамом). Шаги следующие:
- Получить хам / спам корпус из Интернета (конечно, уже классифицированы).
- Тренируйте классификатор с 80% корпуса и оставьте 20% для тестирования
- Создайте простой веб-сервис, который классифицирует спам онлайн. Вы предоставляете ему почту, и она будет говорить «хорошо» или «плохо» (или «ветчина» или «спам»)
Корпус, который мы собираемся использовать, принадлежит Spam Assasin , проекту с открытым исходным кодом от Apache, который является фильтром антиспама. Это учебное пособие, поэтому мы не пытаемся классифицировать очень сложные письма, просто чтобы показать, насколько просто это можно сделать с помощью Mahout (конечно, сложные вещи были запрограммированы разработчиками этой библиотеки). Этот корпус довольно прост, и результаты будут очень удовлетворительными.
Mahout поставляется с некоторыми примерами, уже подготовленными. Одним из них является пример из 20 групп новостей, который пытается классифицировать множество писем из группы новостей по их категориям. Этот пример можно найти в вики Mahout, и, к счастью для нас, формат новостных групп почти такой же, как и у наших писем. Мы собираемся применить ту же цепочку обработки к нашим письмам, что и группа новостей 20. Кстати, мы собираемся использовать алгоритм классификации, называемый наивным байесовским, который использует знаменитую теорему Байеса, о которой я уже упоминал в предыдущем посте. Я не буду объяснять, как работает алгоритм, я просто покажу вам, как он работает!
Mahout имеет две программы драйвера (они называются так, потому что они также используются в Hadoop для выполнения заданий по сокращению карты), одна для обучения классификатора, а другая для его тестирования.
Когда вы обучаете классификатор, вы предоставляете ему файл (да, один файл), который содержит один документ на строку, уже проанализированный. «Анализируется» в том же смысле, что и Lucene анализирует документы. Фактически, мы собираемся использовать StandardAnalizer Lucene, чтобы немного очистить документы и преобразовать их в поток терминов. Этот поток помещается в строку этого обучающего файла, где первым термином является категория, к которой принадлежит элемент. Например, учебный файл будет выглядеть так
Ham новая версия Mahout выпущен
спам купить виагру сейчас особая скидка
Вместе с Mahout поставляется небольшая программа для преобразования каталогов документов в этот формат. Каталог должен иметь внутренний каталог для каждой категории. В нашем случае мы собираемся разделить наш набор тестов на два каталога, один для тестирования, а другой для обучения (оба в <mahout_home> / examples / bin / work / spam, где <mahout home> — это место, где вы распаковали дистрибутив mahout) ,
В каждом из них мы собираемся поместить каталог спама и каталог ветчины.
контрольная работа
поезд
Мы вручную берем около 80% ветчины и помещаем ее в поезд / ветчину, остальные в тест / ветчину, и то же самое со спамом в поезд / спам и тест / ветчина (подготовить тестовый набор никогда не было проще! !!)
Далее мы собираемся подготовить поезд и проверить файлы с помощью следующих команд
1
2
|
bin /mahout prepare20newsgroups -p examples /bin/work/spam/train -o examples /bin/work/spam/prepared-train -a org.apache.mahout.vectorizer.DefaultAnalyzer -c UTF-8
bin /mahout prepare20newsgroups -p examples /bin/work/spam/test -o examples /bin/work/spam/prepared-test -a org.apache.mahout.vectorizer.DefaultAnalyzer -c UTF-8
|
По умолчанию используется анализатор Lucene (на самом деле он заключен в класс mahout)
Мы собираемся тренировать классификатор. Тренировка классификатора подразумевает заполнение mahout файлом поезда и позволяет ему строить внутренние структуры с данными (да, как вы можете понять, используя мое слово «internal», я понятия не имею, как работают эти структуры).
1
|
bin /mahout trainclassifier -i examples /bin/work/spam/prepared-train -o examples /bin/work/spam/bayes-model - type bayes -ng 1 - source hdfs
|
Модель создается в каталоге модели Байеса, алгоритм Байеса (наивный Байес), мы используем распределенную файловую систему Hadoop (мы не сообщаем об этом команде, когда вы не используете распределенную базу данных, такую как Hbase), и нг это нграммы для использования. Нграммы — это группы слов. Давая больше нграмм вы добавляете больше контекста к каждому слову (окружающим словам) Чем больше ngram вы используете, тем лучше должны быть результаты. Мы используем 1, потому что лучшие результаты, очевидно, стоят больше времени на обработку.
Теперь мы запускаем тесты с помощью следующей команды
1
|
bin /mahout testclassifier -m examples /bin/work/spam/bayes-model -d examples /bin/work/spam/prepared-test - type bayes -ng 1 - source hdfs -method sequential
|
И через некоторое время мы получаем следующие результаты
-------------------------------------------------- -----
Правильно классифицированные экземпляры: 383 95,75%
Неверно засекреченные экземпляры: 17 4,25%
Всего классифицированных экземпляров: 400
================================================== =====
Путаница Матрица
-------------------------------------------------- -----
ab <- классифицируется как
189 11 | 200 a = спам
6 194 | 200 б = ветчина
Очень хорошие результаты !!!
Сервер для классификации спама в режиме реального времени
Но мы еще не сделали ничего отличного от примера 20newsgroup! Теперь, что мы можем сделать, если мы хотим классифицировать письма по мере их поступления. Мы собираемся создать антиспам-сервер, на который почтовый сервер будет отправлять все получаемые им письма, а наш сервер будет отвечать, если это хам или спам (применяя эту процедуру)
Сервер будет настолько простым, насколько мы можем (это всего лишь подтверждение концепции):
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
public class Antispam extends HttpServlet {
private SpamClassifier sc;
public void init() {
try {
sc = new SpamClassifier();
sc.init( new File( "bayes-model" ));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (InvalidDatastoreException e) {
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Reader reader = req.getReader();
try {
long t0 = System.currentTimeMillis();
String category = sc.classify(reader);
long t1 = System.currentTimeMillis();
resp.getWriter().print(String.format( "{\"category\":\"%s\", \"time\": %d}" , category, t1-t0));
} catch (InvalidDatastoreException e) {
e.printStackTrace();
}
}
}
|
Поскольку мы собираемся сделать очень простой пример, мы будем использовать простой сервлет. Важным классом является SpamClassifier
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
public class SpamClassifier {
private ClassifierContext context;
private Algorithm algorithm;
private Datastore datastore;
private File modelDirectory;
Analyzer analyzer;
public SpamClassifier(){
analyzer = new DefaultAnalyzer();
}
public void init(File basePath) throws FileNotFoundException, InvalidDatastoreException{
if (!basePath.isDirectory() || !basePath.canRead()){
throw new FileNotFoundException(basePath.toString());
}
modelDirectory = basePath;
algorithm = new BayesAlgorithm();
BayesParameters p = new BayesParameters();
p.set( "basePath" , modelDirectory.getAbsolutePath());
p.setGramSize( 1 );
datastore = new InMemoryBayesDatastore(p);
context = new ClassifierContext(algorithm, datastore);
context.initialize();
}
public String classify(Reader mail) throws IOException, InvalidDatastoreException {
String document[] = BayesFileFormatter.readerToDocument(analyzer, mail);
ClassifierResult result = context.classifyDocument(document, "unknown" );
return result.getLabel();
}
}
|
У вас есть хранилище данных и алгоритм. Хранилище данных представляет модель, которую вы ранее создали, обучая классификатор. Мы используем InMemoryBayesDatastore (есть также HbaseBayesDatastore, который использует базу данных Hadoop), и мы предоставляем ему базовый путь и размер ngrams. Мы используем ngrams из 1, чтобы упростить этот пример. В противном случае необходимо постобработать анализируемый текст, построив нграммы.
Алгоритм является ядром метода и является очевидным примером шаблона проектирования Стратегии. Мы используем алгоритм Байеса, но мы могли бы использовать алгоритм Cbayes, который использует дополнительный наивный алгоритм Байеса.
ClassifierContext — это интерфейс, который вы будете использовать для классификации документов.
Мы можем протестировать наш сервер с помощью curl:
curl http: // localhost: 8080 / antispam -H "Content-T-Type: text / xml" --data-binary @ ham.txt
и мы получаем
{"category": "ветчина", "время": 10}
Выводы
Как мы уже видели, процесс фильтрации спама можно разделить на две части. Автономный процесс, когда у вас есть много писем, которые уже кем-то классифицированы, и вы тренируете классификатор. И онлайн-процесс, где вы тестируете документ, чтобы классифицировать его с помощью ранее созданной модели. Модель может развиваться, вы можете добавлять больше документов с дополнительной информацией, и после выполнения автономной обработки вы обновляете сетевой сервер новой моделью. Модель может быть очень большой. Это где Hadoop выходит на сцену.
Автономный процесс можно отправить в кластер с запущенным hadoop, и с помощью тех же библиотек (Mahout!) Вы выполняете то же самое, что и алгоритмы, и быстрее получаете результаты. Конечно, алгоритмы не одинаковы, потому что они выполняются параллельно тысячами компьютеров, которые у вас наверняка есть в вашем кластере (или двух или трех компьютерах, которые у вас есть). Mahout был разработан с учетом этого. Большинство его алгоритмов были адаптированы для работы над Hadoop. Но интересно то, что они также могут работать без него в целях тестирования, или когда вы должны внедрить алгоритмы на сервер без необходимости распределенных вычислений, как, как мы делали в этом посте. Сочетание его возможностей быть пользователем в кластере и быть встроенным в приложение делает Mahout мощной библиотекой для современных приложений, использующих данные веб-масштаба.
Ссылка: Ветчина, спам и слоны (или как построить сервер фильтра спама с Mahout) от нашего партнера JCG Эммануэля Эспина в блоге emmaespina .