【问题标题】:(Featuretools) How are aggregate feature primitives calculated?(Featuretools) 如何计算聚合特征图元?
【发布时间】:2020-07-29 11:59:35
【问题描述】:

即使我使用非常简单的数据进行测试,我也不知道如何计算聚合特征原语。我也查看了 featuretools 代码,但找不到聚合操作发生在哪里。

这里是示例代码:

from sklearn.utils import shuffle

periods = 5
end_date = "2012-04-13"
train_df = pd.DataFrame(
    {
        "store_id": [0]*periods + [1]*periods + [2]*periods + [3]*periods,
        "region": ["A"]*periods+["B"]*periods*3,
        "amount": shuffle(range(periods*4)),
        "transacted_date": [
            "2012-02-05", "2012-02-10", "2012-03-01", "2012-03-18", "2012-04-23",
        ]*4
    }
)
train_df["transacted_date"] = pd.to_datetime(train_df["transacted_date"])
train_df.sort_values(["store_id", "transacted_date"], inplace=True)


def make_retail_cutoffs_amounts(data_df, amount_start_date, amount_end_date):
    store_pool = data_df[data_df['transacted_date'] < amount_start_date]['store_id'].unique()
    tmp = pd.DataFrame({'store_id': store_pool})

    amounts = data_df[
        (data_df['store_id'].isin(store_pool)) &
        (amount_start_date <= data_df['transacted_date']) &
        (data_df['transacted_date'] < amount_end_date)
    ].groupby('store_id')['amount'].sum().reset_index()

    amounts = amounts.merge(tmp, on = 'store_id', how = 'right')
    amounts['amount'] = amounts['amount'].fillna(0)  # 0으로 채워지는 애는 3개월 다 수익이 없는 녀석!

    amounts['cutoff_time'] = pd.to_datetime(amount_start_date)

    amounts = amounts[['store_id', 'cutoff_time', 'amount']]
    amounts = amounts.rename(columns={"amount":"1month_amount_from_cutoff_time"})
    return amounts


amount_start_date = "2012-02-01"
amount_end_date = end_date
agg_month = 1

data_df_list = []
date_list = pd.date_range(amount_start_date, datetime.strptime(end_date, "%Y-%m-%d") + pd.DateOffset(months=1), freq="MS")

for amount_start_date, amount_end_date in zip(date_list[:-agg_month], date_list[agg_month:]):
    data_df_list.append(
        make_retail_cutoffs_amounts(
            train_df, amount_start_date, amount_end_date
        )
    )
data_df = pd.concat(data_df_list)
data_df.sort_values(["store_id", "cutoff_time", ], inplace=True)

import featuretools as ft

es = ft.EntitySet(id="sale_set")
es = es.entity_from_dataframe(
    "sales",
    dataframe=train_df,
    index="sale_id", make_index=True,
    time_index='transacted_date',
)
es.normalize_entity(
    new_entity_id="stores",
    base_entity_id="sales",
    index="store_id",
    additional_variables=['region']
)

# When using a training window, 
# it is necessary to calculate the last time indexes for the entity set. Adding
es.add_last_time_indexes()

features  = ft.dfs(
    entityset=es,
    target_entity='stores',
    cutoff_time=data_df,
    verbose=1,
    cutoff_time_in_index=True,
    n_jobs=1,
    max_depth=2,

    agg_primitives=["sum",],
    trans_primitives=["cum_max"], 
    training_window="1 month",
)

dfs 工作正常,但无法解释结果特征。

这里是特征的样本数据:

正如您在此处看到的,SUM(sales.amount)SUM(sales.CUM_MAX(amount)) 的第一行分别为 19、37。我想知道它们是如何计算的。

这是我对结果的解释:

  1. 如您所见,store_0 有 2 条 2012 年 2 月的销售数据记录。因此,2012 年 3 月 1 日截止时间 store_id=0 的 SUM(sales.amount) 应为 0 + 8 = 8,不是 19 岁。

  2. 同样,SUM(sales.CUM_MAX(amount))of store_id=0 在 2012-03-01 的截止时间也应该是 SUM(sales.CUM_MAX(amount)) = SUM([0, 8]) = 8,而不是 37 .

我错过了什么吗?它们是如何计算的?

