Hedef tabakalaşma ile Grup K katlama
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
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:
- gruplara göre ayırın ( GroupKFold yöntemini şuradan kullanabilirsiniz
sklearn) - eğitim / test setlerinde hedeflerin dağılımını kontrol edin.
- 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.