【问题标题】:Calculate Confusion Matrix of a FastText Classifier model计算 FastText 分类器模型的混淆矩阵
【发布时间】:2018-04-09 05:49:43
【问题描述】:

我正在为 Facebook FastText 分类器模型计算 this 方式中的混淆矩阵:

#!/usr/local/bin/python3

import argparse
import numpy as np
from sklearn.metrics import confusion_matrix


def parse_labels(path):
    with open(path, 'r') as f:
        return np.array(list(map(lambda x: int(x[9:]), f.read().split())))


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Display confusion matrix.')
    parser.add_argument('test', help='Path to test labels')
    parser.add_argument('predict', help='Path to predictions')
    args = parser.parse_args()
    test_labels = parse_labels(args.test)
    pred_labels = parse_labels(args.predict)

    print(test_labels)
    print(pred_labels)

    eq = test_labels == pred_labels
    print("Accuracy: " + str(eq.sum() / len(test_labels)))
    print(confusion_matrix(test_labels, pred_labels))

我的预测和测试集是这样的

$ head -n10 /root/pexp 
__label__spam
__label__verified
__label__verified
__label__spam
__label__verified
__label__verified
__label__verified
__label__verified
__label__verified
__label__verified

$ head -n10 /root/dataset_test.csv 
__label__spam
__label__verified
__label__verified
__label__spam
__label__verified
__label__verified
__label__verified
__label__verified
__label__verified
__label__verified

模型的预测是通过这种方式在测试集上计算出来的:

./fasttext predict /root/my_model.bin /root/dataset_test.csv > /root/pexp

然后我要计算FastText混淆矩阵:

$ ./confusion.py /root/dataset_test.csv /root/pexp

但我遇到了这个错误:

Traceback (most recent call last):
  File "./confusion.py", line 18, in <module>
    test_labels = parse_labels(args.test)
  File "./confusion.py", line 10, in parse_labels
    return np.array(list(map(lambda x: int(x[9:]), f.read().split())))
  File "./confusion.py", line 10, in <lambda>
    return np.array(list(map(lambda x: int(x[9:]), f.read().split())))
ValueError: invalid literal for int() with base 10: 'spam'

我已按照建议修复了脚本以处理非数字标签:

def parse_labels(path):
    with open(path, 'r') as f:
        return np.array(list(map(lambda x: x[9:], f.read().split())))

此外,在 FastText 的情况下,测试集可能会在某些时候具有标准化标签(没有前缀 __label__),因此要转换回前缀,您可以这样做:

awk 'BEGIN{FS=OFS="\t"}{ $1 = "__label__" tolower($1) }1' /root/dataset_test.csv  > /root/dataset_test_norm.csv 

请参阅here 了解此内容。

此外,输入测试文件必须从标签列之外的其他列中剪切:

cut -f 1 -d$'\t' /root/dataset_test_norm.csv > /root/dataset_test_norm_label.csv

所以最后我们得到了混淆矩阵:

$ ./confusion.py /root/dataset_test_norm_label.csv /root/pexp
Accuracy: 0.998852852227
[[9432    21]
 [    3 14543]]

我的最终解决方案是here

[更新]

脚本现在运行良好。我在我的 FastText Node.js 实现中直接添加了混淆矩阵计算脚本,FastText.jshere

【问题讨论】:

  • 你的脚本是错误的,需要给定输入文件中的数字(查看 parse_labels 方法),而你有文本标签。
  • 嗯,所以您指的是解析标签的 return np.array(list(map(lambda x: int(x[9:]), f.read().split()))) 方法...
  • 没错。如果我理解得很好,那行期望该行的第九个字符之后的所有内容都形成一个整数;这根本不是您的数据的样子。
  • 是的,因为 fasttext 默认情况下会添加正好是 9 个字符的 __label__ 前缀。所以我的猜测是为什么标签是一个数字而不是一个字符串......因为标签通常应该是一个字符串......
  • 根本不需要删除__label__eq = test_labels == pred_labels 中的比较确实在这里比较了字符串。所以你可以稍微改进一下parse_labels()return np.array(f.readlines())

标签: machine-learning dataset evaluation confusion-matrix fasttext


【解决方案1】:
from sklearn.metrics import confusion_matrix

# predict the data
df["predicted"] = df["text"].apply(lambda x: model.predict(x)[0][0])

# Create the confusion matrix
confusion_matrix(df["labeled"], df["predicted"])


## OutPut:
# array([[5823,    8,  155,    1],
#        [ 199,   51,   22,    0],
#        [ 561,    2,  764,    0],
#        [  48,    0,    4,    4]], dtype=int64)

【讨论】:

    猜你喜欢
    • 2018-04-01
    • 2017-02-25
    • 2020-06-23
    • 2017-09-25
    • 2018-12-19
    • 2021-10-09
    • 2021-03-15
    • 2019-07-07
    相关资源
    最近更新 更多