【问题标题】:customized metric function for multi class in lightgbmlightgbm中多类的自定义度量函数
【发布时间】:2018-07-24 12:18:30
【问题描述】:

在我的数据中,大约有 70 个类,我正在使用 lightGBM 来预测正确的类标签。

在 R 中,希望有一个自定义的“度量”函数,我可以在其中评估 lightgbm 的前 3 个预测是否覆盖了真实标签。

here 的链接很鼓舞人心

def lgb_f1_score(y_hat, data):
    y_true = data.get_label()
    y_hat = np.round(y_hat) # scikits f1 doesn't like probabilities
    return 'f1', f1_score(y_true, y_hat), True

但是我不知道要起作用的参数的维度。似乎数据由于某种原因被打乱了。

【问题讨论】:

  • y_truey_hat 是数组,对吧?如果是这样,为什么不直接打印尺寸?除非您使用 CV,否则不应发生洗牌。免责声明:我不使用 R,但我在 python 中使用 lightgbm 有一些经验

标签: r lightgbm


【解决方案1】:

Scikit-learn 实现

from sklearn.metrics import f1_score

def lgb_f1_score(y_true, y_pred):
    preds = y_pred.reshape(len(np.unique(y_true)), -1)
    preds = preds.argmax(axis = 0)
    print(preds.shape)
    print(y_true.shape)
    return 'f1', f1_score(y_true, preds,average='weighted'), True

【讨论】:

  • 这会产生:AttributeError: 'Dataset' object has no attribute 'reshape'。此外,第一个参数应该是预测值,第二个参数应该是真实值。你用相反的方式命名它们。
【解决方案2】:

在阅读了lgb.trainlgb.cv 的文档后,我不得不创建一个单独的函数get_ith_pred,然后在lgb_f1_score 中重复调用它。

函数的文档字符串解释了它是如何工作的。我使用了与 LightGBM 文档中相同的参数名称。这适用于任意数量的类,但不适用于二元分类。在二进制情况下,preds 是一个包含正类概率的一维数组。

from sklearn.metrics import f1_score

def get_ith_pred(preds, i, num_data, num_class):
    """
    preds: 1D NumPY array
        A 1D numpy array containing predicted probabilities. Has shape
        (num_data * num_class,). So, For binary classification with 
        100 rows of data in your training set, preds is shape (200,), 
        i.e. (100 * 2,).
    i: int
        The row/sample in your training data you wish to calculate
        the prediction for.
    num_data: int
        The number of rows/samples in your training data
    num_class: int
        The number of classes in your classification task.
        Must be greater than 2.
    
    
    LightGBM docs tell us that to get the probability of class 0 for 
    the 5th row of the dataset we do preds[0 * num_data + 5].
    For class 1 prediction of 7th row, do preds[1 * num_data + 7].
    
    sklearn's f1_score(y_true, y_pred) expects y_pred to be of the form
    [0, 1, 1, 1, 1, 0...] and not probabilities.
    
    This function translates preds into the form sklearn's f1_score 
    understands.
    """
    # Only works for multiclass classification
    assert num_class > 2

    preds_for_ith_row = [preds[class_label * num_data + i]
                        for class_label in range(num_class)]
    
    # The element with the highest probability is predicted
    return np.argmax(preds_for_ith_row)

    
def lgb_f1_score(preds, train_data):
    y_true = train_data.get_label()

    num_data = len(y_true)
    num_class = 70
    
    y_pred = []
    for i in range(num_data):
        ith_pred = get_ith_pred(preds, i, num_data, num_class)
        y_pred.append(ith_pred)
    
    return 'f1', f1_score(y_true, y_pred, average='weighted'), True

【讨论】:

    猜你喜欢
    • 2019-09-23
    • 2019-05-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 2019-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多