在 Python 特征工具中从特征工程中排除当前行
Excluding the current row from feature engineering in Python featuretools
我正在使用 featuretools
为当前行生成历史特征。例如,会话期间最后一小时的交易数量。
包 featuretools
包含参数 cutoff_time
以及时排除 cutoff_time
之后的所有行。
我将 cutoff_time
设置为 time_index value - 1 second
,因此我希望特征基于历史数据减去当前行。这允许包括来自历史行的响应变量。
问题是,当这个参数不等于 time_index
变量时,我在原始 和 生成的特征中得到一堆 NaN
s .
示例:
#!/usr/bin/env python3
import featuretools as ft
import pandas as pd
from featuretools import primitives, variable_types
data = ft.demo.load_mock_customer()
transactions_df = data['transactions']
transactions_df['cutoff_time'] = transactions_df['transaction_time'] - pd.Timedelta(seconds=1)
es = ft.EntitySet('transactions_set')
es.entity_from_dataframe(
entity_id='transactions',
dataframe=transactions_df,
variable_types={
'transaction_id': variable_types.Index,
'session_id': variable_types.Id,
'transaction_time': variable_types.DatetimeTimeIndex,
'product_id': variable_types.Id,
'amount': variable_types.Numeric,
'cutoff_time': variable_types.Datetime
},
index='transaction_id',
time_index='transaction_time'
)
es.normalize_entity(
base_entity_id='transactions',
new_entity_id='sessions',
index='session_id'
)
es.add_last_time_indexes()
fm, features = ft.dfs(
entityset=es,
target_entity='transactions',
agg_primitives=[primitives.Sum, primitives.Count],
trans_primitives=[primitives.Day],
cutoff_time=transactions_df[['transaction_id', 'cutoff_time']].
rename(index=str, columns={'transaction_id': 'transaction_id', 'cutoff_time': 'time'}),
training_window='1 hours',
verbose=True
)
print(fm)
输出(摘录):
DAY(cutoff_time) sessions.SUM(transactions.amount) \
transaction_id
352 NaN NaN
186 NaN NaN
319 NaN NaN
256 NaN NaN
449 NaN NaN
40 NaN NaN
13 NaN NaN
127 NaN NaN
21 NaN NaN
309 NaN NaN
列 sessions.SUM(transactions.amount)
应该 >= 0。原始特征 session_id product_id amount
也都是 NaN
。
如果 transactions_df['cutoff_time'] = transactions_df['transaction_time']
(无时间增量),此代码有效但包含当前行。
计算将从计算中排除当前行的聚合和转换的正确方法是什么?
您看到的是截止时间和 time_index
的预期行为。实体的 time_index
表示第一次可以知道每个实例的任何信息。当您向 Featuretools 提供截止时间时,它会通过删除时间索引在截止时间之后的行来模拟数据集处的数据集状态。
在这种情况下,交易的 transaction_id
和 session_id
在交易时间之前是未知的,这是有道理的,因为交易还没有发生。这就是为什么当您要求 Featuretools 在交易时间前一秒计算特征时,它 returns NaN
用于所有特征。
处理这个问题的方法是分配一个secondary_time_index to variables like amount
in transactions
. This is described in the advanced solution of this Stack Overflow answer。这允许您告诉 Featuretools 特定变量在 transaction_time
时无效,只能在您的辅助时间索引列中使用。本质上,您将阻止某些行值在事务处理时被使用,同时允许其他值。您可以为该实体中的任意数量的变量分配辅助时间索引。
根据 Max Kanter 的回答:
#!/usr/bin/env python3
import featuretools as ft
import pandas as pd
from featuretools import primitives, variable_types
data = ft.demo.load_mock_customer()
transactions_df = data['transactions']
transactions_df['response_time'] = transactions_df['transaction_time'] + pd.Timedelta(seconds=1)
es = ft.EntitySet('transactions_set')
es.entity_from_dataframe(
entity_id='transactions',
dataframe=transactions_df,
variable_types={
'transaction_id': variable_types.Index,
'session_id': variable_types.Id,
'transaction_time': variable_types.DatetimeTimeIndex,
'product_id': variable_types.Id,
'amount': variable_types.Numeric,
'response_time': variable_types.Datetime
},
index='transaction_id',
time_index='transaction_time',
secondary_time_index={'response_time': ['amount', 'transaction_id']}
)
es.normalize_entity(
base_entity_id='transactions',
new_entity_id='sessions',
index='session_id'
)
es.add_last_time_indexes()
fm, features = ft.dfs(
entityset=es,
target_entity='transactions',
agg_primitives=[primitives.Sum, primitives.Count],
trans_primitives=[primitives.Day],
cutoff_time=transactions_df[['transaction_id', 'transaction_time']],
cutoff_time_in_index=True,
training_window='5 minutes',
verbose=True
)
print(fm)
此代码生成的特征 sessions.SUM(transactions.amount)
和 sessions.COUNT(transactions)
排除了当前行,并包含所有之前不到 5 分钟的行。
我正在使用 featuretools
为当前行生成历史特征。例如,会话期间最后一小时的交易数量。
包 featuretools
包含参数 cutoff_time
以及时排除 cutoff_time
之后的所有行。
我将 cutoff_time
设置为 time_index value - 1 second
,因此我希望特征基于历史数据减去当前行。这允许包括来自历史行的响应变量。
问题是,当这个参数不等于 time_index
变量时,我在原始 和 生成的特征中得到一堆 NaN
s .
示例:
#!/usr/bin/env python3
import featuretools as ft
import pandas as pd
from featuretools import primitives, variable_types
data = ft.demo.load_mock_customer()
transactions_df = data['transactions']
transactions_df['cutoff_time'] = transactions_df['transaction_time'] - pd.Timedelta(seconds=1)
es = ft.EntitySet('transactions_set')
es.entity_from_dataframe(
entity_id='transactions',
dataframe=transactions_df,
variable_types={
'transaction_id': variable_types.Index,
'session_id': variable_types.Id,
'transaction_time': variable_types.DatetimeTimeIndex,
'product_id': variable_types.Id,
'amount': variable_types.Numeric,
'cutoff_time': variable_types.Datetime
},
index='transaction_id',
time_index='transaction_time'
)
es.normalize_entity(
base_entity_id='transactions',
new_entity_id='sessions',
index='session_id'
)
es.add_last_time_indexes()
fm, features = ft.dfs(
entityset=es,
target_entity='transactions',
agg_primitives=[primitives.Sum, primitives.Count],
trans_primitives=[primitives.Day],
cutoff_time=transactions_df[['transaction_id', 'cutoff_time']].
rename(index=str, columns={'transaction_id': 'transaction_id', 'cutoff_time': 'time'}),
training_window='1 hours',
verbose=True
)
print(fm)
输出(摘录):
DAY(cutoff_time) sessions.SUM(transactions.amount) \
transaction_id
352 NaN NaN
186 NaN NaN
319 NaN NaN
256 NaN NaN
449 NaN NaN
40 NaN NaN
13 NaN NaN
127 NaN NaN
21 NaN NaN
309 NaN NaN
列 sessions.SUM(transactions.amount)
应该 >= 0。原始特征 session_id product_id amount
也都是 NaN
。
如果 transactions_df['cutoff_time'] = transactions_df['transaction_time']
(无时间增量),此代码有效但包含当前行。
计算将从计算中排除当前行的聚合和转换的正确方法是什么?
您看到的是截止时间和 time_index
的预期行为。实体的 time_index
表示第一次可以知道每个实例的任何信息。当您向 Featuretools 提供截止时间时,它会通过删除时间索引在截止时间之后的行来模拟数据集处的数据集状态。
在这种情况下,交易的 transaction_id
和 session_id
在交易时间之前是未知的,这是有道理的,因为交易还没有发生。这就是为什么当您要求 Featuretools 在交易时间前一秒计算特征时,它 returns NaN
用于所有特征。
处理这个问题的方法是分配一个secondary_time_index to variables like amount
in transactions
. This is described in the advanced solution of this Stack Overflow answer。这允许您告诉 Featuretools 特定变量在 transaction_time
时无效,只能在您的辅助时间索引列中使用。本质上,您将阻止某些行值在事务处理时被使用,同时允许其他值。您可以为该实体中的任意数量的变量分配辅助时间索引。
根据 Max Kanter 的回答:
#!/usr/bin/env python3
import featuretools as ft
import pandas as pd
from featuretools import primitives, variable_types
data = ft.demo.load_mock_customer()
transactions_df = data['transactions']
transactions_df['response_time'] = transactions_df['transaction_time'] + pd.Timedelta(seconds=1)
es = ft.EntitySet('transactions_set')
es.entity_from_dataframe(
entity_id='transactions',
dataframe=transactions_df,
variable_types={
'transaction_id': variable_types.Index,
'session_id': variable_types.Id,
'transaction_time': variable_types.DatetimeTimeIndex,
'product_id': variable_types.Id,
'amount': variable_types.Numeric,
'response_time': variable_types.Datetime
},
index='transaction_id',
time_index='transaction_time',
secondary_time_index={'response_time': ['amount', 'transaction_id']}
)
es.normalize_entity(
base_entity_id='transactions',
new_entity_id='sessions',
index='session_id'
)
es.add_last_time_indexes()
fm, features = ft.dfs(
entityset=es,
target_entity='transactions',
agg_primitives=[primitives.Sum, primitives.Count],
trans_primitives=[primitives.Day],
cutoff_time=transactions_df[['transaction_id', 'transaction_time']],
cutoff_time_in_index=True,
training_window='5 minutes',
verbose=True
)
print(fm)
此代码生成的特征 sessions.SUM(transactions.amount)
和 sessions.COUNT(transactions)
排除了当前行,并包含所有之前不到 5 分钟的行。