Назад в блог

Анализ тональности Twitter с помощью Spark

Анализ тональности Twitter с помощью Spark

В нашем предыдущем посте, я разработал способ извлечения данных Twitter в реальном времени с помощью Apache Flume. На данный момент я получил много данных из Twitter. Поэтому я хотел бы проанализировать их и найти в них некоторые тенденции. Чтобы выполнить анализ тональности данных Twitter, я собираюсь использовать еще один инструмент Big Data, Apache Spark.

Согласно Hortonworks, “Apache Spark — это быстрый механизм обработки данных в оперативной памяти с элегантными и выразительными API для разработки, позволяющий специалистам по данным эффективно выполнять потоковую передачу, машинное обучение или SQL-нагрузки, требующие быстрого итеративного доступа к наборам данных. Благодаря запуску Spark на Apache Hadoop YARN разработчики во всем мире теперь могут создавать приложения, использующие возможности Spark, получать аналитическую информацию и обогащать свои рабочие нагрузки в области анализа данных в рамках единого общего набора данных в Hadoop.”

Программу на Spark можно написать на JAVA, Scala, Python или R. В данном случае мы будем использовать JAVA вместе с Maven. Кроме того, Spark поставляется как в дистрибутиве HDP, так и в Cloudera. В настоящее время используется версия Spark 2.

Чтобы выполнить анализ тональности с помощью Spark, я создаю новый проект Maven. Я называю его Twitter Sentiment Analyzer’. Далее я создаю класс “TwitterDataFlow.java”, в котором реализую все необходимые методы.

Language Tool: Исправление орфографии

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

Я собираюсь сделать это, создав новый статический метод с именем ‘CorrectSpell’. Кроме того, я буду использовать LanguageTool для проверки орфографии и ее исправления.

Согласно LanguageTool’s GIT, “LanguageTool — это программное обеспечение с открытым исходным кодом для проверки правописания на английском, французском, немецком, польском, русском и более чем 20 других языках. Оно находит множество ошибок, которые не может обнаружить простой инструмент проверки орфографии.”

Далее я добавляю зависимость для языкового инструмента в pom.xml:

<dependency>
<groupId>org.languagetool</groupId>
<artifactId>language-en</artifactId>
<version>4.0</version>
</dependency>

После этого я определяю статическую переменную уровня класса langTool класса JLanguageTool. Затем я инициализирую langTool объектом класса AmericanEnglish.

Далее я пишу код метода с именем SpellChecker, где входным параметром является String text (обычный текст), а возвращаемым типом также является String (текст с исправленной орфографией). Я использую метод check класса JLanguageTool с параметром в виде непроверенного текста. Далее он возвращает список RuleMatch. Согласно Java-документации JLanguageTool, класс RuleMatch предоставляет “информацию о правиле ошибки, соответствующем тексту, и позиции совпадения.”

После этого я определяю три переменные: ‘result’ типа String, ‘lastPos’ типа integer, ‘tmp’ типа String. Кроме того, для каждого RuleMatch я воссоздаю предложение с первым предложенным инструментом вариантом написания. Вместе с этим я добавил необходимые блоки try-catch везде, где это требуется.

 

Анализатор тональности: Stanford CoreNLP

Следующим шагом в анализе тональности с помощью Spark является определение тональности текста. Для этого я использую библиотеку Stanford’s Core NLP для поиска значений тональности. Затем я создаю класс с именем ‘StanfordSentiment’, в котором собираюсь реализовать библиотеку для поиска тональности в нашем тексте.

Для этого я добавляю следующие зависимости в файл pom.xml:

<!– Это библиотека Stanford Core NLP –>
<dependency>
<groupId>edu.stanford.nlp</groupId>
<artifactId>stanford-corenlp</artifactId>
<version>3.8.0</version>
</dependency>

<!– Это файл моделей Stanford Core NLP –>
<dependency>
<groupId>edu.stanford.nlp</groupId>
<artifactId>stanford-corenlp</artifactId>
<version>3.8.0</version>
<classifier>models</classifier>
</dependency>

Я создаю статическую переменную объекта ‘props’, которая определяет свойства для конвейера Stanford Core NLP. Я выбрал минимальные свойства, чтобы сделать его как можно более легким. После этого я настраиваю аннотаторы на tokenize, ssplit, pos, parse, sentiment. Я создаю еще одну статическую переменную объекта ‘pipeline’ класса StanfordCoreNLP. Наконец, я инициализирую конвейер со свойствами ‘props’.

GetSentiment:

Я создал метод GetSentiment с входным значением типа String и выходным значением типа Double. Я использую метод CorrectSpell, который я создал в файле LanguageCheck.java. Метод CorrectSpell объекта LanguageCheck возвращает мне правильное написание введенного твита. Я использую метод annotate класса StanfordCoreNLP с этим исправленным текстом. Значения тональности, возвращаемые этой библиотекой, следующие:

0 => очень негативный

1 => негативный

2 => нейтральный

3 => положительный

4 => очень положительный

 

Я вычитаю 2 из результата для каждого предложения, чтобы получить следующие новые категории тональности:

-2 => очень негативный

-1 => негативный

0 => нейтральный

1 => положительный

