如何在scikit-learn的FeatureUnion中筛选最优transformer组合
scikit-learn 最优transformer组合筛选实现方案
你提到的动态管道筛选需求,在SLEP002正式落地前,有以下几种成熟的临时实现方案:
方案1:利用FeatureUnion原生drop机制+网格搜索
scikit-learn 0.21及以上版本中,FeatureUnion支持将指定transformer设为drop值,即可完全跳过该特征分支的输出,无需修改管道结构。直接将drop加入对应参数的搜索候选列表即可实现全组合自动筛选:
from sklearn.pipeline import Pipeline, FeatureUnion from sklearn.model_selection import GridSearchCV from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.svm import SVC # 基础管道定义和你提供的示例一致 base_pipeline = Pipeline([ ('vectorizer', FeatureUnion(transformer_list=[ ('word-freq', TfidfVectorizer()), ('doc2vec', MyDoc2VecVectorizer()), ('doc-length', MyDocLengthVectorizer()), ('sentiment', MySentimentVectorizer()) ])), ('classifier', SVC()) ]) # 定义参数网格,每个transformer分支可选启用或丢弃,同时支持搜索其他超参数 param_grid = { 'vectorizer__word-freq': [TfidfVectorizer(ngram_range=(1,1)), TfidfVectorizer(ngram_range=(1,2)), 'drop'], 'vectorizer__doc2vec': [MyDoc2VecVectorizer(), 'drop'], 'vectorizer__doc-length': [MyDocLengthVectorizer(), 'drop'], 'vectorizer__sentiment': [MySentimentVectorizer(), 'drop'], 'classifier__C': [0.1, 1, 10], 'classifier__kernel': ['linear', 'rbf'] } # 执行网格搜索,自动选出最优transformer组合+超参数 search = GridSearchCV(base_pipeline, param_grid, cv=5, scoring='f1') search.fit(X_train, y_train) # 查看最优组合 print(search.best_params_)
如果分支数量较多导致搜索量过大,可改用RandomizedSearchCV随机采样部分组合,降低计算开销。
方案2:结合特征选择层间接筛选
如果不需要严格保留/丢弃整个transformer分支,仅需要筛选有效特征,可在FeatureUnion后追加特征选择模块,自动过滤无用特征:
from sklearn.feature_selection import SelectFromModel from sklearn.ensemble import RandomForestClassifier pipeline = Pipeline([ ('vectorizer', FeatureUnion(transformer_list=[ ('word-freq', TfidfVectorizer()), ('doc2vec', MyDoc2VecVectorizer()), ('doc-length', MyDocLengthVectorizer()), ('sentiment', MySentimentVectorizer()) ])), # 基于树模型自动选择重要特征,间接过滤无效transformer的输出 ('feature_selector', SelectFromModel(RandomForestClassifier())), ('classifier', SVC()) ])
方案3:自定义分组特征选择器
如果需要精准控制保留/丢弃整个transformer的全部输出,可自定义分组选择Transformer,配合网格搜索实现分支筛选,适合需要按特征组控制的场景:
from sklearn.base import BaseEstimator, TransformerMixin class GroupFeatureSelector(BaseEstimator, TransformerMixin): def __init__(self, keep_groups=None): # keep_params为要保留的分支名称列表 self.keep_groups = keep_groups or [] # 提前定义每个分支对应的特征索引范围 self.group_ranges = { 'word-freq': slice(0, 10000), # 假设Tfidf输出维度为10000 'doc2vec': slice(10000, 10032), 'doc-length': slice(10032, 10033), 'sentiment': slice(10033, 10036) } def fit(self, X, y=None): return self def transform(self, X): selected_slices = [self.group_ranges[g] for g in self.keep_groups] selected_cols = [] for s in selected_slices: selected_cols.extend(range(s.start, s.stop)) return X[:, selected_cols] # 加入管道后搜索keep_groups参数即可 param_grid = { 'feature_selector__keep_groups': [ ['word-freq', 'doc2vec'], ['doc2vec', 'sentiment', 'doc-length'], # 其他要测试的组合 ], 'classifier__C': [0.1, 1, 10] }
以上方案均为当前版本scikit-learn原生支持的实现方式,不需要等待SLEP002的动态管道功能落地即可直接使用。
内容的提问来源于stack exchange,提问作者eliangius
相关产品推荐
相关产品推荐

