НЛП в финансах

Ответ на финансовый вопрос с Джиной и BERT - Часть 2

Учебник о том, как оценивать и улучшать результаты поиска Financial QA с помощью Jina

Часть 1 - узнайте, как использовать структуру нейронного поиска, Jina, для создания приложения для поиска ответов на финансовые вопросы (QA) с помощью FiQA. Набор данных, PyTorch и Трансформаторы обнимающего лица .

Часть 2. Узнайте, как оценивать и улучшать результаты поиска по финансовому контролю качества с помощью Jina

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

Напомним, что Jina предоставляет нам строительные блоки, которые позволяют нам создавать поисковое приложение. Поэтому вместо того, чтобы самостоятельно внедрять показатели оценки, мы можем использовать Evaluator Джины, разновидность Executor.

До сих пор мы уже видели некоторые из Executors: Encoder, Indexer и Ranker. Каждый из этих исполнителей отвечает за логику своих соответствующих функций. Как следует из названия, оценщик будет содержать логику наших показателей оценки. Мы также узнали, как разработать индекс и поток запросов, которые являются конвейерами для индексации и поиска фрагментов ответов.

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

Руководство

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

Мы будем оценивать результаты поиска до и после перерейтинга с FinBERT-QA. Вот обзор процесса оценки:

Настраивать

Если вы переходите к предыдущему руководству, вам нужно будет внести небольшие изменения в app.py, FinBertQARanker/__init__.py и FinBertQARanker/tests/test_finbertqaranker.py. Джоан Фонтаналс Мартинес и я добавили некоторые вспомогательные функции и пакетирование в Ranker, чтобы ускорить процесс.

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

Клонировать шаблон проекта:

git clone https://github.com/yuanbit/jina-financial-qa-evaluator-template.git

Убедитесь, что требования установлены, и вы загрузили данные и модель.

Вы можете найти окончательный код этого руководства здесь.

Давайте рассмотрим процесс оценки шаг за шагом.

Шаг 1. Определите данные нашего тестового набора.

Наш рабочий каталог будет jina-financial-qa-evaluator-template/. В папке dataset/ должны быть следующие файлы:

Для этого урока нам понадобятся:

sample_test_set.pickle: образец набора тестов с 50 вопросами и достоверными ответами

qid_to_text.pickle: словарь для сопоставления идентификаторов вопросов с текстом вопроса

Если вы хотите использовать полный набор тестов от FinBERT-QA, test_set.pickle, который содержит 333 вопроса и достоверные ответы, вы можете просто изменить путь.

Набор тестов, с которым мы будем работать в этом руководстве, представляет собой файл pickle, sample_test_set.pickle. Это список списков в форме [[question id, [ground truth answer ids]]], где каждый элемент содержит идентификатор вопроса и список идентификаторов основных истинных ответов. Вот фрагмент из тестового набора:

[[14, [398960]],
 [458, [263485, 218858]],
 [502, [498631, 549435, 181678]],
 [712, [212810, 580479, 527433, 28356, 97582, 129965, 273307]],...]

Далее, аналогично определению нашего Документа для индексации отрывков с ответами, мы создадим два Документа, содержащих данные вопросов и основные истинные ответы.

Напомним, в нашем потоке индекса, когда мы определяли наши данные в функции index_generator, мы включали идентификаторы отрывков ответа (docids) в документ. Следовательно, после индексации эти идентификаторы ответов сохраняются в индексе, и они важны, поскольку являются частью результатов поиска во время запроса. Таким образом, нам нужно только определить Документ наземной истины с идентификаторами ответов основной истины для каждого запроса и сравнить эти идентификаторы ответов с идентификаторами ответов совпадений.

Давайте добавим генератор Python под функцию load_pickle, чтобы определить наш тестовый набор для оценки. Для каждого документа мы сопоставим соответствующий вопрос и из набора тестов с фактическим текстом.

Шаг 2. Закодируйте вопросы

Как и в случае с потоком запросов, мы передадим наши два документа в модуль кодировщика из pods/encode.yml. Драйвер передаст текст вопроса в кодировщик, чтобы преобразовать его во вложение, и тот же драйвер добавит вложение в документ запроса. Единственная разница на этот раз заключается в том, что мы передаем два документа в модуль кодировщика, а документ основополагающей достоверности неизменен и остается неизменным в потоке.

