【问题标题】:Can't predict the result. Get wrong result in Multi label classification with OneVsRestClassifier无法预测结果。使用 OneVsRestClassifier 在多标签分类中得到错误的结果
【发布时间】:2021-10-03 22:18:21
【问题描述】:

多标签分类

gender  age weight  height  vitamin_A   vitamin_C   vitamin_D
0       55  64      128     0           1           0
0       54  72      135     0           1           0
0       82  70      150     1           1           1
0       82  70      150     1           1           1
0       59  64      107     0           1           0

特征是性别、年龄、体重、身高

标签是维生素 A、C、D

X = df[['gender', 'age', 'weight', 'height']]
y = df[['vitamin_A', 'vitamin_C', 'vitamin_D']]

我用 OneVsRestClassifier 做了简单的多标签分类模型。

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=True)
LR_pipeline = Pipeline([('clf', OneVsRestClassifier(LogisticRegression(solver='sag'), n_jobs=-1))])
labels = ['vitamin_A', 'vitamin_C', 'vitamin_D']
acc_classifier = []

for label in labels:
    LR_pipeline.fit(X_train, y_train[label])
    prediction = LR_pipeline.predict(X_test)
    acc = accuracy_score(y_test[label], prediction)
    acc_classifier.append(acc)

df_ = pd.DataFrame({'Label': labels, 'Accuracy': acc_classifier})
df_

    Label      Accuracy
0   vitamin_A   0.75
1   vitamin_C   0.65
2   vitamin_D   1.00

原代码在code link。 数据在data link

但我不知道如何使用模型。我做到了,但结果似乎是错误的。因为每次我尝试它都会得到相同的结果,并且只有 1,1,1。

data_test = [[0, 82, 70, 150]] 
for label in labels:
     y_predict = LR_pipeline.predict(data_test)
     print(y_predict)

结果是[1][1][1]每次偶数变化。

我的专家是:

输入:性别=0,年龄=55,体重=64,身高=128

结果1:维生素A为0,维生素C为1,维生素D为0

结果 2:维生素 A 为 0.64,维生素 C 为 0.82,维生素 D 为 0.34

vitamin_A vitamin_B vitamin_C vitamin_A_prob vitamin_B_prob vitamin_C_prob
0         1         0         0.64           0.82           0.34    

【问题讨论】:

    标签: python machine-learning multilabel-classification


    【解决方案1】:

    首先,您要多次拟合同一个模型。 fit 方法重新初始化模型,丢弃任何先前训练的参数。

    其次,提供的数据集不是多标签的,因为“vitamin_A”列的一行有一个“2”。假设这只是一个错字,您可以直接在整个数据集上使用OneVsRestClassifier.fit,无需为每个标签进行拟合。运行:

    LR_pipeline.fit(X_train, y_train)
    prediction = LR_pipeline.predict(X_test)
    subset_accuracy = accuracy_score(y_test,prediction)
    accuracy_per_label = [accuracy_score(y_test[l],prediction[:,i]) for i,l in enumerate(labels)]
    

    OneVsRestClassifier 执行您的训练循环正在执行的操作:分别为每个标签训练一个二元分类器,就好像它是一个二元分类问题一样。 OneVsRestClassifier 更常称为二元关联法。

    【讨论】:

      【解决方案2】:

      将pandas 输出数据框转成numpy y_test.to_numpy() = (samples, n_classes) 直接拟合;无需循环每个类别。这对我有用,测试输入不一样

      import numpy as np
      import pandas as pd
      from sklearn.model_selection import train_test_split
      from sklearn.linear_model import LogisticRegression
      from sklearn.multiclass import OneVsRestClassifier
      
      
      df = pd.read_csv("vitamin.csv")
      
      X = df[['gender', 'age', 'weight', 'height']]
      y = df[['vitamin_A', 'vitamin_C', 'vitamin_D']]
      
      X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, shuffle=True, random_state=42)
      clf = OneVsRestClassifier(LogisticRegression(solver='sag')).fit(X_test.to_numpy(), y_test.to_numpy())
      
      
      data_test1 = [[0, 57, 79, 145]] #  
      data_test2 = [[0, 59, 64, 107]] # 
      data_test3= [[0, 89, 74, 107]] # 
      y_predict1 = clf.predict(data_test1)
      y_predict2 = clf.predict(data_test2)
      y_predict3 = clf.predict(data_test3)
      print(*y_predict1)
      print(*y_predict2)
      print(*y_predict3)
      
      [1 1 0]
      [0 0 0]
      [0 0 0]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-02
        • 2017-12-22
        • 1970-01-01
        • 2021-01-25
        • 1970-01-01
        • 1970-01-01
        • 2020-03-01
        • 2023-02-11
        相关资源
        最近更新 更多