2014-04-28 26 views
25

ile çapraz doğrulama I hatırlama, hassas ve farklı sınıflandırıcıların bir çapraz geçerlilik testinin F-ölçü hesaplamak istiyoruz. scikit-öğrenmecross_val_score ama ne yazık ki böyle bir yöntem dönmez birden çok değer ile birlikte gelir.sklearn - Birden çok puanları

Ben üç kez cross_val_score arayarak böyle önlemleri hesaplamak olabilir ama bu verimli değildir. Daha iyi bir çözüm var mı? Temelde karışıklık matris değerleri özetliyor ve sahip kez yanlış pozitif, yanlış negatif kolayca hatırlama hesaplayabilir vs, hassas vs.

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 

: Artık

Ben bu fonksiyonu yazdım .. Ama yine de bu çözüm sevmiyorum :)

+0

'classification_report' kullanımıyla ilgili sorun nedir? Bkz. Http://scikit-learn.org/stable/modules/generated/sklearn.metrics.classification_report.html#sklearn.metrics.classification_report – EdChum

+0

Temel olarak "cross_val_score" un özünü aldınız ve bunu davanıza uyarladınız. Bu mükemmel bir seçenek gibi görünüyor, nasıl daha iyi yapılacağını görmüyorum. Sklearn kodunu değiştirmeyi düşünüyorsanız, lütfen sorunun açıklamasını ve bir geçici çözümü yanıtıma bakın. – eickenberg

+0

@EdChum bu çapraz doğrulama yapmaz. Modelin performansını tek bir ön eğitim aşamasına göre ölçersiniz. – Dror

cevap

6

Eğer mevcut çözüm mükemmel duruma adapte cross_val_score tam işlevsellik, temsil eder. Gitmenin doğru yolu gibi görünüyor.

cross_val_score değerlendirme parallelizeable hale argüman n_jobs= sürer. Bu İhtiyacınız şey ise, bir paralel döngü ile bir döngü için değiştirilmesi sklearn.externals.joblib.Parallel kullanarak içine bakmak gerekir. scikit öğrenmek daha genel bir kayda göre

, bir tartışma sorun izleyicide birden puanların sorun hakkında devam etmektedir. Temsilci bir iş parçacığı here bulunabilir. Bu yüzden gelecekteki sürümlerinde benziyor ederken scikit-öğrenme bugün itibariyle bu imkansız, golcülerin birden çıkışlarını izin verecektir.

Bunu aşmanın bir hacky (feragat!) Yolu puanı, bir sayı olup olmadığı konusunda bir koşul işareti kaldırarak, her zamankinden biraz cross_validation.py kodu değiştirmektir. Ancak, bu öneri çok versiyonu bağlıdır, bu yüzden sürümü 0.14 için sunacak.

1) IPython'da, from sklearn import cross_validation yazın ve onu cross_validation?? takip edin. Görüntülenen dosya adını not alın ve bir editörde açın (root ayrıcalıklarına ihtiyacınız olabilir).

2) Sen Zaten ilgili çizgi (1066) etiketledi this code bulacaksınız.

Bu satırların kaldırılması gerekir. ne atan döner yapmaz ise cross_val_score şok başka yerde, aşağıdaki

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

ile değiştirin (geri değiştirmek istiyorum hiç değilse), bu sorunun çözülmesi gerekir zamanlar orada ne izlemek amacıyla . Bu durumda lütfen bana bildirin.

+0

Bu durum kulağa korkutucu geliyorsa: Ben bu yama sürümü ile çalışıyorum. Bu sayıları girdiğimden beri öğreniyorum.Number' koşulu, çünkü puanlayıcılarım 20000 ile 100000 arasında puanlar döndürüyor. Her ne kadar kodun yamalanması ideal bir çözüm olmadığını itiraf etsem de ve bu fikri büyük kamuoyuna onaylamamalıyım, başka bir yerde meydana gelebilecek hataları yakalamak için durum var. Yazı hakeminizin hata ile birden çok değer döndürmediğini biliyorsanız, bu koşulu güvenli bir şekilde kaldırabilirsiniz. – eickenberg

+0

Cevabınız için teşekkür ederiz ve evet oldukça korkutucu: D Gelecek sürümün bunu uygulayacağını ümit ederek, çözümümle (veya benzer bir şeyle) ilgileneceğim. – blueSurfer

+0

Teşekkürler. Diğerlerinin bunu yararlı bulabilmesi için cevabı hala alacağım. Belirtildiği gibi, scikit öğrenmede devam eden bir sorundur ve bu problemle karşılaşan tek kişi siz değilsiniz. Cevabımı, yazdığınız kodun yapmaya çalıştığınız şeyi yapmak için mükemmel olduğunu açıkça belirterek düzenledim. – eickenberg

2

Sen Doğruluk hesaplamak için aşağıdaki kodu kullanabilirsiniz, Hassas, Hatırlama ve çapraz doğrulama adımı başına yalnızca bir kez tahmincisi takarak başka ölçütler.

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)} 

Birden çok istatistiği bir arada işlemek için cross_val_score yerine bu işlevleri sık sık kullanıyorum. İstediğiniz kalite metriklerini değiştirebilirsiniz.

2

Bu kullanabilirsiniz:

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 kaynağı Şimdi Github

6

üzerindedir scikit-öğrenme: cross_validate birden metrikleri hakkında bir model değerlendirebilirsiniz yeni fonksiyondur. Bu özellik ayrıca GridSearchCV ve RandomizedSearchCV (doc) adreslerinde de bulunur. merged recently in master ve v0.19'da satışa sunulacak.

scikit-learn doc itibaren

:

cross_validate işlevi iki şekilde cross_val_score farklıdır: 1. Bu değerlendirme için birden çok ölçü belirterek sağlar. 2. Test puanına ek olarak antrenman skorları, uyum-zamanları ve skor-zamanları içeren bir dict döndürür.

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) 

da this example bakınız:

tipik bir kullanım durumu

gider.

İlgili konular