2014-04-28 8 views
25

와 교차 검증 나는 리콜, 정밀 다른 분류에 대한 교차 검증 테스트의 F-측정을 계산하고 싶습니다. scikit-learncross_val_score과 함께 제공되지만 불행히도 이러한 방법은 여러 값을 반환하지 않습니다.sklearn - 여러 점수

나는 세 번 cross_val_score를 호출하여 조치를 계산할 수 있지만 효율적이지 않습니다. 더 나은 해결책이 있습니까? 그것은 기본적으로 혼란 매트릭스 값을 요약하고 일단 위양성, 위음성 쉽게 리콜을 계산할 수 등 정밀 등

from sklearn import metrics 

def mean_scores(X, y, clf, skf): 

    cm = np.zeros(len(np.unique(y)) ** 2) 
    for i, (train, test) in enumerate(skf): 
     clf.fit(X[train], y[train]) 
     y_pred = clf.predict(X[test]) 
     cm += metrics.confusion_matrix(y[test], y_pred).flatten() 

    return compute_measures(*cm/skf.n_folds) 

def compute_measures(tp, fp, fn, tn): 
    """Computes effectiveness measures given a confusion matrix.""" 
    specificity = tn/(tn + fp) 
    sensitivity = tp/(tp + fn) 
    fmeasure = 2 * (specificity * sensitivity)/(specificity + sensitivity) 
    return sensitivity, specificity, fmeasure 

: 지금까지

나는이 기능을 썼다 ..하지만 여전히 나는이 솔루션을 좋아하지 않습니다 :)

+0

'classification_report'를 사용하는 것이 잘못된 이유는 무엇입니까? http://scikit-learn.org/stable/modules/generated/sklearn.metrics.classification_report.html#sklearn.metrics.classification_report – EdChum

+0

기본적으로 'cross_val_score'의 본질을 취하여이를 귀하의 경우에 적용했습니다. 이것은 완벽하게 실행 가능한 옵션처럼 보입니다. 더 나은 방법을 찾지 못합니다. sklearn 코드를 수정하려는 경우를 대비하여 문제에 대한 설명과 해결 방법에 대한 내 대답을 참조하십시오. – eickenberg

+0

@EdChum 이것은 교차 유효성 검사를 수행하지 않습니다. 단일 사전 훈련 단계를 기반으로 모델의 성능을 측정합니다. – Dror

답변

6

당신이 제시하는 해결책은 귀하의 상황에 완벽하게 적응 된 cross_val_score의 기능을 정확하게 나타냅니다. 그것은 올바른 길을가는 것처럼 보입니다.

cross_val_score은 인수 n_jobs=을 사용하여 평가를 병렬 처리 가능하게 만듭니다. 이것이 필요한 경우, sklearn.externals.joblib.Parallel을 사용하여 for 루프를 병렬 루프로 대체해야합니다.

scikit의 문제 추적기에서 여러 점수 문제에 대한 토론이 진행되고 있습니다. 대표 스레드는 here입니다. 그래서 scikit-learn의 미래 버전이 scorers의 여러 출력을 허용하는 것처럼 보이지만, 현재로서는 불가능합니다.

이 문제를 해결받을 수있는 해키 (면책 조항!) 방법은 당신의 점수는 숫자 여부에 대한 조건 확인을 제거하여, 지금까지 약간 cross_validation.py의 코드를 변경하는 것입니다. 그러나이 제안은 버전에 따라 다르므로 버전 0.14으로 알려 드리겠습니다.

1) IPython에서 from sklearn import cross_validation을 입력 한 다음 cross_validation??을 입력하십시오. 표시되는 파일 이름을 메모하고 편집기에서 엽니 다 (루트 권한이 필요할 수도 있음).

2) this code을 찾을 수 있습니다. 여기에서 이미 관련된 줄 (1066)을 태그했습니다. 그것은 말합니다

if not isinstance(score, numbers.Number): 
     raise ValueError("scoring must return a number, got %s (%s)" 
         " instead." % (str(score), type(score))) 

이 줄을 제거해야합니다. 무엇 당신의 득점 반환하지 않는 경우 cross_val_score 초크 다른 곳에서, 다음

if not isinstance(score, numbers.Number): 
     pass 
     # raise ValueError("scoring must return a number, got %s (%s)" 
     #     " instead." % (str(score), type(score))) 

로 교체 (다시 변경하려면 어느 경우),이 문제를 해결해야 번이 무엇인지를 추적하기 위해 . 이 경우 알려주십시오.

+0

)이 경우가 무섭다는 것을 대비하여 : 나는이 패치 된 버전의 scikit으로 작업 해왔다. 내 scorers가 20000과 100000 사이의 점수를 반환하기 때문에이 numbers.Number' 조건의 도입 이후 배웁니다. 코드를 패치하는 것이 이상적인 해결책은 아니지만 그 아이디어를 일반인에게 공개해서는 안되며 다른 곳에서 발생할 수있는 오류를 잡기위한 조건이 있음을 인정합니다. 기록원이 오류로 여러 값을 반환하지 않는다는 것을 알고 있으면 안전하게 그 조건을 제거 할 수 있습니다. – eickenberg

+0

