Классификация текста на Java с WEKA — анализ финансовых транзакций

Alexey Titov
4 min readDec 8, 2019

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

copyright from Alex Titov

Уже несколько десятков лет мы наблюдаем стремительное развитие сервисов, предоставляющих финансове услуги. Современные финансы — это банкинг, кредитование, налогообложение, управление инвестициями, переводы и платежи. Все эти составляющие почти полностью перекочевали в виртуальное пространство. Онлайн кабинеты и мобильные клиенты обеспечивают постоянный доступ пользователей к услугам. Данные средства весьма удобны и практичны, имеют персональные и корпоративные уровни обслуживания, непрерывно действующую систему поддержки. Они дают возможность проводить денежные транзакции различного характера. Электронные сервисы постоянно развиваются, автоматизируются и становятся “умнее”.

Одной из важнейших технических задач в электронных финансах, является задача определения направления потока материальных средств (расход / приход). Платеж или поступление осуществляется в данный момент при проведении банковской операции.

Эти и аналогичные задачи могут быть легко автоматизированны при помощи австралийского инструмента WEKA. В нем были реализованы подходы для анализа данных и машинного обучения, в том числе обработки текстов финансового характера.

Weka — нелетающая птичка, эндемичный вид австралийской птицы из семейства пастушковых, который живёт в Новой Зеландии. Авторы и разработчики свободного программного обеспечения, написанного на Java в Университете Уаикато (Новая Зеландия) и распространяющегося по лицензии GNU GPL, взяли эту птичку за “основу” и научили ее многому.

Несмотря на свое необычное и забавное название, WEKA — это инструмент, способный решать весьма сложные финансовые задачи.

Рассмотрим проблему классификации денежной транзакции по ключевым словам. Эта задача весьма похожа на SPAM-классификатор: при должной доработке бинарного SPAM-классификатора можно получить дебет-кредит-классификатор.

Бинарный классификатор может быть создан на наивном Байесовском классификаторе, который основан на применении теоремы Байеса со строгими (“наивными”) предположениями о независимости испытаний. Таким образом, WEKA предоставляет мощный инструмент Байесовского классификатора.

Иморт отсновных инструментов WEKA и Java

Создадим класс DebitCreditWekaClassifier.java, который готовит данные и обучает нашу модель классификатора.

public class DebitCreditWekaClassifier {...}

Введем защищенные переменные класса — переменные класса, не доступные из внешнего мира. У нас это объект фильтра классификатора FilteredClassifier и логгер класса Logger. Объект FilteredClassifier является объектом произвольного классификатора. Основу классификатора составляет фильтр (структура с весами или коэффициентами), через который проходят данных. Структура фильтра и его коэффициенты основаны исключительно на обучающих данных. Тестовые данные будут обрабатываться фильтром без изменения его коэффициентов и структуры. Если после обучения присутствуют неравные веса фильтра или ошибки классификации, то экземпляры или атрибуты данных подвергаются повторной обработке. Используется, как правило, альтернативная выборка из исходного набора тренировочных данных. Таким образом, все веса фильтра уточняются (перенастраиваются), прежде чем они будут переданы в итоговый классификатор.

Защищенные переменные класса классификатора

Данные для обучения trainData будут содержать набор из экземпляров и меток.

Класс для атрибутов — wekaAttributes. Как только атрибуты были созданы, их нельзя изменить. Поддерживаются следующие типы атрибутов: числовой, строковый, дата, реляционный и номинальный. Последний тип представляет собой фиксированный набор номинальных значений. Более подробную информацию об атрибутах WEKA смотрите по ссылке.

Перейдем к описанию основных методов класса. Прежде всего, рассмотрим конструктор класса DebitCreditWekaClassifier. Он выглядит так:

Конструктор основного класса

Данный метод содержит необученный экземпляр классификатора classifier. Для определения алгоритма классификации зададим полиномиальный наивный Байесовский классификатор NaiveBayesMultinomial() (see for more). Зададим атрибуты модели в wekaAttributes. Первый атрибут — это attributeText. Сюда будет помещен тренировочный размеченный текст, модель будет работать с текстовой информацией. Добавим метки классов для тренировочных данных в контейнер classAttribute — в нашем случае это два типа меток debit и credit. На этом формирование конструктора закончено.

Теперь приведем данные к нужному формату ARFF (Attribute-Relation File Format). Загрузим и сохраним данные в ARFF формате.

Нам необходимо создать фильтр, преобразующий словарь в вектора свойств StringToWordVector filter. Вектор свойств — это n-мерный вектор числовых параметров, представляющих некоторый объект.

Для получения набора векторов на основе текстовых данных нам необходимо разбить обучающую выборку на фразы. Для этого добавим токенизатор, разделяющий данные на фразы или N-граммы. Как правило, на практике N-грамма — это ряд слов. Установим для эксперимента размер фразы только в одно слово tokenizer.setNGramMinSize(1). В качестве разделителя укажем любой не буквенно-цифровой символ “\\W”. Это выглядит так: tokenizer.setDelimiters(“\\W”). Применяем заданный токенизатор к нашему фильтру filter.setTokenizer(tokenizer). Далее следует стандартная процедура, включенная в возможности фильтра — приведение к нижнему регистру filter.setLowerCaseTokens(true). Применим новый настроенный фильтр к нашему классификатору classifier.setFilter(filter).

Переходим к тренировке классификатора на подготовленный данных.

Тренировка проходит без ошибок и логгирования. После этого должна быть создана и сохранена модель MODEL = “model/debit_credit_model.dat”.

Прогоняем тест для анализа полученной модели и пишем результат в логгер.

LOGGER.info("Evaluation Result: \n"+wt.evaluate());
....
Результат анализа:
Correctly Classified Instances 8 100 %
Incorrectly Classified Instances 0 0 %
Kappa statistic 1
Mean absolute error 0.2334
Root mean squared error 0.2456
Relative absolute error 46.6838 %
Root relative squared error 49.1217 %
Total Number of Instances 8

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

Полный код смотрите на сайте в проекте https://github.com/AlexTitovWork/testWekaClassify.

С уважением, Алекс Титов!

https://github.com/AlexTitovWork

--

--

Alexey Titov

R&D engineer in machine learning and data analysis. Java, C/C++, Python, M and CUDA. HPC, processors architectures and parallel systems.