Классификация русского текста с помощью библиотеки Natural на NodeJS

    Преамбула


    Я никого не удивлю, если скажу, что современный человек, а, в особенности, программист, каждый день получает огромное информации. К примеру, мой RSS-клиент выдает мне в неделю около 500 статей. И, конечно же, это далеко не единственный источник информации.

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

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

    Результаты работы с Brain и Fann я показывать не хочу — я не считаю, что я обладаю достаточной экспертизой для того, чтобы судить о них. Скажу только что из коробки они меня не устроили совершенно — на моих входных данных они не давали адекватного количества правильных ответов. А вот библиотека Natural меня очень впечатлила.

    Далее я покажу как я обучал классификатор, проверял его работу и заставлял понимать русский язык.



    Входные данные


    Данные, на которых я обучал и тестировал классификатор, можно просмотреть тут. Их достаточно много для статьи, по этому я их вынес отсюда.

    Код


    'use strict';
    
    var data = require('./data');
    
    var natural = require('natural'),
      porterStemmer = natural.PorterStemmerRu,
      classifier = new natural.BayesClassifier(porterStemmer);
    
    // Даем classifier'у примеры хороших и плохих данных.
    for (var i = 0; i < data.good.length; i++) {
      classifier.addDocument(data.good[i], 'good'); 
    };
    
    for (var i = 0; i < data.bad.length; i++) {
      classifier.addDocument(data.bad[i], 'bads');
    };
    
    // Запускаем обучение на переданных текстах.
    classifier.train();
    
    
    // А теперь классифицируем тестовые тексты.
    console.log('START CLASSIFICATION');
    console.log('Test on good');
    for (var i = 0; i < data.test_good.length; i++) {
      console.log("> ",classifier.classify(data.test_good[i]));
    };
    
    console.log('Test on bad');
    for (var i = 0; i < data.test_bad.length; i++) {
      console.log("> ",classifier.classify(data.test_bad[i]));
    };
    


    Результат


    START CLASSIFICATION
    Test on good
    >  good
    >  good
    >  good
    >  good
    Test on bad
    >  bads
    >  bads
    >  bads
    >  bads
    >  good
    >  bads
    >  bads
    >  good


    Поддержка русского языка


    Для качественной классификации в Natural используется компонент «stemmer», который разбивает текст на массив из слов, удаляет бесполезные слова (так называемые stopwords) и обрезает окончания слов.

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

    var classifier = new natural.BayesClassifier(natural.PorterStemmerRu);
    


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

    Любителям экспериментов


    Я специально создал репозиторий с работающим классификатором. Установка тривиальна:

    git clone git@github.com:shuvalov-anton/classifier.git
    cd classifier
    npm i
    node app.js
    


    Дальше меняете данные в data.js на свои и смотрите результат.

    PS


    Честно говоря, у меня нет опыта классификации информации чтобы оценить результат, но результаты работы Natural меня как простого пользователя очень впечатлили. К сожалению, я не нашел какой-то более-менее серьезной документации по проекту кроме readme на github. И для того, чтобы понять как включить русский язык мне пришлось порыться в исходниках, но чего-то сверхсложного в этом не было, и, я считаю, что результат того стоил!
    Метки:
    • +17
    • 11,4k
    • 6
    Поделиться публикацией
    Похожие публикации
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 6
    • +1
      Сложное впечатление от статьи…

      С одной стороны, подразумевается нечто полезное, но оно отсутствует как продукт.
      С другой стороны, показывается как создать некий «гаджет» (не полная инструкция, кстати), но он НЕ в хабе DIY.

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

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

        Дописал абзац «Любителям экспериментов». Клонируйте репозиторий и экспериментируйте со своими данными на здоровье!
        • 0
          Спасибо.

          Теперь моя совесть чиста и прокрастинация запятнана. ;)

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

          А, кстати, вы и сами можете оформить математику в няшный интерфейс и собирать по доллару с носа.

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

          И, если помечтать, вы бы могли попробовать интегрировать, например, с фидли, а фидли бы, в конце концов, выкупил бы ваш продукт. ;)
    • НЛО прилетело и опубликовало эту надпись здесь
      • 0
        Привет! Воспользовался библиотекой из статьи — все отлично. А можно ли использовать классификацию так, чтобы она возвращала несколько подходящих результатов? Что-то типа elastic search.

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