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

Предпосылки:

Приготовьте следующее:

  1. Учетная запись телепата
  2. Прочтите Руководство по началу работы или используйте Telepath Github для создания экземпляра проекта.

Определение проблемы и решение

Ситуация. Традиционный процесс оформления кредита медленный и непрозрачный.

Проблема. Традиционный подход к андеррайтингу кредитов основан на правилах, при которых специалист по андеррайтингу кредитов просматривает каждую заявку и одобряет или отклоняет кредит в соответствии с критериями приемлемости, установленными кредитором. Если это так в вашей компании, вполне вероятно, что весь процесс требует времени, и если кредит заемщика не будет одобрен, действенная информация не будет предоставлена ​​для положительного курса действий. Можем ли мы использовать машинное обучение, чтобы, по крайней мере, сократить время, затрачиваемое на процесс принятия решения о кредите?

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

Решение проблемы с данными и машинным обучением

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

Здесь loan_id и borrower_id являются уникальным идентификатором, присвоенным кредиту и заемщику. Для этого урока давайте просто предположим, что между loan_id и borrower_id существует отношение один к одному. Кредит может быть связан с заемщиком и наоборот.

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

Теперь, когда у нас есть таблица со столбцом прогнозирования, можем ли мы просто использовать ее для построения модели машинного обучения? Конечно, его можно использовать, если вас устраивает низкая производительность. loan_id и borrower_id являются уникальными идентификаторами, и поэтому никакой прогностический сигнал не будет предоставляться, пока модель пытается извлечь уроки из данных. Время сдаться? Еще нет. Нам нужно логически выбрать атрибуты из кредитов и заемщиков в поисках прогностического сигнала.

Собранные данные

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

Если вы заинтересованы в использовании этих данных, вы можете найти их здесь.

Таблица кредитов

Таблицы заемщиков

Таблица профилей заемщиков

Кредитная история заемщиков

Опрос заемщиков

Проверка кредитоспособности заемщика

Перейдите в среду разработки Typescript.

В вашем файле index.ts

Давайте импортируем объекты, необходимые для создания модели, из Telepath.

import { ModelSpec, Pipeline, Query, Source } from '@telepath/telepath';
import { InputWrap } from '@telepath/runtime';

Чтобы узнать больше о ModelSpec, Pipeline и Source, ознакомьтесь с нашей документацией.

Давайте создадим новый источник.

const source = new Source('bank-data', {
    sourceConnectionSlug: 'loan_underwriting'
});

💡 Исходный ресурс определяет подключение к вашей базе данных.

Давайте создадим новый набор конвейеров.

Первым преобразованием данных в базе данных является преобразование inq_date в ряд запросов. Конвейер следует стандартному SQL в машинописной форме. Если вы не знакомы с TypeScript, это руководство поможет вам быстро понять SDK.

const borrowerCreditInquiriesAggregationPipeline = new Pipeline('borrowerCreditInquiriesAggregationPipeline', {
    input: {
        query: {
      select: {
                'borrower_id': 'borrower_id',
                'inc_last_6mos': {
          count: 'inq_date'
        }
            },
            from: {
                sourceId: source.id,
                table: 'credit_inquiries'
            },
            groupBy: ['borrower_id'],
        }
    }
})

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

Обратите внимание на сходство с оператором SQL ниже:

select "borrower_id", count("inq_date")
from "credit_inquiries"
group by "borrower_id"

Число запросов может быть добавлено к credit_history, чтобы дать более полную картину всего кредитного отчета.

Объект borrowerCreditInquiriesAggregationPipeline содержит объект запроса, который мы можем использовать в качестве переменной в выражении CTE. Объект конвейера borrowerCreditHistoryPipeline ниже показывает использование выражения QueryWith. Используя запрос из приведенного выше конвейера, мы можем вставить этот запрос в этот конвейер.

const borrowerCreditHistoryPipeline = new Pipeline('borrowerCreditHistoryPipeline', {
    input: {
        query: {
            with: {
                borrowerCreditInquiriesAggregationPipeline: borrowerCreditInquiriesAggregationPipeline.query as InputWrap<Query>
            },
            from: {
                sourceId: source.id,
                table: 'credit_history'
            },
            join: [
                {
                    target: 'borrowerCreditInquiriesAggregationPipeline',
                    on: ['borrowerCreditInquiriesAggregationPipeline.borrower_id', 'credit_history.borrower_id'],
                    type: 'LEFT'
                }
            ],
            select: {
                borrower_id: 'credit_history.borrower_id',
                dti: 'credit_history.dti',
                earliest_cr_line: 'credit_history.earliest_cr_line',
                mths_since_last_delinq: 'credit_history.mths_since_last_delinq',
                open_acc: 'credit_history.open_acc',
                pub_rec: 'credit_history.pub_rec',
                revol_bal: 'credit_history.revol_bal',
                revol_util: 'credit_history.revol_util',
                total_acc: 'credit_history.total_acc',
                inc_last_6mos: 'borrowerCreditInquiriesAggregationPipeline.inc_last_6mos'
            }
        }
    }
})

