카테고리 보관물: scikit

기계학습 라이브러리인 scikit-learn 예제 코드들

기계학습 평가 척도. precision recall

Published / by greennuri

엄태웅님의 youtube 링크

여기서는 preision, recall에 대한 설명 보다 왜 이런 평가 지표를 쓸가에 대해서 잘은 모르지만 최대한(제 나름) 설명 하려고합니다.

일반적으로 지도학습(대부분 지도학습 이지만 ^^)에서 성능을 평가 하는 척도는 정확도 (accuracy)인데요.

deep learning이나 machine learning 예제로 나오는 코드 보면 거의 대부분 정확도(acc)라는 지수로 모델의 성능이 좋다 나쁘다를 평가 합니다.

cnn쪽에서는 예외적으로 top-1 error, top-5 error을 쓰는데요 우선 그것은 제외하겠습니다.

acc(정확도)는 고양이 사진 100장, 개 사진 100장 이 있고 고양이 사진은 90장, 개 사진은 90장으로 판별 했다고 볼때, 180(맞춘 전체값) / 200(전체 데이터셋 크기) 해서 90%의 값이 나옵니다

acc(정확도)는 전체 데이터 중에서 정답을 맞춘 비율을 의미합니다.

더 자세한 정의는 여기 참고 하세요

그런데, 고양이랑 개 사진은 애호가가 많아서 인터넷에서 엄청 찾을 수 있는데, 좀 드문 수달도 같이 학습 시켜서 고양이 사진 100장, 개 사진 100장, 수달 사진 10장으로 기계학습을 시켜서 고양이 사진 89장, 개 사진 85장, 수달 사진 1장을 제대로 인식 했다고 하면 전체 인식률은

89(고양이) + 85(개) +1(수달) / 210(전체) = 83.333 약 83% 나옵니다

그런데 수달은 10장 중에 1장만 제대로 인식 했는데 전체 정확도는 83%입니다

뭐가 이상하지 않나요?

문제를 더 간단히 해보면

고양이 사진 90장, 수달 사진 10장으로 어떤 모델을 학습하고,  제대로 인식된 고양이 사진이 80장, 수달 사진이 3장 이면 정확도는

80 + 3 / 100 = 83 % 정확도

수달은 10장 중에 3장만 제대로 뽑아 냈는데, 정확도는 83% ???

이러한 경우는 학습 시키는 데이터의 수량이 비슷하지 않아서 생기는 문제입니다. 이러한 경우 정확도가 아닌 다른 평가 척도를 가져와야 하는데 그중 대표적인데 precision, recall, f1입니다. 자세한 설명은 링크를 통해 들어보세요

설명을 워낙 잘 하셔서 링크로 대신합니다.

 

원문

scikit으로 mnist나 iris 같은 데이터를 지도 학습 시킨다고 할때

어떠한 지도학습 모델에 적용 시키느냐에 따라서 성능(acc)이 차이가 나지만,

동일한 지도학습 모델에서도 파라메터 최적화 여부에 따라서 성능이 더 좋아 지기도 합니다.

여기서는 scikit-learn에서 제공하는 grid_search를 통해 학습 모델 최적화에 대해서 얘기 합니다.

from __future__ import print_function

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import classification_report
from sklearn.svm import SVC

print(__doc__)

# Loading the Digits dataset
digits = datasets.load_digits()

# To apply an classifier on this data, we need to flatten the image, to
# turn the data in a (samples, feature) matrix:
n_samples = len(digits.images)
X = digits.images.reshape((n_samples, -1))
y = digits.target

# Split the dataset in two equal parts
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.5, random_state=0)

# Set the parameters by cross-validation
tuned_parameters = [{'kernel': ['rbf'], 'gamma': [1e-3, 1e-4],
                     'C': [1, 10, 100, 1000]},
                    {'kernel': ['linear'], 'C': [1, 10, 100, 1000]}]

scores = ['precision', 'recall']

for score in scores:
    print("# Tuning hyper-parameters for %s" % score)
    print()

    clf = GridSearchCV(SVC(), tuned_parameters, cv=5,
                       scoring='%s_macro' % score)
    clf.fit(X_train, y_train)

    print("Best parameters set found on development set:")
    print()
    print(clf.best_params_)
    print()
    print("Grid scores on development set:")
    print()
    means = clf.cv_results_['mean_test_score']
    stds = clf.cv_results_['std_test_score']
    for mean, std, params in zip(means, stds, clf.cv_results_['params']):
        print("%0.3f (+/-%0.03f) for %r"
              % (mean, std * 2, params))
    print()

    print("Detailed classification report:")
    print()
    print("The model is trained on the full development set.")
    print("The scores are computed on the full evaluation set.")
    print()
    y_true, y_pred = y_test, clf.predict(X_test)
    print(classification_report(y_true, y_pred))
    print()

# Note the problem is too easy: the hyperparameter plateau is too flat and the
# output model is the same for precision and recall with ties in quality.

위 예제는 원문에 있는 코드를 그대로 가져 왔습니다

예제 코드에서는 svm을 최적화 하는 예제

보통 일반적으로 학습을 하려 하면 다음과 같이 수행.

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.5, random_state=0)
#학습 및 평가 데이터셋 분리 
clf = SVC()
clf.fit(X_train, y_train)
#위 코드를 실행 시키면 주어진 데이터에서 알아서 학습을 수행

위 코드에서 나오는 정확도(acc)는 svc 모델의 초기값을 기반으로 나온 정확도

이걸 grid_search를 통해 다음과 같이 최적화 시킴

# Set the parameters by cross-validation
tuned_parameters = [{'kernel': ['rbf'], 'gamma': [1e-3, 1e-4],
                     'C': [1, 10, 100, 1000]},
                    {'kernel': ['linear'], 'C': [1, 10, 100, 1000]}]

scores = ['precision', 'recall']

for score in scores:
    print("# Tuning hyper-parameters for %s" % score)
    print()

    clf = GridSearchCV(SVC(), tuned_parameters, cv=5,
                       scoring='%s_macro' % score)
    clf.fit(X_train, y_train)

    print("Best parameters set found on development set:")
    print()
    print(clf.best_params_)
    print()
    print("Grid scores on development set:")
    print()
    means = clf.cv_results_['mean_test_score']
    stds = clf.cv_results_['std_test_score']
    for mean, std, params in zip(means, stds, clf.cv_results_['params']):
        print("%0.3f (+/-%0.03f) for %r"
              % (mean, std * 2, params))
    print()

    print("Detailed classification report:")
    print()
    print("The model is trained on the full development set.")
    print("The scores are computed on the full evaluation set.")
    print()
    y_true, y_pred = y_test, clf.predict(X_test)
    print(classification_report(y_true, y_pred))
    print()

tunes_parameters 변수에 해당 모델(여기서는 svc)에서 최적화 시킬 파라메터를 정의 한다.

scores 변수에는 precision, recall 어느 지수를 기준으로 최적화 할지를 지정한것.

위 코드를 수행 하면 precision 기준 최적화 한 셋트(tunes_parameters에 나온 파라메터를 다 대입해서 수행)와 recall 기준 최적화 한 셋트를 수행

grid_search는 위의 그림 중 왼쪽에 해당, 모델을 이루고 있는 하이퍼 파라메터를 그림과 같이 그리드를 구성하고 각각 지점에서 성능을 측정한다.

그리고 scikit_learn에서 최적화 알고리즘중 하나인 random_search는 위 그림 중 오른쪽에 나타난데로, 하이퍼파라메터들을 랜덤하게 골라서 최적화를 수행한다.