Text Mining Framework (Java)

    Что это и для кого (вместо вступления)

    В данной статье я бы хотел рассказать о небольших результатах своей научной деятельности в сфере Text Mining. Этими самыми «результатами» стал небольшой FrameWork, который, пока еще, и до либы то не очень дотягивает, но мы растем =). Данный проект — реализация на практике некоторых, разработанных мною, теоретических положений. Как следствие этого я представляю возможности, которыми он может потенциально обладать в конце внедрения всех идей. Названо сее творение: «Text Mining FrameWork»(TextMF). Давайте в кратце рассмотрим, что именно будет позволять TextMF в своей первой финальной версии и что работает уже сейчас.

    Должно быть в финальной версии:

    • Статистический анализ текста;
    • Поиск всех слов и словоформ каждого слова в тексте;
    • Ранжирование слов по весу в тексте;
    • Поиск субъектов в тексте, о которых идет речь;
    • Связи между субъектами в тексте (прямые и не прямые связи);
    • Реферирование текста;
    • Определение темы текста;
    • Обучение языку;
    • Организация взаимодействия с пользователем по средствам общения (чата).

    Уже реализовано (доступно частично или проходит тестирование):

    • Статистический анализ текста (пока реализовано очень частично);
    • Поиск всех слов и словоформ в тексте;
    • Сортировка слов по их весу в данном тексте;
    • Поиск персон в тексте;
    • Определение темы текста (идет тестирование и юстировка формул).

    Зачем еще одна библиотека по обработке текста?

    Дело в том, что цель данного проекта не создать инструмент, используя который можно реализовать какой либо алгоритм обработки текста (как например Python NLTK и схожие), а дать возможность использовать уже готовые алгоритмы. А заодно и апробировть на практике свой собственный алгоритм. Т.е. это не еще один статистический анализатор или набор контейнеров оптимизированных под работу с текстовыми данными. Нет! Это набор эвристик, которые будут работать из коробки, не нуждаясь в дополнительных знаниях. 

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

    Явки и пароли

    Проект распространяется через репозиторий BitBucket.

    Клоните его себе и подключаете к своему проекту =) Все предельно просто. В скором времени будут доступны сборки в виде подключаемого jar.

    Пример использования

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

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

    // Открываем и парсим текстовый файл, который лежит по адресу TEXT_FILE_NAME
    Text text = new Text(TEXT_FILE_NAME); 
    
    // Получаем список слов отранжированных по весу
    List<Word> words = text.getWords();
    
    // Получаем тему текста
    List<Word> theme = text.getThem();
    
    // Получаем первое слово в списке слов
    Word word = words.get(0);
    
    // Получаем лист всех словоформ
    List<String> wordForms =word.getWordForms();
    
    // Получаем количество вхождений слова в текст
    long count = word.getCount();
    
    // Получаем все персоны, которые встречаются в тексте
    List<Word> objects = text.getObjects();
    
    // Смотрим вес слова
    double weight = text.getWordWeight(word);
    


    Повторюсь, получение темы — довольно долгая процедура, так что вызывая данный метод будьте осторожны;) Само собой будет реализован и асинхронный метод получения темы, но позже. Так же ОЧЕНЬ важно отметить, что качество работы методов растет в зависимости от того, какого размера текст подан на вход. Чем больше информации тем, как правило, больше возможности выучить язык. Однако и время открытия файлов существенно возрастает, при увеличении размеров содержимого. 

    Небольшая UI-программа 

    Для наглядной демонстрации некоторых функций программы, моим коллегой по имени Андрей, был на скорую руку написан небольшой UI клиент. На текущей стадии он носит просто ознакомительный характер, так как иногда удобнее воспользоваться им. Написан он на Java FX, и пока не распространяется в виде отдельного jar файла. Для того, что бы его «пощупать», нужно его собрать =(.

    Главное окно программы:



    1) Меню выбора текста для обработки;
    2) Список выбранных файлов;
    3) Результаты работы:
             a) слово встречаемое в тексте;
             b) вес слова в тексте;
    с) количество повторений в тексте
    4) Поле для вывода темы текста;
    5) Список словоформ.

    Давайте посмотрим, что мы можем узнать, используя нашу программу для этого текста: Владельцам «Волг» и «Москвичей» дадут еще один год:



    Поиск темы осуществлялся около минуты (долго, согласен). При выборе какого либо отдельного слова, можно посмотреть его словоформы:



    или вот:



    А теперь попробуем еще один текст: «Пришельцы похитили семью украинцев и рассказали о будущем землян!», наверное один из самых «желтых» текстов =):



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

    нам нужна Ваша помощь

    Само собой, нам очень и очень необходима Ваша помощь! Тасков очень много, а проект то бесплатный. Задачи начинаются от самых простых: заниматься сайтом, писать примеры, документировать код, до самых хардкорных: помогать в оптимизации мат. аппарата и уточнять его. Сейчас, например, неплохо бы было кому-то взять на себя вопрос расширения входных форматов и сделать нечто большее, нежели просто текстовый файл. Так же очень важна помощь в тестировании. У проекта есть домен: www.textmf.com, однако там пусто, и я был бы очень рад, если кто-то помог это исправить =)

    По любым предложениям сотрудничества прошу обращаться сюда: Viacheslav@b0noI.com

    Ближайшие планы

    Из того, что будет в ближайшее время(думаю в пределах месяца-двух) с проектом:

    • добавим сборку jar файла;
    • проект будет разделен на ядро и UI, т.е. добавится еще один репозиторий;
    • начнется реализация долгосрочной памяти;
    • анализ связей между персонами;
    • появится возможность реферирования текста;
    • создание самодостаточного jar с UI. 


    Далекие планы

    Сейчас TextMF стал полуфиналистом проекта www.ukrinnovation.com. Так что есть, хоть и маленький, но все же шанс получить инвестиции на развитие.

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

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

    Авторы TextMF:
    Ваш покорный слуга Вячеслав В Ковалевский и
    разработчик UI Андрей Прищепа (vinglfm@gmail.com)
    Share post

    Comments 39

      +2
      а расскажите как вы делаете поиск персон в тексте?
        0
        Поиск персон довольно банален, пока что. Ищу слова которые имеют большую первую букву. Само собой с поправкой на первые слова в предложение и на вероятность опечатки (последние пока не вошло в публичный релиз).
          +2
          Хорошо, что вы обрабатываете не немецкий язык!:)
          Но проблемы будут и для русского. Ведь у нас с большой первой буквы пишутся почти все named entities, так что с таким методом (если я правильно вас понял) точность будет не очень. Если делаете поиск персон (да и вообще NER), лучше сразу обзавестись тестовым корпусом и отслеживать качество работы модуля.
            0
            Просто эта функция пока просто обозначена, как только доведу до желаемого качества тему и ранжирование веса слов и анализ словоформ то займусь сразу же поиском персон в тексте. К сожалению реализованный, пока что, подход поиска персон действительно оставляет желать лучшего.
        +1
        А как делается определение темы текста, не расскажете в двух словах?
          0
          Если коротко то берется два слова с максимальным весом которые не имеют прямой связи и идет поиск пути с максимальным значением специальной функции. Т.е. есть функция которая принимает на вход маршрут по графу связей и возвращает его вес для данного текста, задача лишь найти экстремумы этой функции. Само собой эта задача не решаемая в реальном времени ибо требует полного перебора всех маршрутов, так что применяю разные эвристики.
          –28
          Почему была выбрана именно джава? Она же известна как один самых медленных языков и глючных языков. соснули.рф/
            +1
            Смотря как готовить джаву — в банковской индустрии это стандарт де-факто, все работает быстро, а требования в банках жесткие, идет борьба за каждую микросекунду.
            Да, кстати, почему глючная-то? :)
              +1
              К слову сказать изначально разработка была на Qt (C++) но именно из-за того что на С++ приходилось много времени уделять оптимизации ресурсов было решено перейти на более высокий язык где больше внимания можно уделить оптимизации именно алгоритмов.
              +5
              Из интереса скачал, скомпилировал. Сразу вопрос — зачем тесты запихали в src?
              Ладно, написал запускалку
                      Text text = new Text("book.txt"); // тестовый файл из комплекта
                      List<Word> words = text.getWords();
              

              И сразу тыща мульонов
              model.NoContentException: Word Word(String word): word == null || word.length() < MINIMUM_WORD_LENGTH

              При попытке распарсить другие тексты выходит
              Exception in thread «main» java.lang.ArithmeticException: / by zero
              at model.memory.short_time.Text.getConnectionLevelBetweenWords(Text.java:114)


              При беглом просмотре кода обнаружилось что разработчики бсытро пчетатают: переменные с именами abstractionLeve, lengthDifferens, getSentansesCount, WordCompratorByWeight, SIMPL, getAbstractoinLevel
              Есть и архитектурные непонятки — внезапно метод Word.equals меняет состояние объекта Word

              Все очень сыро, еще пилить и пилить.
                0
                Огромное спасибо, с Exception in thread «main» java.lang.ArithmeticException: / by zero сейчас разбираюсь как раз. model.NoContentException действительно часто падает когда нарывается на слово которое он не может (не должен) обработать
                  0
                  Все действительно пока сыровато. Однако этот пост помог найти откликнувшихся, так что изменения уже не за горами.
                  +2
                  То, что конструктору надо вскармливать тхт файлы — это не правильно. Раз он работает с текстом, то String. А вот логику перевода входящих данных в стринг надо вынести в отдельный модуль.
                    0
                    Как раз планировал добавить более общий который принимает на вход BufferedReader
                    +2
                    Если
                    // Получаем количество вхождений слова в текст
                    long count = word.getCount();
                    

                    то почему
                    // Смотрим вес слова
                    double weight = text.getWordWeight(word);
                    

                    а не
                    // Смотрим вес слова
                    double weight = word.getWeight();
                    

                    Странный API, вот к чему я. Симметрии нет.
                      +1
                      Потому что вес слова зависит от текста в котором оно используется, если текстов несколько и в дальнейшем будет долгосрочная память то и слово может быть использовано в нескольких текстах. Метод показывает вес слова в конкретном тексте а не вообще абстрактный вес слова
                      +4
                      А чем не устроили широкоизвестные фреймворки по DataMining типа:

                      WEKA
                      Gate
                      MinorThird

                      Они уже имеют все то, что вы хотите иметь в финальной версии, весьма хорошо отлажены, много кем используются и имеют хорошую документацию?
                        –1
                        Хочу на практике реализовать некоторые идеи которые у меня есть только в теории, пока. Т.е. это для меня не просто реализация библиотеки а получение данных для моей кандидатской. Более того, наличие других подобных FrameWork-ов дает возможность провести качественное сравнение после того как реализация моего TextMF достигнет финала
                          +1
                          Перечисленные библиотеки это что-то вроде Matlab, только для DataMining области.
                          Т.е. они содержать в себе много готовых реализаций из которых можно быстро собрать и попробовать любую идею.
                            –1
                            Мне как человеку который часто реализует разные идеи очень полезны указанные Вами WEAK/Gate/MinorThird, я сейчас как раз смотрю на Gate. Сам же использую Python NLTK для апробации идей на практике.

                            Но (может я еще не рассмотрел хорошо эти библиотеки и ошибаюсь), в том виде в котором они есть, они подходя мне, как тому кто реализует идею, но не тому кому нужна именно готовая идея и реализация. TextMF это FrameWork где будет конкретная реализация одной-двух идей, что, само собой делает его куда менее гибким, но ведь и и цель не такая. TextMF позволяет программисту которому нужно готовое решение, а не инструмент создания этого решения.
                              +2
                              И всё-таки та же самая задача решается путем написания ресурсов под какую-нибудь платформу (хотя бы и гейт, хотя машинное обучение мне там не очень нравится) и встраивания их в свою систему. Так экономится масса усилий, кроме того, ваш продукт будет совместим с другими продуктами, опирающимися на ту же платформу.
                              На мой взгляд, хотя в плане экзерсиса написать что-то своё всегда полезно, в промышленном отношении лучше всё-таки держаться поближе к большим платформам и стандартам и изобретать своё только в крайних случаях.
                                –1
                                Я думаю что рано или поздно использование каких либо сторонних решений однозначно будет, это лишь вопрос времени, пока что еще рано говорить об этом шаге. Некоторые вещи хочется реализовать самостоятельно просто для повышения экспы и, быть может, в дальнейшем, такие части будут просто заменены на сторонние аналоги.
                          0
                          А как у них с русским языком? Тот же Gate вроде с русским плохо дружит?
                        +4
                        Хотелось бы увидеть сравнение вашего ПО с аналогами — вы проводили такой анализ?
                          –1
                          Сравнение небольшое есть, но полноценное сравнение проведу после первого релиза и оформлю как новую отдельную статью.
                          +1
                          Может стоит посмотреть в сторону solr? Вы добывайте исходный текст как хотите, анализ либо штатный, либо рассширяете своими классами. А вот поиск уже быстрый и грамотно индексированный. Solr очень гибкий, подойдет под любую вашу идею.

                          Вся суть анализа текста — скорость поиска при очень больших размерах текста. И для практического использования, время отводиться в миллисекундах.
                            0
                            Практически все что делает solr мне нужно будет кастомизировть, за исключением полнотекстного поиска (который я и не делаю у себя). А это значит что прироста КПД будет мало (если вообще будет), так как алгоритм останется тот же по большей части. Хотя я сегодня попробую более пристально взглянуть на solr, быть может я сейчас ошибаюсь
                              0
                              Solr это универсальный движок для хранения и поиска в индексе. Индекс — это набор термов + их аттрибуты + позиции в тексте и много что еще. И все это еще и не плохо расширяется. Перед запуском Solr собирается из отдельных плагинов/классов, этакий контейнер логики. Плагины преабразуют исходные данные, будь то текст, гео-позиции или что либо еще, в набор индексируемых термов и дополнительные данные. Поиск — это анализ запроса (схож с анализом исходного текста), выделение термов для поиска, собственно сам поиск документов по термам, пост-анализ результатов если нужен.

                              Вы реализуете любые ваши алгоритмы data mining'a кака плагин к solr. А вот грамотный и быстрый поиск raw terms при минимальных затратах к памяти — это уже задача solr. А так, вы сейчас пытаетесь решить две независимых задачи в одном продукте, фокусируясь на одном (mining) и забивая на другой (поиск, у вас он медленный).
                                0
                                Я думаю мне нужно все это опробовать что бы корректно прокомментировать ситуацию. У меня одна из проблем эта метод определения равенства при поиске терма. Быть может Вы знаете, это можно кастомизировать в Solar? Спасибо
                                  0
                                  У меня одна из проблем эта метод определения равенства при поиске терма.

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

                                  Почитайте это. Затем гляньте в код/javadoc для каждого фильтра. Вы увидите, что никакой магии нет. К примеру solr.EdgeNGramFilterFactory для каждого входящего терма генерит все префиксы как новые термы («тест» => «т», «те», «тес», «тест»), что позоволяет искать по префиксу. Да, это работает быстро. Да, это не стоит использовать для строк, но, к примеру хорошо идет для поиска в деревьях.
                                    0
                                    Спасибо, сейчас почитаю
                            0
                            Скажите, сейчас уже есть где-то в свободном доступе решения для поиска субъектов в тексте, о которых идет речь? Для русского языка.
                              0
                              Если на уровне FrameWork-а то эта функция у TextMF уже работает и можно использовать для, практически любого языка, и русского в том числе. А если вопрос о UI то данная функция будет реализована в следующей версии. Так же если речь идет о UI то могу порекомендовать мою программу Web Private Detective. Она старая, написана на Qt и под Windows не самая актуальная версия. Зато умеет строить отчеты в HTML и искать не просто персоны в тексте но и связи между ними. Переписанный алгоритм сейчас я портирую в свой TextMF и, как уже сказал, частично оно готово.
                              0
                              Ой, ошибся формой. Модератор, пожалуйста удали этот коммент.
                                +1
                                Apache OpenNLP, как и отдельные библиотеки из того же Lucene, не смотрели?
                                Имхо: helloworld проект который пишут ради развликухи и опыта с вероятностью «взлететь» чуть больше нуля. Я вам очень советую не переизобретать велосипед а посмотреть что есть в Lucene и OpenNLP. Делайте лучше как отдельную библиотеку которая будет способна работать вместе с Lucene или OpenNLP или чем-то другим. И пользы для людей будет больше, и вы посмотрите на каноническую реализацию api и мат методов. В конце-концов у вас появится возможность сравнить как сделали вы и «они», в 10 раз больше опыта получите и +1 при устройстве на работу связанную с поиском и Lucene, который сейчас, к слову, очень популярен.
                                  0
                                  Вы во многом правы, однако пока что выбран путь именно создание в некотором роде «велосипеда». В дальнейшем вполне вероятно начну работать над совместимостью или интеграцией с другими решениями.
                                  +3
                                  Добавил TextMF в каталог NLPub. Пожалуйста, проверьте корректность указания сведений.

                                  Есть несколько вопросов-пожеланий.

                                  Во-первых, почему именно Bitbucket, а не GitHub? Последний гораздо удобнее и популярнее. Во-вторых, под какой лицензией распространяется TextMF? Не обнаружил такой информации. В-третьих, имеется ли возможность её использования в сторонних приложениях? В-четвёртых, у вас в репозитории слишком много автогенерируемых файлов, логов, и внешних jar-файлов, которые вполне можно исключить средствами используемой SCM. В-пятых, почему бы не использовать Maven вместо Ant? Он гораздо более лучше™ одевается. В-шестых, мне кажется, что более правильно писать Topic Detection, чем Theme Searching. В-седьмых, вы можете привязать страницу вашего репозитория на Bitbucket к имеющемуся домену. Разумеется, на GitHub вы можете сделать так же.

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

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

                                    И спасибо огромное за поздравления!

                                  Only users with full accounts can post comments. Log in, please.