использование sklearn.train_test_split для несбалансированных данных

У меня очень несбалансированный набор данных. Я использовал функцию sklearn.train_test_split для извлечения набора данных поезда. Теперь я хочу увеличить выборку для набора данных поезда, поэтому я использовал для подсчета числа type1 (в моем наборе данных есть 2 категории и типа (type1 и tupe2), но примерно все данные моего поезда относятся к type1. Так что я не могу выполнить избыточную выборку.

Раньше я разделял наборы данных для обучающих тестов своим написанным кодом. В этом коде 0,8 всех данных типа 1 и 0,8 всех данных типа 2 были в наборе данных поезда.

Как я могу использовать этот метод с функцией train_test_split или другими методами разделения в sklearn?

* Я должен просто использовать sklearn или мои собственные письменные методы.


person Maryam    schedule 19.05.2020    source источник


Ответы (3)


Вы ищете расслоение. Почему?

В методе train_test_split есть параметр stratify, которому вы можете передать список ярлыков, например. :

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y,
                                                    stratify=y, 
                                                    test_size=0.2)

Также существует StratifiedShuffleSplit.

person Arnaud    schedule 19.05.2020
comment
Но все же я думаю, что нет метода sklearn для реализации передискретизации. - person Maryam; 19.05.2020
comment
Нет, но вот библиотека, созданная в стиле sklearn, которая может оказаться полезной: imbalanced-learn github.com/ scikit-learn-contrib / imbalanced-learn - person Arnaud; 19.05.2020

Похоже, у нас обоих были похожие проблемы. К сожалению, несбалансированное обучение - это не всегда то, что вам нужно, и scikit не предлагает нужных вам функций. Вы захотите реализовать свой собственный код.

Это то, что я придумал для своего приложения. Обратите внимание, что у меня не было много времени на его отладку, но я считаю, что он работает, исходя из проведенного мной тестирования. Надеюсь, это поможет:

def equal_sampler(classes, data, target, test_frac):
    
    # Find the least frequent class and its fraction of the total
    _, count = np.unique(target, return_counts=True)
    fraction_of_total = min(count) / len(target)
    
    # split further into train and test
    train_frac = (1-test_frac)*fraction_of_total
    test_frac = test_frac*fraction_of_total
    
    # initialize index arrays and find length of train and test
    train=[]
    train_len = int(train_frac * data.shape[0])
    test=[]
    test_len = int(test_frac* data.shape[0])
    
    # add values to train, drop them from the index and proceed to add to test
    for i in classes:
        indeces = list(target[target ==i].index.copy())
        train_temp = np.random.choice(indeces, train_len, replace=False)
        for val in train_temp:
            train.append(val)
            indeces.remove(val)
        test_temp = np.random.choice(indeces, test_len, replace=False)
        for val in test_temp:
            test.append(val)
    
    # X_train, y_train, X_test, y_test
    return data.loc[train], target[train], data.loc[test], target[test] 

Для ввода классы ожидают список возможных значений, данные ожидают столбцы фрейма данных, используемые для прогнозирования, цель ожидает целевой столбец.

Позаботьтесь о том, чтобы алгоритм мог быть не очень эффективным из-за тройного цикла for (list.remove занимает линейное время). Несмотря на это, это должно быть достаточно быстро.

person Vlado    schedule 29.07.2020

Вы также можете изучить расслоение в случайном порядке следующим образом:

 # We use a utility to generate artificial classification data.
 from sklearn.datasets import make_classification
 from sklearn.model_selection import StratifiedShuffleSplit
 from sklearn.svm import SVC
 from sklearn.pipeline import make_pipeline

 X, y = make_classification(n_samples=100, n_informative=10, n_classes=2)
 sss = StratifiedShuffleSplit(n_splits=5, test_size=0.5, random_state=0)
 for train_index, test_index in sss.split(X, y):
    print("TRAIN:", train_index, "TEST:", test_index)
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    clf = make_pipeline(StandardScaler(), SVC(gamma='auto'))
    clf.fit(X_train, y_train)
    y_pred = clf.predict(X_test)
person zeroandone    schedule 30.05.2021