Построение модели AI / ML без доступа к набору данных

В этой статье мы продемонстрируем, как создать набор данных для построения модели машинного обучения. Согласно this, мошенничество и злоупотребления в рамках программы Medicare обходятся налогоплательщикам в 60 миллиардов долларов в год. AI / ML может значительно помочь в выявлении и предотвращении мошенничества и злоупотреблений, но поскольку конфиденциальность имеет первостепенное значение в данных о медицинских пациентах, получить доступ к этим данным чрезвычайно сложно. Это не позволяет специалистам по обработке данных создавать модели, которые потенциально могут оказать положительное влияние на эту область. Есть ли способ проектировать и разрабатывать модели без доступа к базовым данным? Да, вы можете создать прототип, используя реалистичные случайно сгенерированные данные. В частности, мы создадим автоматически сгенерированный набор данных о медицинском страховании и будем использовать его для выявления потенциально мошеннических требований. Вот шаги высокого уровня, которым мы будем следовать:

  1. Создание набора данных пациента для разработки прогнозов модели.
  2. Предварительно обработать набор данных для ввода в модель.
  3. Обучите модель прогнозировать стоимость с помощью алгоритма K-Nearest Neighbor.
  4. Для вывода мы введем новые данные пациента и сравним фактическую стоимость с прогнозируемой. Если разница превышает пороговое значение, мы помечаем ее как потенциально мошенническую.

Набор данных

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

Где:

  • Возраст - случайное значение от 1 до 100
  • Курильщик - случайный 0 или 1, настроенный таким образом, чтобы 30% населения были курильщиками.
  • Пол - случайный 0 или 1 (1 женщина)
  • ИМТ - случайное целое число от 5 до 45
  • Диабетический - случайный 0 или 1 с поправкой на то, что 20% населения страдают диабетом
  • Стоимость = Медицинские расходы за год. Среднее значение, которое я использовал, было 9596 долларов.

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

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

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

Остальные поля просты:

  • Начните с приведенной выше формулы, умноженной на возраст.
  • добавить 100% среднего для курильщиков
  • Добавьте 25% от среднего для женщин (это оказалось спорным, когда я показывал своим сверстникам этот черновик. Число, которое я использовал, пришло отсюда.)
  • Добавьте по 1% каждого на каждый процент массы.
  • Добавьте 75% среднего для диабетиков

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

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

Предварительно обработать набор данных для ввода в модель

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

  1. Визуализируйте данные, чтобы убедиться, что они кажутся разумными.
  2. Разместите непрерывные данные в сегментах.
  3. Преобразуйте поля данных в одни столбцы с горячим кодированием.

Визуализация данных

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

Это выглядит довольно близко к тому, что я ожидал. Я всегда могу вернуться и изменить формулу, чтобы улучшить ее, когда я узнаю больше о данных и моделях.

Поместите непрерывные данные в сегменты

У нас есть два поля, которые содержат то, что я называю непрерывными данными (т.е. они не являются логическими или классификационными). Эти поля - Возраст и ИМТ. Возраст может содержать до 100 уникальных значений, а ИМТ может иметь 40 уникальных значений. Это может стать громоздким для нашей модели, поэтому мы разделим их на сегменты. И для возраста, и для индекса массы тела мы разделим их на пять групп.

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

Выглядит неплохо, перейдем к следующему шагу.

Преобразование полей данных в один столбец с горячим кодированием

Как вы можете видеть, возрастная группа и группа ИМТ имеют другую шкалу, чем диабетик, курильщик и пол. Например, возрастная группа находится на шкале от 0 до 4, а для диабетиков - от 0 до 1. Есть много способов решить эту проблему, и для этого я воспользуюсь техникой, называемой горячим кодированием. Идея состоит в том, чтобы разделить столбец Age_group на пять столбцов, содержащих ноль, за исключением столбца, содержащего возрастную группу. Например, если Age_group == 2, значения столбцов будут 0, 0, 1, 0, 0. К счастью, в Python есть встроенная функция, которая сделает это преобразование за нас.

Вот как выглядит наш набор данных после выполнения приведенного выше кода:

Теперь все поля ввода содержат значение ноль или один. Наконец-то мы готовы приступить к построению модели на основе данных.

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

Обучить модель

Первым шагом в обучении модели является разделение наших данных на обучающий набор и тестовый набор. Мы обучим модель на обучающем наборе, а затем протестируем ее, представив данные, которые модель не видела, и сравнив прогнозируемый результат с фактическим. Это называется ошибкой, которую мы хотим минимизировать при обучении модели. Расчет для вычисления ошибки в этом руководстве называется среднеквадратической ошибкой, но есть множество функций, которые вы можете использовать для ее вычисления. Вот код для разделения данных (в данном случае мы используем 70% для обучения и 30% для тестирования).

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

Предположим, у нас есть набор данных, который выглядит следующим образом (X1 и X2 - входные объекты, а Y - результирующее значение).

Теперь давайте изобразим эти данные, чтобы увидеть, как они выглядят:

Благодаря этому мы можем предсказать значение Y для новой точки на графике, усреднив значения Y для K ближайших соседей. В этом примере мы установим K = 4. Красная точка будет нашей новой точкой ввода.

Поскольку в этом примере K == 4, мы возьмем среднее значение Y для 4 точек, ближайших к нашему новому значению, и будем использовать его, чтобы предсказать, каким будет значение Y для нашей новой точки. В этом случае мы будем использовать выделенные строки:

Для нашей новой точки оценка будет 60,5 для значения Y.

В библиотеке Python sklearn есть встроенная функция K-Nearest Neighbor, которую мы будем использовать. Единственный трюк - какое значение мы должны установить для K? Самый простой способ - запустить модель с несколькими значениями K и записать ошибку для каждого значения. Мы можем использовать это, чтобы найти золотую середину для точности. Вот код для этого:

После выполнения приведенного выше кода мы можем построить график коэффициента ошибок по отношению к K:

Чтобы определить наилучшее значение для K, мы воспользуемся методом локтя. По оси Y диаграммы отложено значение ошибки. По оси X отложено значение K. Глядя на диаграмму, кажется, что где-то около 55 было бы лучшим значением для K. Однако «локоть» появляется около 10. После этого ваши результаты начинают выравниваться или даже ухудшаться. В этом уроке я разделю разницу и использую K = 20.

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

Выявление мошеннических требований

А теперь давайте посмотрим, сможем ли мы выявить мошеннические заявления. Для этого я сгенерировал 100 новых строк данных. Идея этого проекта заключается в том, что врач взимает двойную плату за страховые выплаты. Итак, 90 строк использовали функцию add_rows как есть и установили флаг под названием «Мошенничество» на ноль. Затем я добавил 10 строк, но удвоил стоимость и установил флаг «Мошенничество» на 1. Вот диаграмма этого нового набора данных.

Зеленые точки представляют собой мошеннические претензии, а синие точки представляют собой законные претензии. Похоже, у нас есть пять выбросов, которые мы бы исследовали. В этом случае все они мошеннические. Остальные пять отклоняющихся значений скрыты в заявках, не связанных с мошенничеством. Выявить 50% мошеннических претензий неплохо, но можем ли мы сделать лучше?

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

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

Заключение

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