Python - Pandas, Resample набор данных для сбалансированных классов - PullRequest
0 голосов
/ 10 октября 2018

Со следующим фреймом данных только с 2 возможными метками:

   name  f1  f2  label
0     A   8   9      1
1     A   5   3      1
2     B   8   9      0
3     C   9   2      0
4     C   8   1      0
5     C   9   1      0
6     D   2   1      0
7     D   9   7      0
8     D   3   1      0
9     E   5   1      1
10    E   3   6      1
11    E   7   1      1

Я написал код, чтобы сгруппировать данные по столбцу 'name' и преобразовать результат в массив numpy, поэтомукаждая строка представляет собой коллекцию всех выборок определенной группы, а метки - это еще один массив:

Данные:

[[8 9] [5 3] [0 0]] # A lable = 1
[[8 9] [0 0] [0 0]] # B lable = 0
[[9 2] [8 1] [9 1]] # C lable = 0
[[2 1] [9 7] [3 1]] # D lable = 0
[[5 1] [3 6] [7 1]] # E lable = 1

Метки:

[[1]
 [0]
 [0]
 [0]
 [1]]

Код:

import pandas as pd
import numpy as np


def prepare_data(group_name):
    df = pd.read_csv("../data/tmp.csv")


    group_index = df.groupby(group_name).cumcount()
    data = (df.set_index([group_name, group_index])
            .unstack(fill_value=0).stack())



    target = np.array(data['label'].groupby(level=0).apply(lambda x: [x.values[0]]).tolist())
    data = data.loc[:, data.columns != 'label']
    data = np.array(data.groupby(level=0).apply(lambda x: x.values.tolist()).tolist())
    print(data)
    print(target)


prepare_data('name')

Я хотел бы изменить выборку и удалить экземпляры из представленного класса.

т.е.

[[8 9] [5 3] [0 0]] # A lable = 1
[[8 9] [0 0] [0 0]] # B lable = 0
[[9 2] [8 1] [9 1]] # C lable = 0
# group D was deleted randomly from the '0' labels 
[[5 1] [3 6] [7 1]] # E lable = 1

было бы приемлемым решением, поскольку удалениеD (помеченный '0') приведет к сбалансированному набору данных 2 * метка '1' и 2 * метка '0'.

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

Очень простой подход.Взято из склерна и документации Kaggle.

from sklearn.utils import resample

df_majority = df[df.label==0]
df_minority = df[df.label==1]

# Upsample minority class
df_minority_upsampled = resample(df_minority, 
                                 replace=True,     # sample with replacement
                                 n_samples=20,    # to match majority class
                                 random_state=42) # reproducible results

# Combine majority class with upsampled minority class
df_upsampled = pd.concat([df_majority, df_minority_upsampled])

# Display new class counts
df_upsampled.label.value_counts()
0 голосов
/ 16 октября 2018

При условии, что каждый name помечен ровно одним label (например, все A являются 1), вы можете использовать следующее:

  1. Группировать name s поlabel и проверьте, какая метка имеет избыток (с точки зрения уникальных имен).
  2. Произвольно удаляет имена из класса перепредставленных меток, чтобы учесть превышение.
  3. Выберитечасть фрейма данных, которая не содержит удаленных имен.

Вот код:

labels = df.groupby('label').name.unique()
# Sort the over-represented class to the head.
labels = labels[labels.apply(len).sort_values(ascending=False).index]
excess = len(labels.iloc[0]) - len(labels.iloc[1])
remove = np.random.choice(labels.iloc[0], excess, replace=False)
df2 = df[~df.name.isin(remove)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...