2013-05-08 2 views
6

Gibt es einen integrierten Weg, um scikit-learn zu erhalten, um eine geschichtete k-fache Kreuzvalidierung durchzuführen? Dies ist eine der häufigsten CV-Methoden, und ich bin überrascht, dass ich dafür keine integrierte Methode finden konnte.Randomisierte geschichtete k-fache Kreuzvalidierung in scikit-learn?

Ich sah, dass cross_validation.KFold() hat eine Shuffling-Flag, aber es ist nicht geschichtet. Leider hat cross_validation.StratifiedKFold() keine solche Option, und cross_validation.StratifiedShuffleSplit() erzeugt keine disjunkten Falten.

Fehle ich etwas? Ist das geplant?

(natürlich kann ich das von mir implementieren)

Antwort

-3

Soweit ich weiß, das tatsächlich umgesetzt wird Scikit-Learn.

""“ Geschichtete ShuffleSplit Kreuzvalidierung Iterator

Bietet Zug/Test Indizes Daten in dem Zug-Prüfgeräten zu spalten.

Diese Kreuzvalidierung Objekt eine Zusammenführung von StratifiedKFold und ShuffleSplit, die stratifizierte randomisierte Falten zurückgibt. Die Falten werden hergestellt, indem der Prozentsatz der Proben für jede Klasse beibehalten wird.

Hinweis: Wie bei der ShuffleSplit-Strategie garantieren geschichtete Zufallsspalte nicht, dass alle Falten unterschiedlich sind, obwohl dies für große Datensätze immer noch sehr wahrscheinlich ist. „““

+0

Wie ich in meiner Frage schrieb, StratifiedShuffleSplit() tut nicht eine gemischte Version von StratifiedKFold(), dh Mischen vor StratifiedKFold(). Dies wird sogar im letzten Satz Ihrer Antwort erwähnt. KFold CV erfordert, dass es keinen Schnittpunkt zwischen den Falten gibt und dass ihre Vereinigung der gesamte Datensatz ist. – Bitwise

+0

Ah, ja die Falten sind nicht garantiert nicht zu trennen. Tut mir leid, dass ich nicht bis zum Ende Ihrer Frage gelesen habe. – rd108

+0

Sie sollten Ihre Antwort löschen! Bitte... – Merlin

2

Ich dachte, ich meine Lösung für den Fall veröffentlichen würde, ist es an jemand anderen nützlich

from collections import defaultdict 
import random 
def strat_map(y): 
    """ 
    Returns permuted indices that maintain class 
    """ 
    smap = defaultdict(list) 
    for i,v in enumerate(y): 
     smap[v].append(i) 
    for values in smap.values(): 
     random.shuffle(values) 
    y_map = np.zeros_like(y) 
    for i,v in enumerate(y): 
     y_map[i] = smap[v].pop() 
    return y_map 

########## 
#Example Use 
########## 
skf = StratifiedKFold(y, nfolds) 
sm = strat_map(y) 
for test, train in skf: 
    test,train = sm[test], sm[train] 
    #then cv as usual 


####### 
#tests# 
####### 
import numpy.random as rnd 
for _ in range(100): 
    y = np.array([0]*10 + [1]*20 + [3] * 10) 
    rnd.shuffle(y) 
    sm = strat_map(y) 
    shuffled = y[sm] 
    assert (sm != range(len(y))).any() , "did not shuffle" 
    assert (shuffled == y).all(), "classes not in right position" 
    assert (set(sm) == set(range(len(y)))), "missing indices" 


for _ in range(100): 
    nfolds = 10 
    skf = StratifiedKFold(y, nfolds) 
    sm = strat_map(y) 
    for test, train in skf: 
     assert (sm[test] != test).any(), "did not shuffle" 
     assert (y[sm[test]] == y[test]).all(), "classes not in right position" 
1

Hier meine Implementierung von geschichteten Shuffle aufgeteilt in Trainings- und Testsatz ist:

import numpy as np 

def get_train_test_inds(y,train_proportion=0.7): 
    '''Generates indices, making random stratified split into training set and testing sets 
    with proportions train_proportion and (1-train_proportion) of initial sample. 
    y is any iterable indicating classes of each observation in the sample. 
    Initial proportions of classes inside training and 
    test sets are preserved (stratified sampling). 
    ''' 

    y=np.array(y) 
    train_inds = np.zeros(len(y),dtype=bool) 
    test_inds = np.zeros(len(y),dtype=bool) 
    values = np.unique(y) 
    for value in values: 
     value_inds = np.nonzero(y==value)[0] 
     np.random.shuffle(value_inds) 
     n = int(train_proportion*len(value_inds)) 

     train_inds[value_inds[:n]]=True 
     test_inds[value_inds[n:]]=True 

    return train_inds,test_inds 


y = np.array([1,1,2,2,3,3]) 
train_inds,test_inds = get_train_test_inds(y,train_proportion=0.5) 
print y[train_inds] 
print y[test_inds] 

Dieser Code gibt:

[1 2 3] 
[1 2 3]