2

私のデータには約 70 のクラスがあり、lightGBM を使用して正しいクラス ラベルを予測しています。

R では、lightgbm による上位 3 つの予測が真のラベルをカバーしているかどうかを評価できる、カスタマイズされた「メトリック」関数が必要です。

ここのリンクは見るのに刺激的です

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

ただし、機能する引数の次元はわかりません。何らかの理由でデータがシャッフルされているようです。

4

2 に答える 2

1

lgb.trainlgb.cvのドキュメントを読んだ後、別の関数を作成し、それを.xmlget_ith_pred内で繰り返し呼び出す必要がありlgb_f1_scoreました。

関数の docstring は、それがどのように機能するかを説明しています。LightGBM ドキュメントと同じ引数名を使用しました。これは任意の数のクラスで機能しますが、バイナリ分類では機能しません。バイナリの場合、preds陽性クラスの確率を含む 1D 配列です。

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
于 2021-03-01T16:11:12.230 に答える