Всем привет! Сегодня мы, риск-технологи банка «Открытие» Илья Мясников (@berrim0r) и Гевонд Асадян (@Gevond), расскажем, каким образом осуществляем тестирование моделей оценки кредитного риска перед выводом в прод. В прошлой статье про дублирующий проверочный скрипт мы рассказали о том, как мониторим корректность выведенной в прод модели. Но проверок же много не бывает! Перед выводом модели в прод нужно удостовериться, что выводимый функционал работает корректно.
Как проверить корректность расчета модели? Ну да, верно — скормить ей входные данные со строго определенными параметрами. Звучит не очень сложно, правда? А если факторов более полутора сотен? И часть из них оказывают влияние только при определенном взаимодействии с другими факторами? Такое количество вариантов входных данных вручную придется готовить не один день.
Поэтому мы придумали как упростить для себя подобное тестирование. Для этого решили разработать сервис, который позволяет генерировать все возможные комбинации входных данных для модели на основании одного или нескольких заданных входных векторов.
Для работы тестового сервиса необходимо развернуть модель в виде rest-API и, конечно же, иметь набор входных данных. В качестве источника входных данных возможно использовать SQL-запрос к базе данных (запрос должен вернуть выборку значений, структура которой соответствует структуре принимаемого моделью JSON-запроса) или загрузку вектора входных данных из файла (.csv, .json или .xlsx).
Также для работы сервиса необходим файл конфигурации. Данный файл имеет JSON-структуру и включает в себя параметры источника данных, адреса модели, способа отправки запросов и сохранения ответов. Вот пример структуры файла конфигурации:
Имя переменной |
Тип |
Допустимые значения |
|||
loader |
Type |
строка |
"mysql" “mssql” “json” "oracle" |
||
parameters |
request |
строка |
не пустое |
||
connection_dbпараметры подключения к базе данных |
user |
строка |
не пустое |
||
password |
строка |
не пустое |
|||
host |
строка |
не пустое |
|||
port |
строка |
необязательное |
|||
database |
строка |
не пустое |
|||
transformation |
type |
строка |
iteration |
||
rules_list |
json |
json |
|||
sender |
model_uri |
строка |
не пустое |
||
number_of_threads |
целочисленное |
≥ 1 |
|||
type |
строка |
"range" "time" |
|||
parameters параметры отправки векторов к модели |
period_time |
целочисленное |
> 0 |
||
requests_for_period |
целочисленное |
> 0 |
|||
block_size |
целочисленное |
> 0 |
|||
start_index |
целочисленное |
≥ 0 |
|||
session_time |
целочисленное |
> 0 |
|||
saver |
directory |
строка |
путь к файлу |
||
type |
строка |
"json" "excel" |
Конфигурационный файл позволяет трансформировать входной вектор перед его отправкой в модель: мы можем указать конкретные значения для конкретных факторов или, что интереснее, задать список таких значений для одного или нескольких факторов. В последнем случае сервис из одного входного вектора сгенерирует несколько.
Для генерации разных вариантов входных векторов из одного базового вектора в конфигурационном файле необходимо заполнить конструкцию вида:
[{‘var_name’: ‘factor_1’, ‘value’: [‘A’, ‘B’]}, [{‘var_name’: ‘factor_2’, ‘value’: [‘A’, ‘B’]}] — где var_name — ключ для поиска фактора, значения в котором мы будем варьировать, а value — набор варьируемых значений.
Преобразование применяется по следующему алгоритму:
Создается набор значений по принципу полного перебора, для всех ключей «Код», т.е. для первого вектора преобразования сгенерируется набор (factor_1, factor_2) = [(‘A’, ‘A’), (‘A’, ‘B’), (‘B’,’A’), (‘B’, ‘B’)];
Из каждого исходного вектора данных удаляются ключи из сгенерированного набора (factor_1, factor_2);
Для каждого исходного вектора происходит поочередное добавление сгенерированных данных. Таким образом, для каждого вектора с ключами Код factor_1, factor_2 будут сгенерированы векторы со значениями соответствующих ключей.
Посмотрим на примере.
Допустим, модель состоит из трех факторов и ждет на вход вектор следующего вида:
{factor_1: value_01, factor_2: value_02, factor_3: value_03}
Из методики применения модели мы знаем, что факторы 2 и 3 оказывают влияние на результат только при определенном значении фактора 1. И сочетание различных значений факторов 2 и 3 может оказывать как положительное, так и отрицательное влияние.
Значит, в конфигурационном файле нам необходимо задать одно конкретное значение для фактора 1 и все возможные варианты значений для факторов 2 и 3:
[{‘var_name’: ‘factor_1’, ‘value’: ‘A’}, {‘var_name’: ‘factor_2’, ‘value’: [‘A’, ‘B’, ‘C’]}, {‘var_name’: ‘factor_3’, ‘value’: [‘A’, ‘B’, ‘C’]}]
Одной этой строкой мы из одного входного вектора сделали девять тест-кейсов!
Теперь, зная, как работает каждый модуль модели, мы можем сформировать столько вариантов для перебора, сколько посчитаем достаточным.
Дополнительно можно задавать значения факторов, выходящие за пределы допустимых значений или не соответствующие типу данных. Например, если подразумевается, что фактор на входе модели может принимать строго положительные целочисленные значения, в конфигурационном файле можно указать для этого фактора такие варианты: отрицательное целое, дробное (положительное и отрицательное), текст, null, Boolean.
Под разные задачи создаются разные конфигурационные файлы: под каждую модель, под пакетное тестирование, под тестирование на обработку ошибок.
Для запуска сервиса достаточно указать путь к конфигурационному файлу и запустить ноутбук.
После запуска сервис с нужной частотой отправляет входные векторы в модель, собирает ответы и автоматически готовит файл отчета в формате response-request. Результат будет выглядеть примерно так:
В результирующем файле автоматически произведен расчет по всем заданным на входе тест-кейсам. Идентифицируя запрос (request) и соответствующий ему ответ (response), аналитик может в подобном отчете найти конкретный тест-кейс и убедиться, что результат модуля соответствует ожиданиям.
Сейчас мы работаем над расширением функционала сервиса в части проверки результатов. Конфигурационный файл уже настраивается таким образом, чтобы проверяющий знал, какой результат в каком модуле модели ожидается при определенном наборе параметров. Значит можно будет помимо факторов, влияющих на расчет, передавать закодированное название кейса (или группы кейсов), а затем автоматически в результатах работы сервиса искать этот код и сразу проверять результат отработки модели.
Таким образом, от подготовки большого количества разновариантных входных данных вручную мы перешли к подготовке одного большого конфигурационного файла, который пакетно тестирует модель и позволяет сделать вывод о корректности ее реализации.
Спасибо за внимание!
iBljad
То есть у вас есть список возможных результатов работы модели, и вы для них прописываете вручную список (из 150+?) параметров и "алгоритмы" их вариативности, а потом (пока еще) глазами проверяете, что актуальные результаты сошлись с ожидаемыми?