В flows/ давайте создадим файл для настройки нашего процесса оценки с именем evaluate.yml и добавим модуль кодировщика следующим образом:

Выходные данные кодировщика будут содержать документ запроса с вкраплениями вопросов, а документ подтверждения достоверности останется неизменным, как показано на рисунке 4.

Шаг 3. Поисковые индексы

Затем модуль индексатора из pods/doc.yml будет искать ответы с наиболее похожими встраиваемыми версиями, а драйвер индексатора добавит в документ запроса список топ-k совпадений ответов. Документ «Основополагающая истина» остается без изменений.

Давайте добавим doc_indexer к flows/evaluate.yml следующим образом:

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

Шаг 4. Оценка

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

  1. Оценщик результатов матча
  2. Рейтинг
  3. Оценщик результатов с измененным рейтингом

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

Имея цель позволить нам проверять любую часть конвейера и дать нам возможность оценивать в произвольных местах в потоке, мы можем использовать функцию inspect Jina Flow API для прикрепления Модули Evaluator Pods в основной конвейер, чтобы оценки не блокировали сообщения другим компонентам конвейера.

Например, без режима inspect у нас был бы упомянутый выше последовательный дизайн. В режиме inspect после получения совпадений ответов из индексатора документы будут отправляться одновременно в оценщик и ранжировщик. Следовательно, ранжировщику не нужно ждать, пока начальные совпадения ответов будут оценены, прежде чем он сможет вывести повторные совпадения ответов!

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

Вы можете обратиться к этой статье, чтобы узнать больше о дизайне оценочного режима и функции inspect.

Давайте подробнее рассмотрим оценочную часть потока:

На рисунке 6 мы видим, что модуль evaluate_matching, который является оценщиком, отвечающим за оценку совпадений ответов, работает параллельно с модулем Ranker и модулемevaluate_ranking, оценщиком, ответственным за оценку совпадений с повторным ранжированием ответов.

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

Ранее мы использовали кодировщик и индексатор от Jina Hub, открытый реестр для размещения исполнителей через образы контейнеров. Мы снова можем воспользоваться преимуществами Jina Hub и просто использовать уже доступные модули Precision и Reciprocal Rank!

Теперь давайте посмотрим на оценщиков сопоставления и рейтинга:

Соответствующий оценщик

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

Драйвер модуля Matching Evaluator Pod интерпретирует как запрос, так и документ наземной достоверности и передает идентификаторы соответствия ответов и желаемые идентификаторы ответов наземной достоверности для каждого запроса в Matching Evaluator, который вычисляет значения точности и взаимного ранга, как показано на рисунке 7.

А теперь давайте создадим нашу Matching Evaluator. В папке pods/ создайте файл с именем evaluate_matching.yml. Мы добавим в файл следующее:

PrecisionEvaluator и ReciprocalRankEvaluator - это оценщики точности и взаимного ранга от Jina Hub. Мы указываем eval_at: 10 для оценки 10 лучших совпадений ответов. Мы также указываем name для каждого компонента, который мы будем использовать позже в потоке оценки.

Из последнего руководства вы можете спросить, почему нам не нужно указывать драйвер в pods/encode.yml и pods/doc.yml, поскольку для Peas в Pods требуются оба компонента. Это связано с тем, что драйверы для этих двух модулей обычно используются и уже включены по умолчанию. Однако, поскольку мы хотим использовать два оценщика по нашему выбору (точность и взаимный рейтинг) из Jina Hub, нам нужно указать драйвер для каждого оценщика, а именно RankEvaluateDriver.

Затем давайте добавим этот модуль в процесс оценки. В flows/evaluate.yml добавить evaluate_matching следующего содержания:

Здесь мы указываем method: inspect, потому что мы используем функцию inspect из Flow API для проверки производительности нашего приложения в середине потока.

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

Отличная работа! Мы успешно внедрили первый Evaluator. Давайте посмотрим, как оценивать результаты поиска с измененным рейтингом.

Рейтинговая оценка

Другой рабочий процесс после модуля индексатора включает в себя оценщик ранжирования, который отвечает за вычисление точности и взаимного ранга совпадений с повторным ранжированием ответов с помощью FinBERT-QA. Конструкция модуля ранжирования оценщика аналогична модулю сопоставления, с той лишь разницей, что мы передаем переупорядоченные идентификаторы соответствий оценщику ранжирования, как показано на рисунке 9.

