我构建了一个如下所示的 Pipeline:
Pipeline(steps=[('preprocessor', ColumnTransformer(remainder='passthrough', transformers=[('text', Pipeline(steps=[('CV', CountVectorizer())]), 'Tweet'), ('category', OneHotEncoder(handle_unknown='ignore'), ['Tweet_ID']), ('numeric', Pipeline(steps=[('knnImputer', KNNImputer(n_neighbors=2)), ('scaler', MinMaxScale... 'CS', 'UC', 'CL', 'S', 'SS', 'UW', ...])])), ('classifier', LogisticRegression())])
我试图获取特征名称:
feature_names = lr['preprocessor'].transformers_[0][1].get_feature_names()coefs = lr.named_steps["classifier"].coef_.flatten()zipped = zip(feature_names, coefs)features_df = pd.DataFrame(zipped, columns=["feature", "value"])features_df["ABS"] = features_df["value"].apply(lambda x: abs(x))features_df["colors"] = features_df["value"].apply(lambda x: "green" if x > 0 else "red")features_df = features_df.sort_values("ABS", ascending=False)features_df
然而我得到了一个错误:
----> 6 feature_names = lr['preprocessor'].transformers_[0][1].get_feature_names() 7 coefs = lr.named_steps["classifier"].coef_.flatten() 8 AttributeError: 'Pipeline' 对象没有属性 'get_feature_names
我已经查看了以下答案:
但遗憾的是,这些答案并没有像我期望的那样有帮助。
有谁知道如何解决这个问题吗?如果需要,我很乐意提供更多信息。
Pipeline 的一个例子如下:
lr = Pipeline(steps=[('preprocessor', preprocessing), ('classifier', LogisticRegression(C=5, tol=0.01, solver='lbfgs', max_iter=10000))])
其中 preprocessing 是
preprocessing = ColumnTransformer( transformers=[ ('text',text_preprocessing, 'Tweet'), ('category', categorical_preprocessing, c_feat), ('numeric', numeric_preprocessing, n_feat)], remainder='passthrough')
在分割训练集和测试集之前,我会先分离不同类型的特征:
text_columns=['Tweet']target=['Label']c_feat=['Tweet_ID']num_features=['CS','UC','CL','S','SS','UW']
根据大卫的回答和链接,我尝试了如下方法:
对于数值型:
class NumericalTransformer(BaseEstimator, TransformerMixin): def __init__(self): super().__init__() def fit(self, X, y=None): return self def transform(self, X, y=None): # 传递给数值管道的数值特征 X = X[[num_features]] X = X.replace([np.inf, -np.inf], np.nan) return X.values# 定义数值管道的步骤numerical_pipeline = Pipeline(steps=[ ('num_transformer', NumericalTransformer()), ('imputer', KNNImputer(n_neighbors=2)), ('minmax', MinMaxScaler())])
对于分类型:
class CategoricalTransformer(BaseEstimator, TransformerMixin): def __init__(self): super().__init__() # 返回自身,这里没有其他需要做的 def fit(self, X, y=None): return self # 辅助函数,根据输入将值转换为二进制 def create_binary(self, obj): if obj == 0: return 'No' else: return 'Yes' # 此转换器的转换方法 def transform(self, X, y=None): # 传递给分类管道的分类特征 return X[[c_feat]].values# 定义分类管道的步骤categorical_pipeline = Pipeline(steps=[ ('cat_transformer', CategoricalTransformer()), ('one_hot_encoder', OneHotEncoder(handle_unknown='ignore'))])
对于文本特征:
class TextTransformer(BaseEstimator, TransformerMixin): def __init__(self): super().__init__() # 返回自身,这里没有其他需要做的 def fit(self, X, y=None): return self # 辅助函数,根据输入将值转换为二进制 def create_binary(self, obj): if obj == 0: return 'No' else: return 'Yes' # 此转换器的转换方法 def transform(self, X, y=None): # 传递给文本管道的文本特征 return X[['Tweet']].values# 定义文本管道的步骤text_pipeline = Pipeline(steps=[ ('text_transformer', TextTransformer()), ('cv', CountVectorizer())])
然后我将数值型、文本型和分类型管道水平组合成一个完整的大管道:
# 使用 FeatureUnionunion_pipeline = FeatureUnion(transformer_list=[ ('categorical_pipeline', categorical_pipeline), ('numerical_pipeline', numerical_pipeline), ('text_pipeline', text_pipeline)])
最后:
# 将自定义填充器与分类、文本和数值管道结合preprocess_pipeline = Pipeline(steps=[('custom_imputer', CustomImputer()), ('full_pipeline', union_pipeline)])
仍然不清楚如何获取特征名称。
回答:
你需要实现一个专用的 get_feature_names
函数,因为你使用了自定义转换器。
请参考这个问题以获取详细信息,其中你可以找到代码示例。