Доброго времени суток всем. Это наш первый пост в блог стартапа «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 года мы обнаружили в сети открытое тестирование анализа систем анализа тональности на русском языке при конференции «Диалог» и решили принять в нем участие, чтобы проверить насколько наш «кустарный» подход к анализу языка в сравнении с профессиональными решениями. Это привело к нескольким циклам усовершенствований, и бессонных ночей (что есть тема отдельной статьи), но в итоге нам не только удалось подтвердить универсальность, но и занять несколько первых и вторых мест по разным дорожкам, что сделало нашу систему одной из лучших и по точности результатов.

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

Комментарии (26)


  1. Ents
    21.04.2015 17:37
    +6

    А где технические детали? Как вы определяете категории, выделяете блоки отзывов на странице?


    1. Durham Автор
      21.04.2015 17:52

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


      1. Infanty
        21.04.2015 18:22
        +2

        Добавляйте везде статистику и описание алгоритмов (теоретически как производится работа) или их применения. Это интересно и самое главное вряд ли кто то воспользуется вашей идеей. Если голова есть, то сторонний разработчик до подобного сам дойдёт, а если головы нет то кривые руки всегда всё испортят.


        1. Durham Автор
          21.04.2015 19:58

          Спасибо, будем иметь в виду


          1. ServPonomarev
            22.04.2015 11:37

            Я так понимаю, вы — номер первый в дорожках по отзывам www.dialog-21.ru/Default.aspx?DN=c9b5d5e7-1dc4-43a8-b7bf-0840c46b472b&l=Russian

            А почему не участвовали в дорожкам по твитам?

            а… нашёл ниже в комментах.


  1. Infanty
    21.04.2015 18:19

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

    image

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

    Ждём от Вас продолжений статей с более техническими подробностями.


  1. grossws
    21.04.2015 19:28

    Можно ли привести ссылки на результаты на Диалоге? Сходу не находится…


    1. Durham Автор
      21.04.2015 19:38
      +1

      Надо зайти на www.dialog-21.ru/Default.aspx?DN=c9b5d5e7-1dc4-43a8-b7bf-0840c46b472b&l=Russian затем перейти на «дорожка по анализу отзывов», там будет файл SentiRuEval_results, и там наши результаты под кодами 1_1, 1_2, и 1_3 (данные в таблицах не отсортированы по возрастанию, поэтому для удобства их надо отсортировать). Почему так, не знаю, так организаторы решили сделать. Более человеческий вид будет после конференции в мае, когда выйдет наша статья, и статья организаторов с обзором результатов.


      1. grossws
        21.04.2015 19:43
        +1

        А чем отличались сильные и слабые требования и как считались precision и recall?


        1. Durham Автор
          21.04.2015 19:57

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


  1. tolika
    21.04.2015 20:57

    Планируется ли выпуск публичной версии ПО, реализующего/демонстрирующего Ваши достижения?
    Например, в виде десктопного приложения?


    1. Durham Автор
      22.04.2015 14:20

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


      1. ServPonomarev
        22.04.2015 14:31

        будет.

        А как вы кодируете слова для обработки нейронными сетями? Векторизация? Каким методом?


        1. Durham Автор
          22.04.2015 16:24

          Пока используем ныне стандартную практику — распределенное представление слов, которое тренируется на большом текстовом корпусе. Алгоритм аналогичен тому, который описан в статье Mikolov et al, 2010


          1. Stas911
            22.04.2015 20:58

            Это word2vec или что-то другое?


            1. Durham Автор
              22.04.2015 21:30

              word2vec использует похожий, но все-таки другой алгоритм (там skip-gram модель).


              1. Xom
                06.05.2015 21:16

                В w2v тоже есть skip-gramm


                1. Durham Автор
                  07.05.2015 16:33

                  о том и речь, что word2vec это skip gram модель или CBOW, а тот алгоритм о котором идет речь — другой


  1. Xom
    06.05.2015 21:16

    @Мы добавили в программу автоматический «извлекатель» названий товаров и «присваиватель» категорий, так что теперь система сама могла «открывать» новые товары и категории товаров@ А как это можно сделать автоматически? Вы научились автоматически строить онтологию?


    1. Durham Автор
      07.05.2015 16:43

      Собственно такие системы уже давно известны, тот же NEL («never ending language learner») уже пять лет назад мог извлекать новые факты и соотношения из текста, да и до этого были подобные работы. Вопрос был о возможности применения подобной технологии в практической задаче — насколько это эффективно. Общий алгоритм состоит в том, что начиная с некой минимальной базы-затравки из разных источников извлекаются соотношения несколькими методами, и потом каждому соотношению сопоставляется вероятность того, что оно верно или ошибочно.


      1. Xom
        07.05.2015 17:47

        За ссылку спасибо, теперь понятней, о чем речь. А вы прям так как в статье сделали или все таки как то иначе? Методы вы тут описываете несколько иные. Можно в принципе просто по структуре синт. связей существительных вычислять товары — товары покупают, продают в магазинах, ремонтируют, они ломаются. Правда отель не вписывается в этот способ )


        1. Durham Автор
          08.05.2015 12:08

          Мы отталкивались от идей, которые изложены в статье про NEL, но не копировали описанную систему. Что касается отеля, то мы анализируем отзывы, и в этих текстах объект отзыва часто упоминается в сходных контексте (например, «сегодня я расскажу о моих впечатлениях о...»), что позволяет построить алгоритм, способный находить объекты отзывов как таковые.


          1. Xom
            08.05.2015 13:22

            В NELL применяется аж 4 метода, дополняющих друг друга. Вы все из них освоили — имеете код их реализации? И если сркеди прочего вы применяете w2v или то что другое — Glove? Вопрос не праздный. Кстати, конкретную задачу по API вам писать на info@meanotek.ru?


            1. Durham Автор
              08.05.2015 14:52

              Мы не копировали NELL в плане того, что мы не брали тот же CPL, SEAL и т.п. Основной принцип который мы взяли из NELL — использование нескольких источников получения одинаковой информации, которые делают некореллированные друг с другом ошибки, использование нескольких видов связанных между собой знаний, сопряженные методы обучения с обратной связью и сопоставление вероятностей выученным фактам. Но сами методы извлечения данных — другие. Причем, если говорить о reviewdot.ru конкретно, то мы учились паралелельно с тем как делали, и поэтому получилось так, что некоторые части архитектуры опираются на простые методы, вплоть до того, что считают вхождения слова «телефон» в отзывах о продукте, другие части используют semi-supervised извлечение шаблонов, вроде если <очень> ПРИЛ. <название_категории>, то добавить ПРИЛ. в список прилагательных, относящихся к категориям, после чего если встретится <очень> <известное прилагательное> — значит предположить, что X — может быть категорией. В итоге реализовано гораздо больше методов, чем четыре, но они другие, не те которые описаны в статье про NELL. Самые свежие части используют SRL на рекуррентных нейронных сетях. Сейчас мы постепенно разбираем весь получившийся «зоопарк» и оформляем в библиотеки функций, годных к употреблению в разных задачах. Более подробные описания, к сожалению, выходят за рамки одного комментария.

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

              Заявку можно оставить через форму на сайте meanotek.ru или на электронный адрес info@meanotek.ru


              1. Xom
                08.05.2015 15:14

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


                1. Durham Автор
                  08.05.2015 15:31

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

                  TF/IDF кстати не используется при извлечении данных, только в реализации функции поиска товаров.