提问人:Nikitosiwe 提问时间:8/19/2023 最后编辑:desertnautNikitosiwe 更新时间:8/21/2023 访问量:89
如何在 SelectKBest 之后仅将必要的功能传递给管道
How to pass only necessary features to pipeline after SelectKBest
问:
我有一个常规的表格数据集,从数据库中添加了 100 个要素
我想把它推送到一个常规的sklearn.pipeline中,其中将有预处理、编码、一些自定义转换器等。
倒数第二个估计器是 SelectKBest(k=10)
实际上,对于模型,只需要 10 个特征,而管道将需要所有 100 个特征
我想在生产模型中只使用“必要”功能。我想避免额外的功能以减少计算时间。
当然,我可以重建管道,但整个 sklearn 就是不这样做。我不知道这在多大程度上是一种“标准”做法
我理解为什么它根本不起作用,因为 150 个功能实际上可以转到 SelectKBest 输入。在这种情况下,如何确定这些“必要”特征并不明显。
也许还有其他一些开箱即用的工具?
基本示例:
from sklearn.datasets import load_diabetes
from sklearn.preprocessing import StandardScaler
from sklearn.feature_selection import SelectKBest, f_regression
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline
data = load_diabetes(as_frame=True)
X, y = data.data, data.target
X = X.iloc[:, :10]
pipeline = Pipeline([
('scaler', StandardScaler()),
('feature_selection', SelectKBest(score_func=f_regression, k=4)),
('model', LinearRegression())
])
pipeline.fit(X, y)
selected_features = pipeline.named_steps['feature_selection'].get_support()
selected_features = X.columns[selected_features]
print(f"Selected features: {selected_features}")
# Selected features: Index(['bmi', 'bp', 's4', 's5'], dtype='object')
prod_data = X[selected_features]
pred = pipeline.predict(prod_data)
# Here will be an Exception
# ValueError: The feature names should match those that were passed during fit.
# Feature names seen at fit time, yet now missing:
# - age
# - s1
# - s2
# - s3
# - s6
# - ...
答:
在您的管道中,该步骤将负责保留 4 个功能,并删除其他功能。此步骤之后的模型将仅看到这 4 个功能。这是因为在内部,管道将在拟合数据后用于转换数据,因此该步骤仅传递 4 个选定的特征。SelectKBest
SelectKBest
要使用所选要素获取预测,请运行 。这将在它们进入最终模型之前自动删除不必要的功能。我修改了你的代码:pipeline.fit(X, y).predict(X)
from sklearn.datasets import load_diabetes
from sklearn.preprocessing import StandardScaler
from sklearn.feature_selection import SelectKBest, f_regression
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline
data = load_diabetes(as_frame=True)
X, y = data.data, data.target
X = X.iloc[:, :10]
#Define the pipeline
pipeline = Pipeline([
('scaler', StandardScaler()),
('feature_selection', SelectKBest(score_func=f_regression, k=4)),
('model', LinearRegression())
])
#Fit and predict. Final model only uses the k best features.
pred_using_selected_features = pipeline.fit(X, y).predict(X)
#Print results
selected_features = pipeline.named_steps['feature_selection'].get_support()
print(f"Selected features: {X.columns[selected_features].to_list()}")
print(f'Model saw {pipeline.named_steps["model"].n_features_in_} features')
在流水线的过程中,选择了 4 个特征,而模型只看到了这 4 个特征。
评论
X
我同意@some3128的观点,看起来没有单一的管道解决方案。
据我了解,像 SelectKBest 这样的估算器正在用于减少由 PolynomialFeatures、PCA 等其他估算器在 Pipeline 内部生成的特征。
当然,也许有一种方法可以确定最佳生成的特征,并防止在预测时生成无用的特征。但它更像是“低级”优化。
在流水线之前减少特征 - 这是关于特征工程过程,这是一个单独的问题。
我通常建议您尝试避免的解决方案:重新构建管道,而不执行选择步骤,并且不使用训练集中删除的列。
可以识别和更改每个流水线步骤的拟合属性(从缩放器中删除条目等,减少和特征名称等),并且可以自动执行。但是弄乱内部结构有点风险:删除错误的东西不会产生错误,但每列执行错误的缩放。mean_
scale_
n_features_in_
另一个低技术含量的解决方案:您不在乎预测行中已删除列的值是多少,因此只需编造它们即可。sklearn 管道仍将处理假值,但无需在生产环境中收集这些字段。
评论
SelectKBest