Использование запроса в качестве входных данных для CTE позволяет разделить запросы и удобочитаемость.

Приведенный выше запрос (borrowerCreditHistoryPipeline) выражается в SQL как:

with borrowerCreditHistoryPipeline as (
  borrowerCreditInquiriesAggregationPipeline.Query  # <-- query from above
), 
select borrower_id, dti, earliest_cr_line, mths_since_last_delinq, open_acc
  pub_rec, revol_bal, revol_util, total_acc, inc_last_6mos
from credit_history
left join borrowerCreditInquiriesAggregationPipeline as b 
on b.borrower_id == credit_history.borrower_id

❗️ Обратите внимание, что нулевые значения в строках будут обрабатываться процессом моделирования Telepath, и Telepath будет использовать несколько методов для адаптации процесса на основе ваших данных.

Объединение всех данных в плоскую таблицу — последний шаг, так как кредитные данные теперь объединены в таблицу Credit_history. Используя целевую таблицу в качестве основы, приведенный ниже TypeScript объединяет данные в единую таблицу для моделирования. Каждая строка запроса должна содержать прогностические функции и цель.

export const loansPipeline = new Pipeline('loansPipeline', {
    input: {
        query: {
            with: {
                borrowerCreditHistoryPipeline: borrowerCreditHistoryPipeline.query as InputWrap<Query>
            },
            from: {
                sourceId: source.id,
                table: 'loans_borrowers',
                as: 'loans_borrowers_status'
            },
            join: [
                {
                    target: 'borrowerCreditHistoryPipeline',
                    on: ['borrowerCreditHistoryPipeline.borrower_id', 'loans_borrowers_status.borrower_id'],
                    type: 'INNER'
                },
                {
                    target: {
                        sourceId: source.id,
                        table: 'borrowers'
                    },
                    on: ['loans_borrowers_status.borrower_id', 'borrowers.borrower_id'],
                    type: 'INNER'
                },
                {
                    target: {
                        sourceId: source.id,
                        table: 'background_check'
                    },
                    on: ['loans_borrowers_status.borrower_id', 'background_check.borrower_id'],
                    type: 'INNER'
                },
                {
                    target: {
                        sourceId: source.id,
                        table: 'loans'
                    },
                    on: ['loans_borrowers_status.loan_id', 'loans.loan_id'],
                    type: 'INNER'
                }
            ],
            select: {
                loan_id: 'loans_borrowers_status.loan_id',
                borrower_id: 'loans_borrowers_status.borrower_id',
                is_likely_to_pay_off_loan: 'loans_borrowers_status.loan_status',
                dti: 'borrowerCreditHistoryPipeline.dti',
                earliest_cr_line: 'borrowerCreditHistoryPipeline.earliest_cr_line',
                mths_since_last_delinq: 'borrowerCreditHistoryPipeline.mths_since_last_delinq',
                open_acc: 'borrowerCreditHistoryPipeline.open_acc',
                pub_rec: 'borrowerCreditHistoryPipeline.pub_rec',
                revol_bal: 'borrowerCreditHistoryPipeline.revol_bal',
                revol_util: 'borrowerCreditHistoryPipeline.revol_util',
                total_acc: 'borrowerCreditHistoryPipeline.total_acc',
                inc_last_6mos: 'borrowerCreditHistoryPipeline.inc_last_6mos',
                emp_title: 'borrowers.emp_title',
                emp_length: 'borrowers.emp_length',
                home_ownership: 'borrowers.home_ownership',
                annual_inc: 'borrowers.annual_inc',
                zip_code: 'borrowers.zip_code',
                addr_state: 'borrowers.addr_state',
                verification_status: 'background_check.verification_status',
                loan_amnt: 'loans.loan_amnt',
                term: 'loans.term',
                int_rate: 'loans.int_rate',
                installment: 'loans.installment',
                grade: 'loans.grade',
                sub_grade: 'loans.sub_grade',
                purpose: 'loans.purpose',
            }
        }
    }
})

Оператор SQL для приведенного выше конвейера похож на borrowerCreditHistoryPipeline с добавлением другого типа соединения. Дополнительную информацию обо всех возможных атрибутах пайплайна смотрите здесь.

