2015-04-26 14 views
5

Esiste una funzione incorporata in Panda o Scikit: imparare per ricampionare secondo una strategia specificata? Voglio ricampionare i miei dati in base a una variabile categoriale.Ricampionamento in scikit-learn e/o panda

Ad esempio, se i miei dati hanno il 75% di uomini e il 25% di donne, ma mi piacerebbe formare il mio modello su 50% uomini e 50% donne. (Mi piacerebbe anche essere in grado di generalizzare a casi che non sono 50/50)

Quello che mi serve è qualcosa che ricampiona i miei dati in base alle proporzioni specificate.

+1

[StratifiedKFold] (http://scikit-learn.org/stable/modules/generated/sklearn.cross_validation.StratifiedKFold.html) – EdChum

+0

nonché [StratifiedShuffleSplit] (http: // scikit-learn. org/stabile/moduli/generata/sklearn.cross_validation.StratifiedShuffleSplit.html) – lanenok

risposta

2

Campionamento stratificato significa che la distribuzione della classe viene preservata. Se si sta cercando questo, è comunque possibile utilizzare StratifiedKFold e StratifiedShuffleSplit, purché si disponga di una variabile categoriale per la quale si desidera garantire la presenza della stessa distribuzione in ogni piega. Basta usare la variabile al posto della variabile di destinazione. Per esempio, se si dispone di una variabile categoriale nella colonna i,

skf = cross_validation.StratifiedKFold(X[:,i]) 

Tuttavia, se ho capito bene, si desidera ricampionare ad una certa distribuzione di destinazione (ad esempio 50/50) di una delle caratteristiche categoriali. Immagino che dovresti trovare il tuo metodo per ottenere un campione del genere (dividi il set di dati per valore variabile, poi prendi lo stesso numero di campioni casuali da ogni divisione). Se la tua motivazione principale è quella di bilanciare il set di allenamento per un classificatore, un trucco potrebbe essere quello di regolare il sample_weights. È possibile impostare i pesi in modo da bilanciare l'insieme di addestramento in base alla variabile desiderata:

sample_weights = sklearn.preprocessing.balance_weights(X[:,i]) 
clf = svm.SVC() 
clf_weights.fit(X, y, sample_weight=sample_weights) 

Per una distribuzione target non uniforme, si dovrà regolare i sample_weights conseguenza.

2

La mia pugnalata a una funzione per fare ciò che voglio è sotto. Spero che questo sia utile a qualcun altro.

X e sono considerati rispettivamente un DataFrame e una serie Pandas.

def resample(X, y, sample_type=None, sample_size=None, class_weights=None, seed=None): 

    # Nothing to do if sample_type is 'abs' or not set. sample_size should then be int 
    # If sample type is 'min' or 'max' then sample_size should be float 
    if sample_type == 'min': 
     sample_size_ = np.round(sample_size * y.value_counts().min()).astype(int) 
    elif sample_type == 'max': 
     sample_size_ = np.round(sample_size * y.value_counts().max()).astype(int) 
    else: 
     sample_size_ = max(int(sample_size), 1) 

    if seed is not None: 
     np.random.seed(seed) 

    if class_weights is None: 
     class_weights = dict() 

    X_resampled = pd.DataFrame() 

    for yi in y.unique(): 
     size = np.round(sample_size_ * class_weights.get(yi, 1.)).astype(int) 

     X_yi = X[y == yi] 
     sample_index = np.random.choice(X_yi.index, size=size) 
     X_resampled = X_resampled.append(X_yi.reindex(sample_index)) 

    return X_resampled 
Problemi correlati