【机器学习】多类分类性能评价之宏平均(macro-average)与微平均(micro-average)

通常,我们在评价classifier的性能时使用的是accuracy

考虑在多类分类的背景下

accuracy = (分类正确的样本个数) / (分类的所有样本个数)

这样做其实看上去也挺不错的,不过可能会出现一个很严重的问题:例如某一个不透明的袋子里面装了1000台手机,其中有600台iphone6, 300台galaxy s6, 50台华为mate7,50台mx4(当然,这些信息分类器是不知道的。。。)。如果分类器只是简单的把所有的手机都预测为iphone6, 那么通过上面的公式计算的准确率accuracy为0.6,看起来还不错;可是三星,华为和小米的全部预测错了。如果再给一个袋子,里面装着600台galaxy s6, 300台mx4, 50台华为mate7,50台iphone,那这个分类器立马就爆炸了,连回家带孩子的要求都达不到

所以,仅仅用accuracy来衡量一个分类器的性能是很不科学的

为此,引入了宏平均(micro-average)的概念

介绍宏平均之前,还要介绍几个概念:

(1)precision(准确率,查准率)

(2)recall(召回率,查全率)

(3)F-measure

文字性的概念我就不水,我从符号上来表示一下吧:

多类分类问题中,分类结果一般有4种情况:

  • 属于类C的样本被正确分类到类C,记这一类样本数为 TP
  • 不属于类C的样本被错误分类到类C,记这一类样本数为 FP
  • 属于类别C的样本被错误分类到类C的其他类,记这一类样本数为 TN
  • 不属于类别C的样本被正确分类到了类别C的其他类,记这一类样本数为 FN                     

从字面意思上来说,某一类别C的准确率(查准率)可以理解为预测该类样本的准确性:

precision = TP / (TP + FP) 

这里很好理解, TP+FP实际上就是分类器在分类时,预测为类别C的样本个数

而某一个类别C的召回率(查全率)可以理解为,你预测正确的类别C的样本对于样本集中类别C的样本的覆盖程度,如果完全覆盖,那么recall就是100%

recall = TP / (TP + TN)

这里的TP+TN表示样本集中,真实类标为C的样本的个数

单一的用recall或者precision来评价分类器也是不合理的,譬如文章开头说到的那个简单的classifier

我们通过公式可以惊奇的发现在两个样本集上的recall都是100%,这是因为所有的iphone6样本,分类器都可以把它预测对,但是准确率就大不相同了;在第一个数据集上的准确率precision为0.6,但是第二个样本集上的准确率只有可怜的0.05;对于第二个样本集的结果,我可以说classifier很好,因为recall很高,也可以说classifier不好,因为precision很低。不过很明显,这些说法都是不合理的;综合考虑两种指标才是直观的比较可靠的指标。

现在就引入F-measure,计算公式如下

F- measure = (A + 1) * precision * recall / (A ^ 2 * precision + recall)

(不知道怎么写公式,就直接用文字写的,感觉有点挫)

如果A取1,那么F-measure实际上就是precison和recall的调和平均值2*precision*recall / (precision + recall), 此时的F-measure就称为F1值

把这些概念说了, 就回到刚才的宏平均的计算

把所有类的F1值取一个算术平均就得到了Macro-average

微平均Micro-average=(TP + FP) / (TP + TN + FP + FN)

分母就是输入分类器的预测样本个数,分子就是预测正确的样本个数(无论类别)

微平均实际上就是在文章开头说的accuracy


写到这里就差不多了,最后以一个例子来收尾把

考虑现在输入分类器的样本有10个,他们属于类别A B C

假设这10个样本的真实类标为(有序)和分类器预测的类标分别是: 

真实:A A A C B C A B B C

预测:A A C B A C A C B C

precision(A) = 3(正确预测为A类的样本个数为3) / 4(预测为A类的样本数为4) = 0.75  recall(A) = 3 / 4(真实A类样本有4个) = 0.75  

precision(B) = 1 / 2 = 0.5   recall(B) = 1 / 3 = 0.3333

precision(C) = 2 / 4 = 0.5  recall(C) = 2 / 3 = 0.6667

F值计算出来之后,取算术平均就是Macro-average

Micro-average = 6(预测正确的样本个数) / 10 = 0.6


宏平均比微平均更合理,但也不是说微平均一无是处,具体使用哪种评测机制,还是要取决于数据集中样本分布

  • 19
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
以下是用lgb模型进行6分类,并使用StratifiedKFold,评价指标macro-f1的示例代码: ```python import lightgbm as lgb from sklearn.model_selection import StratifiedKFold from sklearn.metrics import f1_score # 假设数据集的特征矩阵为 X,标签为 y # 定义模型参数 params = { 'boosting_type': 'gbdt', 'objective': 'multiclass', 'num_class': 6, 'metric': 'multi_logloss', 'num_leaves': 31, 'learning_rate': 0.05, 'feature_fraction': 0.9, 'bagging_fraction': 0.8, 'bagging_freq': 5, 'verbose': -1, 'random_state': 2021 } # 定义StratifiedKFold交叉验证 n_splits = 5 skf = StratifiedKFold(n_splits=n_splits, shuffle=True, random_state=2021) # 定义输出变量 oof_preds = np.zeros(X.shape[0]) class_preds = np.zeros(X.shape[0]) # 开始交叉验证 for fold, (train_idx, valid_idx) in enumerate(skf.split(X, y)): print("Fold", fold+1) X_train, X_valid = X[train_idx], X[valid_idx] y_train, y_valid = y[train_idx], y[valid_idx] # 定义训练数据 lgb_train = lgb.Dataset(X_train, y_train) lgb_valid = lgb.Dataset(X_valid, y_valid) # 训练模型 model = lgb.train(params, lgb_train, valid_sets=[lgb_valid], num_boost_round=10000, early_stopping_rounds=100, verbose_eval=100) # 对验证集进行预测 valid_preds = model.predict(X_valid, num_iteration=model.best_iteration) oof_preds[valid_idx] = valid_preds.argmax(axis=1) class_preds[valid_idx] = valid_preds.max(axis=1) print("-" * 50) # 输出交叉验证结果 macro_f1 = f1_score(y, oof_preds, average='macro') print("Overall Macro-F1:", macro_f1) ``` 在这个示例中,我们使用了sklearn中的f1_score函数来计算macro-f1。在计算f1_score时,需要将参数average设为'macro'。最终输出结果为整个数据集上的macro-f1。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值