Как мы придумывали систему анализа текстов

    Доброго времени суток всем. Это наш первый пост в блог стартапа «Meanotek», и наверное он будет больше ознакомительного характера. Чтобы не было совсем скучно читать, мы попробуем рассказать историю, о том как одна практическая задача привела нас к созданию полноценной системы «понимания» текста компьютером, и что из этого получилось.

    Мысль научить компьютер общаться на человеческом языке у меня появилась еще в школе, когда у меня дома был один из первых советских аналогов IBM PC, с языком программирования GW BASIC. Понятно, что далеко эта задумка в то время не ушла, потом ее заслонили другие более важные дела, но совершенно неожиданно она всплыла вновь спустя много лет, уже в связи с конкретной потребностью.

    Собственно идея пришла в голову во время работы над другим проектом — сайтом поиска отзывов reviewdot.ru. Идея reviewdot.ru была в следующем — пользователь вводит запрос, например «зеркальный фотоаппарат для начинающих» — и получает список ссылок на отзывы в интернете, которые касаются именно этого вопроса. Или к примеру, чтобы по запросу «что ломается в стиральной машине Indesit?” появлялись ссылки на отзыв пользователей марки Indesit, у которых что-то сломалось. Вопрос ценности данного ресурса для людей пока оставим за скобками, и поговорим немного о технической стороне реализации.

    Ясно, что чтобы искать отзывы в интернете, надо сначала эти отзывы выделить с разных сайтов. Отзывы встречаются на очень разных сайтах (сайты отзовики, интернет-магазины, индивидуальные блоги и т. п.). Классический подход к данной проблеме — загружаем страницы, выделяем нужные блоки из разметки с помощью библиотеки парсера-HTML и заносим в базу данных. Однако, выяснилось, что нашими ограниченными ресурсами так много не сделать (мы работали вдвоем в свободное от работы и отдыха время). Потому как во-первых, добавление каждого нового сайта связано с необходимостью анализа его структуры вручную и прописывания правил для извлечения данных, что не всегда бывает тривиально, даже с помощью HTML-парсера и Xpath запросов. Во-вторых, сайты имеют тенденцию менять структуру. Когда работа идет с 5-6 сайтами это еще ничего, ведь капитальный редизайн случается не так часто. Но если счет источников идет на тысячи… короче, объем усилий, необходимый на поддержку решения в работоспособном состоянии растет пропорционально числу источников. А есть еще и категории товаров, которые на каждом сайте называются по-разному, и надо их сопоставлять, и поддерживать какое-то единое дерево категорий… Короче, объем тупого монотонного труда быстро и монотонно возрастает, что делает задачу для нас неподъемной.

    Поэтому, помучившись некоторое время, мы плюнули и забили на проект, решили пойти другим путем и научить компьютер самостоятельно находить отзывы на любой веб-странице. Стандартных средств для этого не нашлось и после некоторых усилий мы сделали простой алгоритм, выделяющий текстовые блоки из веб-страниц и классифицирующий их на два типа — отзыв/не отзыв. Таким образом, программа приобрела рудиментарный интеллект, а мы избавились от зависимости затрат на поддержание системы от числа источников данных. Сколько сайтов-источников хотим, столько и добавляем, и трудозатраты при этом остаются константой. Правда при этом произошла некоторая потеря в качестве, т. к. около 15% текстов которые попадали в базу не были отзывами, и еще какой-то процент отзывов не находился вообще, но эти недостатки не шли ни в какое сравнение с достигнутой экономией усилий.

    Из чего мы сделали следующие выводы:
    • Элементы «понимания» компьютером текстов могут пригодится в самых разных и неожиданных местах, даже там, где вроде бы можно обойтись
    • В условиях ограниченных ресурсов, лучше иметь одно универсальное решение, чем много специализированных


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

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

    К примеру:
    1. Голосовой интерфейс на естественном языке в каждое мобильное приложение (а не только для избранных)
    2. Новые виды приложений, отвечающие на вопросы (тот же подбор подходящего товара по требованиям на естественном языке)
    3. Анализ сообщений электронной почты, для выявления частых проблем обращающихся, с возможностью автоматического ответа с решением типовых проблем


    Готовые API анализа текстов, как правило, не умеют «открывать» новые концепции в заданной предметной области и использовать их для улучшения качества анализа. Вообще до опыта с reviewdot, мы думали, что подобные самосовершенствующиеся системы недостаточно хорошо работают, чтобы быть практически полезными, но тут мы убедились совсем в обратном.

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

    Клиент (часто разработчик ПО) имеет задачу или идею нового приложения → он обращается к нам, мы бесплатно делаем поддержку нужной именно ему функции и предоставляем ее через web-API или оффлайн → если приложение имеет успех, то разработчик получает доход и оплачивает из него доступ к веб-API.

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

    В осенью 2014 года мы обнаружили в сети открытое тестирование анализа систем анализа тональности на русском языке при конференции «Диалог» и решили принять в нем участие, чтобы проверить насколько наш «кустарный» подход к анализу языка в сравнении с профессиональными решениями. Это привело к нескольким циклам усовершенствований, и бессонных ночей (что есть тема отдельной статьи), но в итоге нам не только удалось подтвердить универсальность, но и занять несколько первых и вторых мест по разным дорожкам, что сделало нашу систему одной из лучших и по точности результатов.

    Таким образом, идея наконец-то созрела, и мы начали работать, пока в тестовом режиме, выискивая людей с интересными задачами или проектами приложений, и предлагая им сделать анализатор. Пока в разработке только два таких проекта, но есть надежда, что появятся и другие.
    MeanoTek 24,00
    Разработка систем анализа и генерации текстов
    Поделиться публикацией
    Комментарии 35
    • +6
      А где технические детали? Как вы определяете категории, выделяете блоки отзывов на странице?
      • 0
        Спасибо за комментарий. Всегда сложно выдержать баланс между необходимостью не потерять общую картину из-за чрезмерных деталей и при этом не написать совсем абстрактно и ни о чем. Чтобы не перегрузить публикацию, мы решили вынести детали в отдельные статьи, так как тут вовлечено несколько алгоритмов, которые заслуживают отдельного разговора.
        • +2
          Добавляйте везде статистику и описание алгоритмов (теоретически как производится работа) или их применения. Это интересно и самое главное вряд ли кто то воспользуется вашей идеей. Если голова есть, то сторонний разработчик до подобного сам дойдёт, а если головы нет то кривые руки всегда всё испортят.
    • 0
      Я зашёл с другой стороны: необходимо понять текст, понимая текст можно отвечать на вопросы, отвечая на вопросы можно получить информационную суть текста, а имея её можно не просто отвечать на вопросы или делать рерайт текста, но и делать выжимку из текста например сокращая новости или получить «войну и мир» вкратце. Интерфейс голосовых команд можно использовать и сторонний. Не спеша за 7 лет свободного времени я получил такую статистику:

      image

      До анализа на основе «войны и мира» пока не добрался, тестирую на небольших текстах — новостные заметки и рецепты блюд.

      Ждём от Вас продолжений статей с более техническими подробностями.
      • 0
        Можно ли привести ссылки на результаты на Диалоге? Сходу не находится…
        • +1
          Надо зайти на www.dialog-21.ru/Default.aspx?DN=c9b5d5e7-1dc4-43a8-b7bf-0840c46b472b&l=Russian затем перейти на «дорожка по анализу отзывов», там будет файл SentiRuEval_results, и там наши результаты под кодами 1_1, 1_2, и 1_3 (данные в таблицах не отсортированы по возрастанию, поэтому для удобства их надо отсортировать). Почему так, не знаю, так организаторы решили сделать. Более человеческий вид будет после конференции в мае, когда выйдет наша статья, и статья организаторов с обзором результатов.
          • +1
            А чем отличались сильные и слабые требования и как считались precision и recall?
            • 0
              В задаче на выделение аспектных терминов «сильные требования» по определению организаторов — засчитывается верным только точное совпадение аспектного термина с выделенным человеком, «слабые требования» — метрики считаются на основании процента перекрывания выделенного программой и человеком термина. На самом деле ничего «слабого» тут нет, т.к. границы терминов плохо совпадают при определении их разными людьми. Precision отношение числа верно выделенных терминов (совпадающих с ручной разметкой человеком) к общему числу терминов выделенных программой, Recall — отношение числа выделенных программой терминов, к числу терминов, выделенных человеком.
        • 0
          Планируется ли выпуск публичной версии ПО, реализующего/демонстрирующего Ваши достижения?
          Например, в виде десктопного приложения?
          • 0
            Честно говоря, сложно представить, как должно выглядеть такое приложение и какую функцию выполнять. У нас есть ядро системы анализа языка, которое обучается различным задачам, но для каждой задачи нужно делать свой frontend для пользователя. Если выбрать какую-то определенную задачу, это можно сделать, но при этом велика вероятность сделать никому не нужное приложение. Поэтому мы решили предоставлять функции ядра системы для интеграции в другие приложения. Думаю, в лучшем случае можно выпустить библиотеку функций для разработчиков, но будет ли к ней интерес пока не знаю.
            • 0
              будет.

              А как вы кодируете слова для обработки нейронными сетями? Векторизация? Каким методом?
              • 0
                Пока используем ныне стандартную практику — распределенное представление слов, которое тренируется на большом текстовом корпусе. Алгоритм аналогичен тому, который описан в статье Mikolov et al, 2010
                • 0
                  Это word2vec или что-то другое?
                  • 0
                    word2vec использует похожий, но все-таки другой алгоритм (там skip-gram модель).
                    • 0
                      В w2v тоже есть skip-gramm
                      • 0
                        о том и речь, что word2vec это skip gram модель или CBOW, а тот алгоритм о котором идет речь — другой
                  • 0
                    там вроде пишут ". Input vector x(t) represents word in time t encoded using 1-of-N coding and previous context layer — size of vector x is equal to size of vocabulary V (this can be in practice 30 000 − 200 000) plus size of context layer. " то есть, насколько я понимаю, входной вектор — это, не считая рекурсивно добавляемого контекста, по сути, весь словарь понимаемых слов, по одному входу на каждое возможное слово. Да?

                    То есть, если словарь корпуса получается на сто тыщ слов, то у входного вектора будет сто тыщ элементов, лишь один из которых будет единичкой при подаче конкретного слова, остальные — нули? Вектор размерностью сто тыщ?
                    • +2
                      Это вектор, который на вход RNNLM поступает, да он размерностью в словарь. RNNLM или word2vec или подобный алгоритм обучается на очень большом корпусе (десятки и сотни миллионов слов) и формирует новое компактное представление слов, в форме весов, ассоциированных с каждым разрядом входного вектора. Это компактное представление обладает тем свойством, что вектора слов, похожих по смыслу, находятся ближе друг к другу. См. также статью Yao et al, о том как это сделать
            • 0
              @Мы добавили в программу автоматический «извлекатель» названий товаров и «присваиватель» категорий, так что теперь система сама могла «открывать» новые товары и категории товаров@ А как это можно сделать автоматически? Вы научились автоматически строить онтологию?
              • 0
                Собственно такие системы уже давно известны, тот же NEL («never ending language learner») уже пять лет назад мог извлекать новые факты и соотношения из текста, да и до этого были подобные работы. Вопрос был о возможности применения подобной технологии в практической задаче — насколько это эффективно. Общий алгоритм состоит в том, что начиная с некой минимальной базы-затравки из разных источников извлекаются соотношения несколькими методами, и потом каждому соотношению сопоставляется вероятность того, что оно верно или ошибочно.
                • 0
                  За ссылку спасибо, теперь понятней, о чем речь. А вы прям так как в статье сделали или все таки как то иначе? Методы вы тут описываете несколько иные. Можно в принципе просто по структуре синт. связей существительных вычислять товары — товары покупают, продают в магазинах, ремонтируют, они ломаются. Правда отель не вписывается в этот способ )

                  • 0
                    Мы отталкивались от идей, которые изложены в статье про NEL, но не копировали описанную систему. Что касается отеля, то мы анализируем отзывы, и в этих текстах объект отзыва часто упоминается в сходных контексте (например, «сегодня я расскажу о моих впечатлениях о...»), что позволяет построить алгоритм, способный находить объекты отзывов как таковые.
                    • 0
                      В NELL применяется аж 4 метода, дополняющих друг друга. Вы все из них освоили — имеете код их реализации? И если сркеди прочего вы применяете w2v или то что другое — Glove? Вопрос не праздный. Кстати, конкретную задачу по API вам писать на info@meanotek.ru?
                      • 0
                        Мы не копировали NELL в плане того, что мы не брали тот же CPL, SEAL и т.п. Основной принцип который мы взяли из NELL — использование нескольких источников получения одинаковой информации, которые делают некореллированные друг с другом ошибки, использование нескольких видов связанных между собой знаний, сопряженные методы обучения с обратной связью и сопоставление вероятностей выученным фактам. Но сами методы извлечения данных — другие. Причем, если говорить о reviewdot.ru конкретно, то мы учились паралелельно с тем как делали, и поэтому получилось так, что некоторые части архитектуры опираются на простые методы, вплоть до того, что считают вхождения слова «телефон» в отзывах о продукте, другие части используют semi-supervised извлечение шаблонов, вроде если <очень> ПРИЛ. <название_категории>, то добавить ПРИЛ. в список прилагательных, относящихся к категориям, после чего если встретится <очень> <известное прилагательное> — значит предположить, что X — может быть категорией. В итоге реализовано гораздо больше методов, чем четыре, но они другие, не те которые описаны в статье про NELL. Самые свежие части используют SRL на рекуррентных нейронных сетях. Сейчас мы постепенно разбираем весь получившийся «зоопарк» и оформляем в библиотеки функций, годных к употреблению в разных задачах. Более подробные описания, к сожалению, выходят за рамки одного комментария.

                        Что касается word2vec, GloVe и т.п. — я дал в первом комментарии точную ссылку на описание метода, который использовался. Это RNNLM-модель, на основании которой впоследствии был придуман word2vec. Она работает медленнее, чем word2vec, но делает по сути похожее дело, плюс создает модель языка, которая нам тоже была нужна для работы. Сейчас мы экспериментируем с разными вариантами, в т.ч. c GloVe.

                        Заявку можно оставить через форму на сайте meanotek.ru или на электронный адрес info@meanotek.ru
                        • 0
                          Так все таки вы используете какие-то rules на синтаксических связях. И TF-IDF, насколько я понял, и «мягкие» шаблоны. Я почему и задавал вопросы, что думал, как это все вы чисто на нейронных (матрицах) решили эту задачу? Но правила вы применяете только для поиска схожих сущностей (товаров) — это интересно.
                          • 0
                            Нет пока целиком у нас нет решения всего процесса на нейронных сетях, но есть цель такое решение получить. Многие компоненты мы смогли заменить нейронными сетями, и наверное, если бы начинали сейчас сначала, то могли бы реализовать без использования шаблонов, правил и тому подобного, так как практика многому научила, и к тому же теория в мире шагнула сильно вперед. Но reviewdot вряд ли будем переделывать, правда сейчас обсуждаем другой похожий проект.

                            TF/IDF кстати не используется при извлечении данных, только в реализации функции поиска товаров.
              • 0
                Приходила мысль «извлечения фактов» из автомобильных форумов, т.е. например «ломается коробка», «дорогая в обслуживании» и т.д. Насколько реалистична такая задача?

                И еще нечто похожее есть в яндекс.маркет(колонки достоинства/недостатки для товаров), но там возможно задача проще так как можно просто смотреть частоту вхождения слов.
                • 0
                  Приходила мысль «извлечения фактов» из автомобильных форумов, т.е. например «ломается коробка», «дорогая в обслуживании» и т.д. Насколько реалистична такая задача?


                  Это называется аспектный анализ тональности — вот результаты.
                  • 0
                    Тут многогранная тема на самом деле. С одной стороны да, задача вроде как решена в рамках аспектного анализа (у нас кстати по SentiRuEval-2015 первый результат по извлечению всех аспектных терминов, относящихся к автомобилям). Но, классический аспектный анализ, он работает в несколько этапов —

                    1. Извлечь термины, вроде «коробка», «двигатель».
                    2. Оценить тональность, т.е. положительное упоминание или отрицательное
                    3. Разбить все термины на категории, вроде «Управляемость», «Надежность» и т.п.
                    4. Построить общую статистику — Т.е.: Надежность — 70%, Внешний вид — 85%, Управляемость — 65%.

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

                    Другое дело извлечение фактов. Например, «Ломается коробка», «туго переключаются передачи», «через 50 000 км коробка подлежит замене», это не то же самое, но в классическом варианте все это станет просто одним: «недостатки: коробка передач». А к чему недостатки, почему они — кто знает? Причем проблема даже не в том, как эти знания из текста извлечь, проблема в том, как имея эти знания сделать что-то полезное для пользователя. В теме про генерацию текстов у нас была дискуссия об этом, видно, что пока решение не очевидно. Вот и получается, что вроде дело полезное, а применить невозможно.
                    • 0
                      А термины извлекаются автоматически или они заранее заданы вручную?

                      И еще спрошу пожалуй тут, приходила на ум еще такая задача, допустим есть у нас рекомендательная система для книг типа books.imhonet.ru и я так понимаю она работает как просто рекомендательная система т.е. имеется некая матрица пользователи-товары, а в ячейках оценки, так вот нельзя ли рекомендовать книги на основе их контента(их текста)?
                      • 0
                        Есть разные способы. Обычно делается какая-то обучающая выборка, предложений, где выделены нужные термины, на основании чего создается классификатор, который умеет выделять термины сам, при этом обобщая до определенной степени понятие термина на новые случаи, которых не было обучающих примерах. (последовательность шагов мы расписывали например здесь). Есть лингвистические алгоритмы без обучающих выборок, они работают обычно хуже, но требуют меньше ручного труда вначале.

                        Что касается книг. Как сделано на imhonet я точно не знаю. Современные системы обычно используют всякие признаки, в том числе и коллаборативный фильтр (оценки других пользователей), информацию о жанре, авторе, информацию о вкусах пользователя и т.п. Есть алгоритмы рекомендации книг и по их тексту, но они несколько хуже работают, чем гибридные системы, за исключением правда ситуации, когда у нас много новых книг, которые мало кто читал и соответственно поставил оценки. То есть, если мы хотим рекомендовать книги новых авторов, различные рассказы, которые выложены в свободный доступ, а также произведения с малой читательской аудиторией, то рекомендатор на базе контента конечно вне конкуренции, но когда мы рекомендуем популярные книги известных авторов, факт их известности играет более существенную роль нежели содержание.

                        Ну и с точки зрения пользы для литературы рекомендация по контенту была бы лучше. Просто потому, что не зависела бы от «именитости» автора, и позволила бы начинающим авторам найти свою аудиторию. Но польза для литературы обычно мало кого заботит.

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

                          И да какие алгоритмы используются в таких задачах? Как такая задача называется по английски?
                          Ну понятное дело что можно побить текст на слова, потом (опционально) стеммером привести их в нормальную форму, сделать мешок слов и в итоге получить для каждого текста бинарный вектор длины N, потом еще и спроецировать каким нибудь нелинейным методом в пространство более низкой размерности при условии, чтобы тексты одного автора были расположены близко в одном кластере, а кластеры разных писателей разнесены.
                          • 0
                            Посмотрите, например, Exploiting FrameNet for Content-Based Book
                            Recommendation
                            . Вообще, то что вы описываете, это baseline для таких задач, но довольно хороший, а использовать можно все что наработано в области классификации текстов (мы немного об этом писали здесь), и сопоставления текстов (text matching), а это довольно много всего и явно в рамках комментария не охватить. На мой взгляд интересны методы, которые пытаются учитывать порядок слов, и даже, в какой-то степени содержание истории, которая рассказывается в книге.

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                  Самое читаемое