Давайте создадим наш оценщик рейтинга. В папке pods/ создайте файл с именем evaluate_ranking.yml. Мы добавим в файл следующее:

Обратите внимание, что это почти идентично evaluate_matching.yml, за исключением соглашений об именах.

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

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

Убедитесь, что у вас установлено расширение Jina Hub:

pip install “jina[hub]”

В рабочем каталоге введите:

jina hub build FinBertQARanker/ — pull — test-uses — timeout-ready 60000

Вы должны получить сообщение о том, что вы успешно создали изображение с его именем тега. В зависимости от текущего выпуска Jina . Не забудьте соответствующим образом изменить имя тега при использовании его в качестве модуля.

Затем давайте добавим модуль Ranker и Evaluate Ranking Pod в поток оценки в flows/evaluate.yml:

Модуль индексатора передаст документ запроса с совпадениями ответов и идентификаторами наземной истины в средство ранжирования, содержащее FinBERT-QA. Затем модуль Ranker Pod выведет документ запроса с переупорядоченными идентификаторами совпадений ответов и документ наземной достоверности, которые будут переданы оценщику рейтинга. Результат, показанный на Рисунке 10, будет таким же, как и у Matching Evaluator, с разницей значений оценки, вычисленных из переупорядоченных совпадений ответов.

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

Шаг 4. Получите результаты оценки

Подобно функции index, в app.py давайте добавим evaluate функцию после evaluate_generator, которая загрузит поток оценки из flows/evaluate.yml и передаст входные документы запроса и обоснования из evaluate_generator в поток. Мы устанавливаем наш top-k=10 для оценки точности @ 10 и обратного ранга @ 10.

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

Окончательные значения оценки будут сохранены в документе запроса, как и функция print_resp, мы можем написать функцию для распечатки ответа оценки, перебирая оценки в нашем документе запроса, d.evaluations и распечатывая значения для каждого оценщика:

Ура! 🎉🎉🎉 Мы только что внедрили оценочный режим в нашу поисковую систему Financial QA! Теперь мы можем запустить:

python app.py evaluate

Поскольку это руководство предназначено для образовательных целей, мы проиндексировали только часть отрывков с ответами и использовали небольшую выборку тестов. Поэтому результаты нельзя сравнивать с результатами FinBERT-QA. Не стесняйтесь проиндексировать всю коллекцию ответов, оценить полный набор тестов и поделиться своими результатами!

Вы увидите, как оцениваются и распечатываются отдельные вопросы. Вот пример идентификатора вопроса: 1281.


Evaluations for QID:1282 
    Matching-Precision@10: 0.10000000149011612 
    Matching-ReciprocalRank@10: 1.0 
    Ranking-Precision@10: 0.10000000149011612 
    Ranking-ReciprocalRank@10: 0.125

В конце вы увидите средние результаты оценки:

Average Evaluation Results
     Matching-Precision@10: 0.056000000834465026
     Matching-ReciprocalRank@10: 0.225
     Ranking-Precision@10: 0.056000000834465026
     Ranking-ReciprocalRank@10: 0.118555556088686

Резюме

В этом руководстве я представил функцию оценки в Jina и продемонстрировал, как мы можем разработать поток оценки для нашего поискового приложения Financial QA. Мы узнали, как использовать режим inspect для создания наших модулей Evaluator Pod и что он приносит пользу нашему приложению, сводя к минимуму влияние оценки на производительность конвейера.

Обязательно загляните на страницу Джины Github, чтобы узнать больше и начать создавать свои собственные поисковые приложения на базе глубокого обучения!

Сообщество

  • Slack channel - коммуникационная площадка для разработчиков, чтобы обсудить Джину.
  • Информационный бюллетень сообщества - подпишитесь на последние обновления, релизы и новости о событиях Jina.
  • LinkedIn - познакомьтесь с Jina AI как компанией и найдите возможности для работы.
  • Twitter - подписывайтесь и взаимодействуйте с Jina AI, используя хэштег #JinaSearch
  • Компания - узнайте больше о Jina AI и их приверженности открытому исходному коду!

Примечание редакторам Data Science. Хотя мы разрешаем независимым авторам публиковать статьи в соответствии с нашими правилами и рекомендациями, мы не поддерживаем вклад каждого автора. Не следует полагаться на работы автора без консультации с профессионалами. См. Подробности в наших Условиях для читателей.