You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免Featuretools组合聚合特征时生成无意义变量?

问题描述

我有一个包含发票(带唯一标识符)和客户(带唯一标识符)的数据集,每个客户可关联1张或多张发票。我按如下方式构建EntitySet:

es = ft.EntitySet(id="data")

es = es.add_dataframe(
    dataframe=df,
    dataframe_name="data",     
    index="rows",              
    make_index=True,           
    time_index="invoice_date", 
    logical_types={
"customer_id": Categorical,
"description": NaturalLanguage,
}
)

es.normalize_dataframe(
    base_dataframe_name="data",     
    new_dataframe_name="invoices",  
    index="invoice",               
    copy_columns=["customer_id"],
)

es.normalize_dataframe(
    base_dataframe_name="invoices",
    new_dataframe_name="customers",  
    index="customer_id",
)

其中customers是invoices的子实体,invoices是整个数据集的子实体。

我希望在整个dataframe层面组合price和quantity变量得到price*quantity,这一步正常,但聚合时出现了不符合人类逻辑的特征组合。我按如下方式设置dfs:

date_primitives = ["month", "weekday"]
text_primitives = ["num_words"]
trans_primitives = date_primitives + text_primitives + ["multiply_numeric"]

agg_primitives = ["mean"]

feature_matrix, feature_defs = ft.dfs(
    entityset=es,       
    target_dataframe_name="customers",     
    agg_primitives=agg_primitives,         
    trans_primitives=trans_primitives,        
    primitive_options={               
        ("multiply_numeric"): {
            'include_columns': {
                'data': ['price', 'quantity']
        }
    }
    },
    max_depth=3,
)

生成的特征包含:

[<Feature: MEAN(data.price)>,
 <Feature: MEAN(data.quantity)>,
 <Feature: MONTH(first_invoices_time)>,
 <Feature: WEEKDAY(first_invoices_time)>,
 <Feature: MEAN(invoices.MEAN(data.price))>,
 <Feature: MEAN(invoices.MEAN(data.quantity))>,
 <Feature: MEAN(data.NUM_WORDS(description))>,
 <Feature: MEAN(data.price * quantity)>,
 <Feature: MEAN(data.price) * MEAN(data.quantity)>,
 <Feature: MEAN(invoices.MEAN(data.NUM_WORDS(description)))>,
 <Feature: MEAN(invoices.MEAN(data.price * quantity))>,
 <Feature: MEAN(invoices.MEAN(data.price) * MEAN(data.quantity))>,
 <Feature: MEAN(data.price * quantity) * MEAN(data.price)>,
 <Feature: MEAN(data.price * quantity) * MEAN(data.quantity)>,
 <Feature: MEAN(data.price * quantity) * MEAN(invoices.MEAN(data.price))>,
 <Feature: MEAN(data.price * quantity) * MEAN(invoices.MEAN(data.quantity))>,
 <Feature: MEAN(data.price) * MEAN(invoices.MEAN(data.price))>,
 <Feature: MEAN(data.price) * MEAN(invoices.MEAN(data.quantity))>,
 <Feature: MEAN(data.quantity) * MEAN(invoices.MEAN(data.price))>,
 <Feature: MEAN(data.quantity) * MEAN(invoices.MEAN(data.quantity))>,
 <Feature: MEAN(invoices.MEAN(data.price)) * MEAN(invoices.MEAN(data.quantity))>]

其中MEAN(data.price * quantity)、MEAN(invoices.MEAN(data.price * quantity))等特征符合逻辑,但MEAN(data.quantity) * MEAN(invoices.MEAN(data.price))、MEAN(invoices.MEAN(data.price)) * MEAN(invoices.MEAN(data.quantity))这类特征无意义。尝试减小max_depth会导致文本primitive无法执行,请问如何避免生成这类无意义特征?

解决方案

可以通过以下几种方式精准控制特征生成,避免无意义组合:

1. 提前计算有意义的乘积字段

不要依赖multiply_numeric原语在特征生成阶段计算乘积,直接在原始数据中新增total_amount = price * quantity字段,再将其加入EntitySet。这样后续聚合只会针对这个预计算的有意义字段,不会衍生出其他无意义的乘积组合。

修改后的EntitySet构建代码示例:

# 提前计算乘积字段
df['total_amount'] = df['price'] * df['quantity']

es = ft.EntitySet(id="data")

es = es.add_dataframe(
    dataframe=df,
    dataframe_name="data",     
    index="rows",              
    make_index=True,           
    time_index="invoice_date", 
    logical_types={
        "customer_id": Categorical,
        "description": NaturalLanguage,
        "total_amount": Integer  # 根据实际数据类型调整
    }
)

# 后续normalize步骤不变
es.normalize_dataframe(
    base_dataframe_name="data",     
    new_dataframe_name="invoices",  
    index="invoice",               
    copy_columns=["customer_id"],
)

es.normalize_dataframe(
    base_dataframe_name="invoices",
    new_dataframe_name="customers",  
    index="customer_id",
)

同时调整dfs参数,移除multiply_numeric原语:

date_primitives = ["month", "weekday"]
text_primitives = ["num_words"]
trans_primitives = date_primitives + text_primitives

agg_primitives = ["mean"]

feature_matrix, feature_defs = ft.dfs(
    entityset=es,       
    target_dataframe_name="customers",     
    agg_primitives=agg_primitives,         
    trans_primitives=trans_primitives,
    max_depth=3,
)

2. 限制乘积原语的作用范围

如果必须保留multiply_numeric原语,可通过primitive_options进一步限制其仅作用于最底层的data实体指定字段,禁止在聚合后的invoices或customers层级特征上应用乘积操作。

修改primitive_options:

primitive_options={               
    "multiply_numeric": {
        'include_columns': {
            'data': ['price', 'quantity']
        },
        'exclude_entities': ['invoices', 'customers']
    }
}

这样乘积操作只会在原始数据层面执行,不会在聚合后的特征上生成无意义组合。

3. 过滤生成后的无效特征

生成特征矩阵后,通过正则表达式或特征名称规则手动过滤无意义特征。比如匹配包含MEAN\(.*\) \* MEAN\(.*\)模式的特征,直接从矩阵中删除:

import re

# 定义无意义特征的匹配规则
pattern = re.compile(r'MEAN\(.*\) \* MEAN\(.*\)')
# 筛选符合逻辑的特征
valid_features = [feat for feat in feature_matrix.columns if not pattern.match(feat)]
# 保留有效特征
feature_matrix = feature_matrix[valid_features]

内容的提问来源于stack exchange,提问作者Sole Galli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 13:01:43