2 => очень положительный

 

Я возвращаю результат тональности каждого твита как среднее значение тональности каждого предложения твита. Твиты не пишутся в каком-либо структурированном формате. Следовательно, я не могу присвоить какой-то конкретной строке твита больший вес, чем другим. Поэтому я предполагаю, что каждая строка в твите имеет одинаковую важность. Я возвращаю переменную ‘total’ типа Double, которая содержит результирующее значение тональности твита.

 

Запуск программы:

Теперь, когда эти два класса готовы, мы перейдем к их использованию. Таким образом, я создаю новый класс “TwitterDataFlow.java”. Сначала я пишу условную проверку, которая запустит программу только в том случае, если количество переданных входных аргументов равно ровно 2. Если количество аргументов не равно 2, она выводит сообщение о некорректном использовании, а также завершает работу с кодом выхода 1.

Я создаю SparkSession с именем приложения Sentiment Analyzer. Я устанавливаю свойство конфигурации hadoop для spark context’s “mapreduce input fileinputformat input dir recursive” в значение true. Это позволит мне рекурсивно извлекать файлы из папок. Я создаю переменную ‘inputPath’ класса String, в которой задаю входной аргумент, а также ‘/*/*’, что позволит мне читать партиционированные данные, сохраненные Flume. Я читаю данные json из Flume в Dataset<Row> ‘data’.

Затем я регистрирую UDF (пользовательскую функцию) в Spark SQL Context под именем ‘Sentiment’, которая принимает String, применяет к ней метод GetSentiment класса StanfordSentiment’s и возвращает тип данных Double.

В настоящее время у меня есть данные по ключевым словам Apple, Google, Tesla, Infosys, TCS, Oracle, Microsoft и Facebook из flume. Поэтому я создаю список String с этими ключевыми словами. Для каждой из этих компаний я выполняю следующие операции.

Поток операций:

Сначала я создаю outPath, куда хочу сохранить результаты. Я создаю временное представление (temp view) ‘complete’ для набора данных ‘data’. Далее я извлекаю из данных timestamp, partitionBy (чтобы партиционировать данные при сохранении результатов), text, main_text (для использования в регулярных выражениях), followers.

Я создаю временное представление для результатов и отфильтровываю из него данные конкретной компании. Также я применяю UDF Sentiment, которая возвращает мне значения тональности в колонке ‘seVal’. Я сохраняю (persist) сериализованные данные в памяти и со сбросом на диск (disk spill). Из этих данных я получаю NetSentiment — произведение количества подписчиков (Number of Followers) и значения тональности (Sentiment Value) этого твита. Это помогает определить влияние, которое может иметь твит. Для этого я могу использовать различные формулы.

Мы сохраняем (persist) сериализованные данные в памяти и на диске, так как хотим сохранить весь результат, поскольку анализ тональности — это ресурсоемкая задача. Если мы не сохраним эти данные и планируем использовать несколько формул для расчета NetSentiment или влияния, то в предыдущем запросе, где мы бы использовали значение метода Sentiment’s несколько раз, анализ тональности твита выполнялся бы многократно.

Группировка данных:

Теперь я группирую данные по столбцам timestamp и partitionBy и нахожу среднее значение NetSentiment для этой группировки. Это дает мне среднее влияние компании, положительное или отрицательное, в конкретную минуту. Следовательно, я записываю результаты для каждой компании в outPath, разделяя их по столбцу partitionBy.

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

где (Источник):

  • --deploy-mode: развертывать ли драйвер на рабочих узлах (cluster) или локально в качестве внешнего клиента (client) (по умолчанию: client)
  • application-jar: путь к собранному jar-файлу, содержащему ваше приложение и все зависимости. Учтите, что URL-адрес должен быть глобально виден внутри вашего кластера, например, путь hdfs:// или file:// путь, который присутствует на всех узлах.
  • application-arguments: аргументы, передаваемые в метод main вашего основного класса, если таковые имеются. В данном случае — пути ввода и вывода

Финальные шаги:

Затем мы получим результаты анализа тональности с помощью Spark из выходного пути. Например, это возможный результат для apple:

{“timestamp”:”Apr 30 2018 20:31:00″,”avg(NetSentiment)”:-3678.768518518518}
{“timestamp”:”Apr 30 2018 20:32:00″,”avg(NetSentiment)”:-883.002824858757}

Я развернул это приложение на CloudSigma с 5-узловым кластером HDP. В частности, каждый узел имел следующую конфигурацию:

256 ГБ SSD
16 ГБ ОЗУ
20 ГГц ЦП

В общей сложности мне удалось получить результаты анализа тональности с помощью Spark примерно за 19 часов. Кроме того, я включил более сложные вычисления, чем в программе, для набора данных объемом более 80 ГБ.

Код можно найти на GITHUB.

 

author

Akshay Nagpal

Автор · CloudSigma

Preslav Dobrev — креативный дизайнер в CloudSigma, сосредоточенный на формировании последовательного корпоративного образа с помощью традиционных и инновационных маркетинговых каналов. Он умело сочетает художественное видение со стратегическим маркетингом, создавая убедительные истории бренда.

Комментарии

Комментариев пока нет. Будьте первым.