with borrowerCreditHistoryPipeline as (
		borrowerCreditHistoryPipeline.Query  # <-- query from above
), 
select loan_id, borrower_id, is_likely_to_pay_off_loan, dti, earliest_cr_line,
                mths_since_last_delinq, open_acc, pub_rec, revol_bal, revol_util,
                total_acc, inc_last_6mos, emp_title, emp_length, home_ownership,
                annual_inc, zip_code, addr_state, verification_status, loan_amnt,
                term, int_rate, installment, grade, sub_grade, purpose
from loans

inner join borrowerCreditHistoryPipelineas as bchp
    on bchp.borrower_id == loans_borrowers_status.borrower_id

inner join borrowers as b 
    on b.borrower_id == loans_borrowers_status.borrower_id

inner join background_check as bc 
    on bc.borrower_id == loans_borrowers_status.borrower_id

inner join loans as l 
    on l.borrower_id == loans_borrowers_status.borrower_id

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

На данный момент у вас есть все необходимые требования для построения вашей модели классификации.

Давайте создадим ModelSpec.

new ModelSpec('loan-underwriting-usecase-model', {
    pipelineId: loansPipeline.id,    
    targetColumn: 'loan_status',
});

💡 Ресурс modelSpec определяет модель, которую будет обучать Telepath. Это еще не модель, но это определение того, какой эта модель может быть.

В терминале выполните следующую команду:

npx telepath deploy

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

Переключитесь на веб-интерфейс для обучения модели.

В разделе Models/Model Specs найдите развернутую спецификацию модели. Выбрав спецификацию модели, вы попадете на страницу для обучения модели.

Нажмите «Начать тренировочную модель», чтобы начать тренировку. Это запускает процесс обучения и показывает прогресс обучения. После завершения ваша модель должна быть развернута.

После завершения развертывания сведения об API отображаются на той же странице.

Теперь вы развернули модель и получили API, к которому можно делать http-запросы.

Посмотрим, сработало ли это

Используйте приведенные выше сведения об API, чтобы отправить запрос curl из командной строки.

Сначала создадим файл test.json с полезной нагрузкой.

Вставьте пример полезных данных запроса в файл test.json. Вот полезная нагрузка.

{
  "data": {
    "dti": 1304202,
    "term": 36,
    "grade": "D",
    "loan_id": 1069314,
    "pub_rec": 0,
    "purpose": "other",
    "int_rate": 18.25,
    "open_acc": 8,
    "zip_code": "180xx",
    "emp_title": null,
    "loan_amnt": 3000,
    "revol_bal": 43936,
    "sub_grade": "D5",
    "total_acc": 22,
    "addr_state": "PA",
    "annual_inc": 65000,
    "emp_length": "9 years",
    "revol_util": 98.1,
    "borrower_id": 1304202,
    "installment": 108.84,
    "inc_last_6mos": null,
    "home_ownership": "MORTGAGE",
    "earliest_cr_line": "Sep-98",
    "verification_status": "not_verified",
    "mths_since_last_delinq": 0
  }
}

Из командной строки отправьте запрос cURL.

curl --location --request POST 'https://api.telepath.io/predict/ID-OF-MODEL' \
--header 'X-API-KEY: YOUR_X_API_KEY' \
--header 'Content-Type: application/json' \
-d "@test.json"

И это должно вернуть что-то похожее на это.

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

К нашему test.json добавим includeConfidence и установим его на true.

{
  "data": {
    "dti": 1304202,
    "term": 36,
    "grade": "D",
    "loan_id": 1069314,
    "pub_rec": 0,
    "purpose": "other",
    "int_rate": 18.25,
    "open_acc": 8,
    "zip_code": "180xx",
    "emp_title": null,
    "loan_amnt": 3000,
    "revol_bal": 43936,
    "sub_grade": "D5",
    "total_acc": 22,
    "addr_state": "PA",
    "annual_inc": 65000,
    "emp_length": "9 years",
    "revol_util": 98.1,
    "borrower_id": 1304202,
    "installment": 108.84,
    "inc_last_6mos": null,
    "home_ownership": "MORTGAGE",
    "earliest_cr_line": "Sep-98",
    "verification_status": "not_verified",
    "mths_since_last_delinq": 0
  },
  "includeConfidence": true
}

Снова используйте команду cURL и давайте посмотрим, что мы получим.

{
    "prediction": [
        [
            1,
            0.8211654911996858
        ]
    ]
}

Модель на 82 % уверена, что заемщик погасит кредит.

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

Следующие шаги

Если вы заинтересованы в использовании Telepath, вы можете зарегистрироваться здесь.