有人可以帮助我如何在python中为多类分类编写自定义F1分数吗?
编辑:我正在编辑问题以更好地了解我想做什么
这是我针对5个类别的多类别问题的自定义eval f1得分指标的功能。
def evalerror(preds, dtrain):
labels = dtrain.get_label()
preds = preds.reshape(-1, 5)
preds = preds.argmax(axis = 1)
f_score = f1_score(preds, labels, average = 'weighted')
return 'f1_score', f_score, True
注意:我要重塑的原因是验证真值的长度为252705,而preds是长度为1263525的数组,是实际值的5倍。原因是LGB为每个预测输出每个类别的概率。
下面,我将火车和验证数据转换为LGB可接受的格式。
dtrain = lgb.Dataset(train_X, label= train_Y, free_raw_data = False)
dvalid = lgb.Dataset(valid_X, label= valid_Y, free_raw_data = False,
reference= dtrain)
下面是我适合训练数据的LGB模型。如您所见,我已经将evalerror
自定义函数传递给了我在feval
处的模型,并且还将验证数据dvalid
传递给了我想在训练时查看其f1分数。
我正在训练模型10次迭代。
evals_result = {}
num_round = 10
lgb_model = lgb.train(params,
dtrain,
num_round,
valid_sets = dvalid,
feval = evalerror,
evals_result = evals_result)
随着模型接受10轮训练,验证集上每次迭代的F1分数显示在下面,这不正确,因为我的误差约为0.18。
[1] valid_0's multi_logloss: 1.46839 valid_0's f1_score: 0.183719
[2] valid_0's multi_logloss: 1.35684 valid_0's f1_score: 0.183842
[3] valid_0's multi_logloss: 1.26527 valid_0's f1_score: 0.183853
[4] valid_0's multi_logloss: 1.18799 valid_0's f1_score: 0.183909
[5] valid_0's multi_logloss: 1.12187 valid_0's f1_score: 0.187206
[6] valid_0's multi_logloss: 1.06452 valid_0's f1_score: 0.187503
[7] valid_0's multi_logloss: 1.01437 valid_0's f1_score: 0.187327
[8] valid_0's multi_logloss: 0.97037 valid_0's f1_score: 0.187511
[9] valid_0's multi_logloss: 0.931498 valid_0's f1_score: 0.186957
[10] valid_0's multi_logloss: 0.896877 valid_0's f1_score: 0.18751
但是一旦对模型进行了10次迭代训练,我将运行以下代码来预测相同的验证集。
lgb_prediction = lgb_model.predict(valid_X)
lgb_prediction = lgb_prediction.argmax(axis = 1)
lgb_F1 = f1_score(lgb_prediction, valid_Y, average = 'weighted')
print("The Light GBM F1 is", lgb_F1)
The Light GBM F1 is 0.743250263548
注意:这里我没有像在自定义函数中那样重塑,因为lgb_model.predict()
输出的是(252705,5)的numpy数组
另请注意,我传递的是valid_X
而不是dvalid
,因为在预测时,我们将必须传递原始格式,而不是像在lgb.train()
当我在同一个验证数据集上进行预测时,我得到的F1分数为0.743250263548,足够了。因此,我期望的是在第10次迭代时的有效F1分数,而训练应该与我训练模型后预测的分数相同。
有人可以帮助我解决我做错的事情。谢谢
答案 0 :(得分:1)
sklearn.metrics.f1_score(y_true, y_pred, labels=None, pos_label=1, average=’binary’, sample_weight=None)[source]
因此,您应该根据以下内容进行纠正:
#f1_score(labels , preds)
def evalerror(preds, dtrain):
labels = dtrain.get_label()
preds = preds.reshape(-1, 5)
preds = preds.argmax(axis = 1)
f_score = f1_score(labels , preds, average = 'weighted')
return 'f1_score', f_score, True
答案 1 :(得分:0)
我有同样的问题。
Lgb预测以平坦数组输出。
通过检查,我发现它像这样:
示例a
对类别i
的概率位于
num_classes*(a-1) + i
位置
关于您的代码,应该是这样的:
def evalerror(preds, dtrain):
labels = dtrain.get_label()
preds = preds.reshape(5, -1).T
preds = preds.argmax(axis = 1)
f_score = f1_score(labels , preds, average = 'weighted')
return 'f1_score', f_score, True