답장을 보내 주셔서 감사 드리며 매우 귀찮습니다. D 향후 버전에서이를 구현할 수 있기를 희망합니다. – blueSurfer

+0

감사합니다. 나는 다른 사람들이 이것을 유용하게 찾을 수 있기 때문에 여전히 답을 알려줄 것입니다. 지적했듯이, 그것은 scikit learn에서 진행중인 문제이며,이 문제를 만난 유일한 사람은 아닙니다. 필자가 작성한 코드가 당신이하려는 것을하기에 완벽하다는 것을 명확히하기 위해 나의 대답을 편집했다. – eickenberg

2

정확도, 정밀도, 회수율 및 다른 메트릭을 계산하기 위해 교차 검증 단계마다 견적기를 한 번만 피팅하면 다음 코드를 사용할 수 있습니다.

def get_true_and_pred_CV(estimator, X, y, n_folds, cv, params): 
    ys = [] 
    for train_idx, valid_idx in cv: 
     clf = estimator(**params) 
     if isinstance(X, np.ndarray): 
      clf.fit(X[train_idx], y[train_idx]) 
      cur_pred = clf.predict(X[valid_idx]) 
     elif isinstance(X, pd.DataFrame): 
      clf.fit(X.iloc[train_idx, :], y[train_idx]) 
      cur_pred = clf.predict(X.iloc[valid_idx, :]) 
     else: 
      raise Exception('Only numpy array and pandas DataFrame ' \ 
          'as types of X are supported') 

     ys.append((y[valid_idx], cur_pred)) 
    return ys 


def fit_and_score_CV(estimator, X, y, n_folds=10, stratify=True, **params): 
    if not stratify: 
     cv_arg = sklearn.cross_validation.KFold(y.size, n_folds) 
    else: 
     cv_arg = sklearn.cross_validation.StratifiedKFold(y, n_folds) 

    ys = get_true_and_pred_CV(estimator, X, y, n_folds, cv_arg, params)  
    cv_acc = map(lambda tp: sklearn.metrics.accuracy_score(tp[0], tp[1]), ys) 
    cv_pr_weighted = map(lambda tp: sklearn.metrics.precision_score(tp[0], tp[1], average='weighted'), ys) 
    cv_rec_weighted = map(lambda tp: sklearn.metrics.recall_score(tp[0], tp[1], average='weighted'), ys) 
    cv_f1_weighted = map(lambda tp: sklearn.metrics.f1_score(tp[0], tp[1], average='weighted'), ys) 

    # the approach below makes estimator fit multiple times 
    #cv_acc = sklearn.cross_validation.cross_val_score(algo, X, y, cv=cv_arg, scoring='accuracy') 
    #cv_pr_weighted = sklearn.cross_validation.cross_val_score(algo, X, y, cv=cv_arg, scoring='precision_weighted') 
    #cv_rec_weighted = sklearn.cross_validation.cross_val_score(algo, X, y, cv=cv_arg, scoring='recall_weighted') 
    #cv_f1_weighted = sklearn.cross_validation.cross_val_score(algo, X, y, cv=cv_arg, scoring='f1_weighted') 
    return {'CV accuracy': np.mean(cv_acc), 'CV precision_weighted': np.mean(cv_pr_weighted), 
      'CV recall_weighted': np.mean(cv_rec_weighted), 'CV F1_weighted': np.mean(cv_f1_weighted)} 

종종 cross_val_score 대신이 함수를 사용하여 여러 통계를 모두 계산합니다. 원하는대로 품질 메트릭을 변경할 수 있습니다.

2

이를 사용할 수 있습니다

from sklearn import metrics 
from multiscorer import MultiScorer 
import numpy as np 

scorer = MultiScorer({ 
    'F-measure' : (f1_score, {...}), 
    'Precision' : (precision_score, {...}), 
    'Recall' : (recall_score, {...}) 
}) 

... 

cross_val_score(clf, X, target, scoring=scorer) 
results = scorer.get_results() 

for name in results.keys(): 
    print '%s: %.4f' % (name, np.average(results[name])) 

multiscorer의 소스에서 이제 Github

6

에 scikit 배우기 : cross_validate 여러 메트릭에 대한 모델을 평가할 수있는 새로운 기능입니다. 이 기능은 GridSearchCVRandomizedSearchCV (doc)에서도 사용할 수 있습니다. merged recently in master이고 v0.19에서 사용할 수 있습니다.

scikit-learn doc 가입일

:

cross_validate 함수는 두 가지 상이한 cross_val_score 1.이 평가를 위해 다수의 측정 항목을 지정 허용한다. 2. 테스트 점수 외에 훈련 득점, 경기 시간 및 득점 시간이 포함 된 사전을 반환합니다.

from sklearn.svm import SVC 
from sklearn.datasets import load_iris 
from sklearn.model_selection import cross_validate 
iris = load_iris() 
scoring = ['precision', 'recall', 'f1'] 
clf = SVC(kernel='linear', C=1, random_state=0) 
scores = cross_validate(clf, iris.data, iris.target == 1, cv=5, 
         scoring=scoring, return_train_score=False) 

this example를 참조하십시오

일반적인 사용 사례

에 의해 간다.