Дублирование обучающих примеров для обработки дисбаланса классов во фрейме данных pandas

У меня есть DataFrame в пандах, которые содержат примеры обучения, например:

   feature1  feature2  class
0  0.548814  0.791725      1
1  0.715189  0.528895      0
2  0.602763  0.568045      0
3  0.544883  0.925597      0
4  0.423655  0.071036      0
5  0.645894  0.087129      0
6  0.437587  0.020218      0
7  0.891773  0.832620      1
8  0.963663  0.778157      0
9  0.383442  0.870012      0

который я сгенерировал, используя:

import pandas as pd
import numpy as np

np.random.seed(0)
number_of_samples = 10
frame = pd.DataFrame({
    'feature1': np.random.random(number_of_samples),
    'feature2': np.random.random(number_of_samples),
    'class':    np.random.binomial(2, 0.1, size=number_of_samples), 
    },columns=['feature1','feature2','class'])

print(frame)

Как видите, обучающая выборка несбалансирована (8 образцов имеют класс 0, и только 2 образца имеют класс 1). Я хотел бы передискретизировать тренировочный набор. В частности, я хотел бы дублировать обучающие выборки с классом 1, чтобы обучающая выборка была сбалансированной (т. Е. Где количество выборок с классом 0 примерно такое же, как количество выборок с классом 1). Как я могу это сделать?

В идеале я хотел бы решение, которое может быть обобщено на настройку мультикласса (т. е. целое число в столбце класса может быть больше 1).


person Franck Dernoncourt    schedule 22.01.2018    source источник
comment
Будет ли работать что-то вроде frame.groupby('class', group_keys=False).apply(lambda x: x.sample(10, replace=True)) (поскольку его параметр замены имеет значение True, теоретически он может не выбирать все уникальные элементы в классе) или вы ищете ручное дублирование?   -  person ayhan    schedule 22.01.2018
comment
@ayhan Спасибо, это выглядит хорошо, за исключением того, что, как вы упомянули, он может не отбирать все уникальные предметы в классе. Вы видите какой-нибудь способ обойти это? Кроме того, что вы подразумеваете под ручным дублированием?   -  person Franck Dernoncourt    schedule 22.01.2018


Ответы (1)


Вы можете найти максимальный размер группы с

max_size = frame['class'].value_counts().max()

В вашем примере это равно 8. Для каждой группы вы можете сэмплировать с заменой max_size - len(group_size) элементов. Таким образом, если вы соедините их с исходным DataFrame, их размеры будут одинаковыми, и вы сохраните исходные строки.

lst = [frame]
for class_index, group in frame.groupby('class'):
    lst.append(group.sample(max_size-len(group), replace=True))
frame_new = pd.concat(lst)

Вы можете поиграть с max_size-len(group) и, возможно, добавить немного шума, потому что это сделает все размеры групп равными.

person ayhan    schedule 22.01.2018