Обнаружение аномалий с помощью автоэнкодеров для мошеннических заявлений о страховании здоровья.

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

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

Я бы рекомендовал прочитать книгу Практическое обучение без учителя с использованием Python для лучшего практического понимания темы. Для этой книги есть репозиторий GitHub. В своем примере я использую функцию вычисления оценки аномалий из этой книги.

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

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

Трудно получить общедоступные данные для медицинского страхования (вопросы конфиденциальности). По этой причине я использую сгенерированные данные (на основе этого поста - Наука о данных без данных):

  • Обучение: 100 000 (обоснованные претензии), 1 000 (мошеннические претензии)
  • Тестирование: 30000 (обоснованные претензии), 300 (мошеннические претензии)
  • Правило мошенничества: заявленная страховая стоимость удваивается

Функция оценки аномалий для определения частоты ошибок восстановления данных:

def anomalyScores(originalDF, reducedDF):
    loss = np.sum((np.array(originalDF) - \
                   np.array(reducedDF))**2, axis=1)
    loss = pd.Series(data=loss,index=originalDF.index)
    loss = (loss-np.min(loss))/(np.max(loss)-np.min(loss))
    
    print('Mean for anomaly scores: ', np.mean(loss))
    
    return loss

Автоэнкодер реализован с помощью Keras / TensorFlow. Нейронная сеть имеет 3 уровня (количество узлов = измерение данных). Используя линейную активацию, оптимизатор Адам:

# Call neural network API
model = Sequential()
# Apply linear activation function to input layer
# Generate hidden layer with 14 nodes, the same as the input layer
model.add(Dense(units=14, activation='linear',input_dim=14))
model.add(Dense(units=14, activation='linear'))
# Apply linear activation function to hidden layer
# Generate output layer with 14 nodes
model.add(Dense(units=14, activation='linear'))
# Compile the model
model.compile(optimizer='adam',
              loss='mean_squared_error',
              metrics=['accuracy'])

Это обучение без учителя - этикетка о мошенничестве не включается в обучение:

# Train the model
num_epochs = 10
batch_size = 256
history = model.fit(x=dataX, y=dataX,
                    epochs=num_epochs,
                    batch_size=batch_size,
                    shuffle=True,
                    validation_data=(dataX, dataX),
                    verbose=1)

Модель обучается за 10 прогонов. После каждого прогона рассчитывается оценка аномалии для измерения точности реконструкции. Сохраняется лучшая модель. Точность измеряется с использованием прецизионного вызова и рабочих характеристик приемника. Примерный результат обучения:

Логика обнаружения мошенничества реализована в блокноте fraud_detection. Функция Predict выполняется на тестовых данных без меток. Оценки аномалий рассчитываются с использованием функции оценки аномалий. Я рассчитал средний балл аномалии, это поможет определить порог, позволяющий различать действительные и мошеннические претензии. Среднее значение, рассчитанное на основе данных испытаний:

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

Порог обнаружения мошенничества = 0,01.

Полученные результаты:

  • Действительные претензии: 30 000
  • Мошенничество: 286 (точность 95%)
  • Не идентифицировано как мошенничество: 14

Порог обнаружения мошенничества = 0,005 (ближе к расчетному среднему значению 0,003).

Полученные результаты:

  • Действительные претензии: 29 636
  • Мошенничество: 293 (точность 98%)
  • Действительно, идентифицировано как мошенничество: 364
  • Не идентифицировано как мошенничество: 7

Порог обнаружения мошенничества = 0,003 (равно расчетному среднему 0,003).

Полученные результаты:

  • Действительные претензии: 26 707
  • Мошенничество: 300 (точность 100%)
  • Действительно, идентифицировано как мошенничество: 3293

Заключение

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

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

Исходный код: репо GitHub