본문 바로가기

머신러닝, 딥러닝

multi-label 분류 문제에서 f1 score는 못 사용하는 걸까?

+ 주의 : 글 내용에 오류가 있을 수 있습니다. 댓글을 참조해주세요.

 

다중 클래스 분류 문제에서 모델의 평가지표로 f1 을 넣었더니 제대로 작동하지 않았다.

accuracy를 넣으니 제대로 작동되었다.

 

왜 그럴까 했었는데,

클래스를 positive, negative로 이진 분류해야 precision, recall, f1을 구할 수 있으니 다중 클래스 분류에서는 f1 스코어를 사용 못 하는 걸까 싶었다.

 

하지만 찾아보니 사용할 수 있다.

 

방법1 : metrics.classification_report를 사용

from sklearn import metrics

# Print the confusion matrix
print(metrics.confusion_matrix(y_true, y_pred))

# Print the precision and recall, among other metrics
print(metrics.classification_report(y_true, y_pred, digits=3))

 

 

방법2 : f1_score(average='') 조절

공식문서 https://scikit-learn.org/stable/modules/generated/sklearn.metrics.f1_score.html

 

sklearn.metrics.f1_score — scikit-learn 0.24.1 documentation

 

scikit-learn.org

from sklearn.metrics import f1_score
f1_score(y_true, y_pred, average=[‘micro’, ‘macro’, ‘samples’,’weighted’ 중 하나 선택])

average를 설정함으로써 사용할 수 있다.

디폴트 값은 binary이고, positive lavel에 대한 결과를 제공한다. 이진 분류 문제에서만 작동한다. 
정규화 또는 가중치가 적용된 macro 편균인데, 평균을 계산할 때 각 클래스 레이블의 샘플 개수를 가중하여 계산한다. 가중치 적용된 마크로 평균은 레이블마다 샘플 개수가 다른 불균형한 클래스를 다룰 때 유용하다.

'micro':

Calculate metrics globally by counting the total true positives, false negatives and false positives.

true positive와 false negative, false positive의 합을 산출해 스코어를 계산한다.

-> 각 샘플이나 예측에 동일한 가중치를 부여하고자 할 때 사용한다.

 

'macro':

Calculate metrics for each label, and find their unweighted mean. This does not take label imbalance into account.

각 레이블의 unweighted된 평균(레이블이 불균형한 멀티-클래스 분류 문제에서)을 계산한다. 레이블이 불균형을 따로 고려하지 않는다.

모든 클래스에 동일한 가중치를 부여하여 분류기의 전반적인 성능을 평가한다. 가장 빈도 높은 클래스 레이블의 성능이 중요하다.

 

'weighted':

Calculate metrics for each label, and find their average weighted by support (the number of true instances for each label). This alters ‘macro’ to account for label imbalance; it can result in an F-score that is not between precision and recall.

각 레이블이 불균형해도, weight를 주어 평가지표를 계산한다. precision과 recall의 합이 아닌 F-score를 야기할 수 있다.

'samples':

Calculate metrics for each instance, and find their average (only meaningful for multilabel classification where this differs from accuracy_score

각 레이블의 평가지표를 평균 낸다.(accuracy_score와 다른 멀티-레이블 분류 문제에서만 의미 있다.)

 

고로 average='sample', 아니면 'weighted', 아니면 'micro'를 사용해도 괜찮을 것 같다.

-> 하지만 모델에 넣어봤을 때, 'sample'의 경우 동작하지 않았고 'weighted'를 넣으니 동작했다.

 

방법 3 : precision_recall_fscore_support를 사용

>>> import numpy as np
>>> from sklearn.metrics import precision_recall_fscore_support
>>> y_true = np.array(['cat', 'dog', 'pig', 'cat', 'dog', 'pig'])
>>> y_pred = np.array(['cat', 'pig', 'dog', 'cat', 'cat', 'dog'])
>>> precision_recall_fscore_support(y_true, y_pred, average='macro')
(0.22..., 0.33..., 0.26..., None)
>>> precision_recall_fscore_support(y_true, y_pred, average='micro')
(0.33..., 0.33..., 0.33..., None)
>>> precision_recall_fscore_support(y_true, y_pred, average='weighted')
(0.22..., 0.33..., 0.26..., None)

precision_recall_fscore_support를 사용해서 average를 조절하며 fscore 값을 확인할 수 있는데,

>>> precision_recall_fscore_support(y_true, y_pred, average=None,
... labels=['pig', 'dog', 'cat'])
(array([0.        , 0.        , 0.66...]),
 array([0., 0., 1.]), array([0. , 0. , 0.8]),
 array([2, 2, 2]))

labels을 직접 지정해줄 수도 있다.

 

f-1 score의 의미는 : beta가 1이라는 거다. f-score 자체에 베타값이 들어가 있어, f1 score 도 f-beta score다.

f1 score는 recall과 precision을 동등한 가중치로 두고 score를 매긴다.

f-beta score는 precision과 recall을 어느 정도로 가중치를 두느냐에 따라 beta값이 달라진다.

f-beta score는 모델이 만들어진 상태에서 스코어를 낼 때 사용한다.