【问题讨论】:

    标签: python featuretools


    【解决方案1】:

    这些概念将帮助您了解特征的计算方式:

    1. 时间索引达到并包括截止时间的数据用于计算特征。
    2. 为了在每个商店的基础上计算CumMax,它需要放在groupby_trans_primitives 而不是trans_primitives

    我会举一个例子。这是CSV格式的数据。

    store_id,region,amount,transacted_date
    0,A,16,2012-02-05
    0,A,15,2012-02-10
    0,A,13,2012-03-01
    0,A,2,2012-03-18
    0,A,3,2012-04-23
    1,B,9,2012-02-05
    1,B,8,2012-02-10
    1,B,14,2012-03-01
    1,B,1,2012-03-18
    1,B,5,2012-04-23
    2,B,6,2012-02-05
    2,B,12,2012-02-10
    2,B,4,2012-03-01
    2,B,7,2012-03-18
    2,B,11,2012-04-23
    3,B,18,2012-02-05
    3,B,19,2012-02-10
    3,B,0,2012-03-01
    3,B,10,2012-03-18
    3,B,17,2012-04-23
    

    首先,我加载数据集。

    import pandas as pd
    
    train_df = pd.read_csv('data.csv', parse_dates=['transacted_date'])
    train_df.sort_values(["store_id", "transacted_date"], inplace=True)
    
     store_id region  amount transacted_date
            0      A      16      2012-02-05
            0      A      15      2012-02-10
            0      A      13      2012-03-01
            0      A       2      2012-03-18
            0      A       3      2012-04-23
            1      B       9      2012-02-05
            1      B       8      2012-02-10
            1      B      14      2012-03-01
            1      B       1      2012-03-18
            1      B       5      2012-04-23
            2      B       6      2012-02-05
            2      B      12      2012-02-10
            2      B       4      2012-03-01
            2      B       7      2012-03-18
            2      B      11      2012-04-23
            3      B      18      2012-02-05
            3      B      19      2012-02-10
            3      B       0      2012-03-01
            3      B      10      2012-03-18
            3      B      17      2012-04-23
    

    然后,我使用Compose 自动生成相同的截止时间。

    import composeml as cp
    
    def total_amount(df):
        return df.amount.sum()
    
    
    lm = cp.LabelMaker(
        target_entity='store_id',
        time_index='transacted_date',
        labeling_function=total_amount,
        window_size='1MS',
    )
    
    lt = lm.search(
        train_df,
        num_examples_per_instance=-1,
        minimum_data='2012-03-01',
    )
    
     store_id cutoff_time  total_amount
            0  2012-03-01            15
            0  2012-04-01             3
            1  2012-03-01            15
            1  2012-04-01             5
            2  2012-03-01            11
            2  2012-04-01            11
            3  2012-03-01            10
            3  2012-04-01            17
    

    现在,我构建实体集。

    import featuretools as ft
    
    es = ft.EntitySet(id="sale_set")
    
    es = es.entity_from_dataframe(
        "sales",
        dataframe=train_df,
        index="sale_id",
        make_index=True,
        time_index='transacted_date',
    )
    
    es.normalize_entity(
        new_entity_id="stores",
        base_entity_id="sales",
        index="store_id",
        additional_variables=['region'],
    )
    
    es.add_last_time_indexes()
    

    这是一个了解实体集结构的图。

    es.plot()
    

    最后,我运行 DFS 来计算特征。

    fm, fd = ft.dfs(
        entityset=es,
        target_entity='stores',
        cutoff_time=lt,
        cutoff_time_in_index=True,
        agg_primitives=["sum"],
        groupby_trans_primitives=["cum_max"],
        training_window="1 month",
        max_depth=2,
        verbose=1,
    )
    
    fm.filter(regex='SUM')
    
                         SUM(sales.amount)  SUM(sales.CUM_MAX(amount) by store_id)
    store_id time
    0        2012-03-01                 44                                    48.0
             2012-04-01                 15                                    26.0
    1        2012-03-01                 31                                    32.0
             2012-04-01                 15                                    28.0
    2        2012-03-01                 22                                    30.0
             2012-04-01                 11                                    11.0
    3        2012-03-01                 37                                    56.0
             2012-04-01                 10                                    10.0
    

    我们可以看到SUM(sales.amount) for store 0 在截止时间2012-03-01 包含直到并包括2012-03-01 的数据以计算特征。

    >>> 16 + 15 + 13
    44
    

    SUM(sales.CUM_MAX(amount) by store_id) 在 DFS 中作为 groupby_trans_primitives 应用时也是如此。

    >>> sum((16, 16, 16))
    48
    

    如果这有帮助,请告诉我。

    【讨论】:

    • 感谢您的回答。这确实有帮助,但我有一些问题和问题
    • 1.你能解释一下为什么当我使用trans_primitive.....以便我可以决定何时使用trans_primitivegroupby_trans_primitive 时,我的屏幕截图中的这些值会出现吗?
    • 2.似乎使用groupby_trans_primitive 可以解决所有问题。那么,在哪种情况下我应该使用trans_primitive?回购中有任何示例笔记本吗?
    • 3.看起来trans_primitive 忽略了所有组类别并在所有组中生成特征......如果是这样,我认为那些生成的特征是无用且毫无意义的。如果我遗漏了什么,请纠正我
    • 4.前瞻问题。在计算lt 时,当 cutoff_time 为“2012-03-01”(存储 0)时,计算“2012-03-01”的数量。那么,1个月的金额汇总期:2012-03-01~2012-03-31,对吧?让我们看看(store_id = 0 & 2012-03-01 截止时间)的SUM(sales.amount)。将 2012-02-05、2012-02-10 和 """2012-03-01""" 的数量相加后的值为 44!这里又算“”“2012-03-01”“”,这是一种作弊和前瞻性偏差。
    猜你喜欢
    • 2019-01-22
    • 2020-08-09
    • 2019-02-27
    • 2020-04-19
    • 1970-01-01
    • 2020-06-28
    • 2016-10-14
    • 1970-01-01
    • 2018-10-17
    相关资源
    最近更新 更多