Hedef tabakalaşma ile Grup K katlama

Sep 10 2020

Bir pd.DataFrame var

pd.DataFrame({
    'person': ['a', 'b', 'c', 'aa', 'bb', 'cc', 'aaa', 'bbb', 'ccc'],
    'group': [10, 10, 10, 20, 20, 20, 30, 30, 30],
    'target': [1, 2, 2, 3, 2, 3, 1, 2, 3]
})

Df'yi eğitime ayırmak ve birkaç kez gruba göre test etmek (K-Katlama) istiyorum, bu nedenle eğitim ve test, birbirini dışlayan grup alt kümelerinden örnekler içerir . Örneğin, test [10, 20] gruplarından örnekler içeriyorsa, test yalnızca [30] grubundan örnekler içermelidir. Ayrıca hedefe göre tabakalaşmayı sürdürmek istiyorum. Bu nedenle, grup alt kümelerinin oluşturulması için hedef dağıtım da dikkate alınır. Bu nasıl mümkün olaiblir? Scikit-learn'de yardımcı olabilecek hiçbir şey bulamadık.

Uygulamada yaklaşık 500 bin sıra, 2,5 bin farklı kişi, 30 grup ve aşağıdaki hedef dağılımı olan bir df var

Yanıtlar

1 etiennedm Sep 10 2020 at 00:40

Hem grupları hem de tabakalaşmayı kullanmak için kendi kodunuzu yazmanız gerekiyor gibi görünüyor. Eğitimde ve / veya test setinde kaçınılmaz olarak numune kaybedeceğinizi unutmayın (şanslı değilseniz).

Bunu başarmanın bir yolu şudur:

  1. gruplara göre ayırın ( GroupKFold yöntemini şuradan kullanabilirsiniz sklearn)
  2. eğitim / test setlerinde hedeflerin dağılımını kontrol edin.
  3. dağılımları dengelemek için eğitim veya test setindeki hedefleri rastgele kaldırın.

Not : Böyle bir algoritma kullanılarak bir grubun kaybolması mümkündür. Eğitim / test setlerini dengelerken hedefleri rastgele kaldırmamayı tercih edebilirsiniz.


İşte örnek bir kod

import pandas as pd
import numpy as np
from sklearn.model_selection import GroupKFold

df = pd.DataFrame({
    'person': ['a', 'b', 'c', 'aa', 'bb', 'cc', 'aaa', 'bbb', 'ccc'],
    'group': [10, 10, 20, 20, 20, 20, 20, 30, 30],
    'target': [1, 2, 2, 3, 2, 3, 1, 2, 3]
})

X = df['person']
y = df['target']
groups = df['group'].values
group_kfold = GroupKFold(n_splits=3)
group_kfold.get_n_splits(X, y, groups)

# First split by groups
for train_index, test_index in group_kfold.split(X, y, groups):
    print("Groups split: TRAIN:", train_index, "TEST:", test_index)
    y_train_grouped, y_test_grouped = y[train_index], y[test_index]

    final_train_index = []
    final_test_index = []
    # Then balance the distributions for each target
    for target in df['target'].unique():
        target_train_index = y_train_grouped[y_train_grouped == target].index.tolist()
        target_test_index = y_test_grouped[y_test_grouped == target].index.tolist()
        n_training = len(target_train_index)
        n_testing = len(target_test_index)
        print("Target:" + str(target) + " - n_training:" + str(n_training) + " - n_testing:" + str(n_testing) +
              " | target_train_index:" + str(target_train_index) + " - target_test_index:" + str(target_test_index))
        
        # Shuffle to remove randomly
        np.random.shuffle(target_train_index)
        np.random.shuffle(target_test_index)
        
        # Check if we need to remove samples from training or testing set
        if n_training > n_testing:
            while n_training > n_testing:
                target_train_index.pop(0)
                n_training = len(target_train_index)
        if n_training < n_testing:
            while n_training < n_testing:
                target_test_index.pop(0)
                n_testing = len(target_test_index)
        
        # Append new indexes to global train/test indexes
        final_train_index.append(target_train_index)
        final_test_index.append(target_test_index)

    # Flatten for readability
    final_train_index = [item for sublist in final_train_index for item in sublist]
    final_test_index = [item for sublist in final_test_index for item in sublist]
    print("FINAL split: TRAIN:", final_train_index," TEST:", final_test_index, "\n")

DÜZENLE

Tabakaland çapraz doğrulama kullanarak değil gibi görünüyor olması zorunlu Kullanmaya yeniden gözden geçirebileceğini böylece, (aşağıdaki bağlantılara bakın).

Bu bağlantıları yararlı bulabilirsiniz:

  • Neden katmanlı çapraz doğrulama kullanılıyor? Bu neden varyansla ilgili faydaya zarar vermez?
  • Katmanlı çapraz doğrulamayı anlama
  • Doğruluk tahmini ve model seçimi için çapraz doğrulama ve önyükleme çalışması

Fazla / yetersiz örneklemeyle ilgili olarak, veri dağılımına ve sınıflarınızın ne kadar dengesiz olduğuna dair daha fazla ayrıntı olmadan cevap vermenin zor olduğunu düşünüyorum.