March 28, 2021

Как сформировать исторические признаки для моделей машинного обучения

В этой статье я поделюсь простым приемом формирования исторических признаков на основании последовательных сведений.

Рассмотрим использованные в прошлой статье данные о заработках людей по месяцам:

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

Одним из простых путей добиться этого является объединение таблицы по месяцу и имени человека с ее же копией, сдвинутой на заданное количество месяцев вперед (в частности, для предыдущего - на один).

Это можно реализовать при помощи указанной ниже функции get_shift_data, принимающей в качестве параметра датафрейм, состоящий из колонки данных (заработок) и столбцов, по которым происходит объединение (ФИО человека и дата в нашем случае), наименований столбцов даты и данных, а также числа периодов, на которые целевой признак отстоит от текущего:

def get_shift_data(df, date_col, data_col, n):
    df_c = df.copy()
    cols_merge = list(df.columns)
    cols_merge.remove(data_col)
    df_c[date_col] = df_c[date_col].map(lambda x: x + n)
    df_f = pd.merge(df, df_c, on=cols_merge, suffixes=[None,f'_{n}'])
    return df_f

Рассмотрим ее применение на наших данных:

n_m_b = 3
df_hist = get_shift_data(data[['date_sh', 'names', 'income']],'date_sh','income', n_m_b)
data[data['names']=='G H']
df_hist[df_hist['names']=='G H']

Функцию get_shift_data можно использовать для написания более продвинутой версии - get_shift_data_tilln, возвращающей все признаки раньше заданного (она принимает те же параметры):

def get_shift_data_tilln(df, date_col, data_col, n):
    cols_merge = list(df.columns)
    cols_merge.remove(data_col)
    df_f = get_shift_data(df, date_col, data_col, 1)
    if n>1:
        for i in range(2,n+1):
            df_f_t = get_shift_data(df, date_col, data_col, i)
            df_f = pd.merge(df_f, df_f_t[cols_merge+[data_col+f'_{i}']], on=cols_merge, suffixes=[None,f'_{n}'])
    return df_f

Рассмотрим ее работу на примере:

n_m_b = 3
df_hist_till = get_shift_data_tilln(data[['date_sh', 'names', 'income']]
                                    ,'date_sh','income', n_m_b)
data[data['names']=='G H']
df_hist_till[df_hist_till['names']=='G H']

Или для другой длины окна, чтобы сохранить больше данных:

n_m_b = 2
df_hist_till = get_shift_data_tilln(df_nullplus[['date_sh', 'names', 'income']],'date_sh','income', n_m_b)
data[data['names']=='G H']
df_hist_till[df_hist_till['names']=='G H']