如何处理 All vs All 分类问题

数据挖掘 机器学习 分类 xgboost 多类分类
2022-03-03 14:04:02

假设您正在构建一个可以诊断任何医疗状况的星际迷航式医疗三录仪。它需要能够检测患者患有多种疾病的合并症(例如,患者可能同时患有 COVID、糖尿病和肺癌)。

您将如何构建一个分类系统来检测最可能的一组条件?

我看到两种方法:

  1. 为每种疾病建立一个模型,使用每种模型进行预测,并报告患者患有预测概率超过阈值(例如 0.95)的任何疾病
likely_diseases = []
THRESHOLD = 0.95
for disease in disease_columns:
  model = xgb.XGBClassifier()
  model.fit(X_train, y_train[disease])
  pred_proba = model.predict_proba(patient_data)[:, 1]
  if (pred_proba > THRESHOLD):
    likely_diseases.append(disease)
  1. 每种疾病组合建立一个模型,并选择概率最高的组合
df['has_covid_lung_cancer_and_stroke'] = df.apply(lambda patient: patient['has_lung_cancer'] and patient['has_covid'] and patient['has_stroke'])

# create all other possible permutations of diseases

highest_probability = 0.0
most_likely_disease_combination = None
for disease_combination in disease_combinations: 
  model = xgb.XGBClassifier()
  model.fit(X_train, y_train[disease])
  pred_proba = model.predict_proba(patient_data)[:, 1]
  if (pred_proba > highest_probability):
    most_likely_disease_combination = disease_combination
    highest_probability = pred_proba

让我感到震惊的是,方法二可能会更准确,但计算量可能太大以至于难以处理。在训练数据集中出现率极低的组合被丢弃的情况下,可能会进行一些修剪。

1个回答

我认为您可以执行通常的多类分类,而不是手动执行 one-VS-all 策略(即在 for 循环中),前提是您可以生成多标签目标(即您所说的所有可能的疾病组合)。所以,我会做类似的事情:

  • 生成正确的标签 --> 如果你有 n 个可能的疾病组合,你应该最终有 n 个目标标签(因此使用 apply-lambda 表达式为你生成 n 个二进制列,你也可以将其转换为单个数字列n 个可能的整数值)。您可以在下面找到一种方法来获取目标值的最后一列每个可能组合的整数值);wines 数据集为例,我还考虑了所有可能的组合(在您的情况下,风味类型类似于可能的疾病)。我猜你有一个这样的数据框: 在此处输入图像描述

因此您可以创建一个 dict 将可能的组合映射到整数目标值(用于多类分类):

target_labels_dict = {tuple([1, 0, 0]): 0, tuple([0, 1, 0]): 1, tuple([0, 0, 1]): 2, tuple([1, 1, 0]): 3, tuple([1, 0, 1]): 4, tuple([0, 1, 1]): 5, tuple([1, 1, 1]): 6}

你有这个: 在此处输入图像描述

例如,元组 (1, 1, 0) 表示“酸”和“甜”...

最后,创建您的目标列:

target_flavours_array = np.zeros(len(y_train)).astype('int') 

for ind in y_train_df.index:
   combination_values = tuple(y_train_df.iloc[ind])
   target_flavours_array[ind] = target_labels_dict[combination_values]

得到类似的东西:

在此处输入图像描述

  • 使用 softmax(或其类似的 sofprob 函数,在此处查看)和​​ xgboost 实例 --> 下面是一个快速示例(在原始 3 类数据集上进行训练以获取示例的效果):

从 sklearn.datasets 导入 load_wine

from sklearn.model_selection import train_test_split
import numpy as np 
import xgboost as xgb

dataset = load_wine()
X_train, X_test, y_train, y_test = train_test_split(dataset.data, 
dataset.target, test_size=0.1, random_state=42)

dtrain = xgb.DMatrix(X_train, label=y_train)
dtest = xgb.DMatrix(X_test, label=y_test)    

params = {
    'max_depth': 4,  # maximum depth of each tree
    'eta': 0.2,  # learning rate
    'objective': 'multi:softprob',  # for multiclass problem, providing probabilities
    'num_class': len(np.unique(dataset.target))} # number of classes

iters_number = 30
xgb_model = xgb.train(params, dtrain, iters_number)
xgb_model.predict(dtest)

并且,结果是每个可能类别的预测概率(您的用例中的疾病组合):

在此处输入图像描述

在这里您可以选择每一行的最高概率值。