使用LightGBM进行特征重要性评估

27
我将尝试运行以下代码以使用lightgbm进行特征选择;
初始化
# Initialize an empty array to hold feature importances
feature_importances = np.zeros(features_sample.shape[1])

# Create the model with several hyperparameters
model = lgb.LGBMClassifier(objective='binary', 
         boosting_type = 'goss', 
         n_estimators = 10000, class_weight ='balanced')

然后我按以下方式适配模型

# Fit the model twice to avoid overfitting
for i in range(2):

   # Split into training and validation set
   train_features, valid_features, train_y, valid_y = train_test_split(train_X, train_Y, test_size = 0.25, random_state = i)

   # Train using early stopping
   model.fit(train_features, train_y, early_stopping_rounds=100, eval_set = [(valid_features, valid_y)], 
             eval_metric = 'auc', verbose = 200)

   # Record the feature importances
   feature_importances += model.feature_importances_

但我收到了以下错误信息。
Training until validation scores don't improve for 100 rounds. 
Early stopping, best iteration is: [6]  valid_0's auc: 0.88648
ValueError: operands could not be broadcast together with shapes (87,) (83,) (87,) 

你如何初始化 feature_importances? - Florian Mutel
@FlorianMutel 请查看更新的帖子。 - Ian Okeyo
features_sample是什么?你有多少个特征?例如,我无法使用鸢尾花数据重现你的错误。看起来你正在尝试添加不同形状的数组。要么你初始化时维度有误,要么在拆分数据(训练/验证)时,一些特征变为空(全部为nan)或常数,并且lightgbm会忽略它们。尝试查看你的拆分! - Florian Mutel
4个回答

27

使用train模型在lightgbm中获取特征重要性的示例。

import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.simplefilter(action='ignore', category=FutureWarning)

def plotImp(model, X , num = 20, fig_size = (40, 20)):
    feature_imp = pd.DataFrame({'Value':model.feature_importance(),'Feature':X.columns})
    plt.figure(figsize=fig_size)
    sns.set(font_scale = 5)
    sns.barplot(x="Value", y="Feature", data=feature_imp.sort_values(by="Value", 
                                                        ascending=False)[0:num])
    plt.title('LightGBM Features (avg over folds)')
    plt.tight_layout()
    plt.savefig('lgbm_importances-01.png')
    plt.show()

5
特征重要性 = pd.DataFrame({'Value': model.feature_importances_, 'Feature': self.x_cols}) - user3067175
1
feature_imp = pd.DataFrame({'Value':model.feature_importances_,'Feature':X.columns}) - kevin_theinfinityfund

8

根据我们使用的是scikit-learn还是lightgbm方法来训练模型,我们需要选择相应的feature_importances_属性或feature_importance()函数来获取重要性信息。例如,在下面的示例中,(其中modellgbm.fit() / lgbm.train()的结果,而train_columns = x_train_df.columns):

import pandas as pd

def get_lgbm_varimp(model, train_columns, max_vars=50):
    
    if "basic.Booster" in str(model.__class__):
        # lightgbm.basic.Booster was trained directly, so using feature_importance() function 
        cv_varimp_df = pd.DataFrame([train_columns, model.feature_importance()]).T
    else:
        # Scikit-learn API LGBMClassifier or LGBMRegressor was fitted, 
        # so using feature_importances_ property
        cv_varimp_df = pd.DataFrame([train_columns, model.feature_importances_]).T

    cv_varimp_df.columns = ['feature_name', 'varimp']

    cv_varimp_df.sort_values(by='varimp', ascending=False, inplace=True)

    cv_varimp_df = cv_varimp_df.iloc[0:max_vars]   

    return cv_varimp_df
    

注意,我们依赖于一个假设,即特征重要性的值按照模型矩阵列的顺序进行排序,就像训练期间一样(包括独热编码虚拟列),详见LightGBM #209

1
+1,但是关于“feature_importance()函数在LightGBM Python API中不再可用”的问题,实际上它仍然存在,我想你可能指的是Scikit-learn API。 - Mustafa Aydın
2
feature_importance()仍然存在(https://lightgbm.readthedocs.io/en/latest/pythonapi/lightgbm.Booster.html#lightgbm.Booster.feature_importance),我建议您相应地更新答案。 - desertnaut
1
这个泛化应该自动检测用于训练的API,并选择适当的方法来获取重要性。 - mirekphd

4
对于LightGBM的3.1.1版本,扩展@user3067175的评论:
pd.DataFrame({'Value':model.feature_importance(),'Feature':features}).sort_values(by="Value",ascending=False)

这是一个特征名称列表,与您的数据集相同的顺序,可以用 features = df_train.columns.tolist() 替换。这应该以与图形相同的顺序返回特征重要性。

注意:如果您使用LGBMRegressor或LGBMClassifier,则应使用

pd.DataFrame({'Value':model.feature_importances_,'Feature':features}).sort_values(by="Value",ascending=False)

1
这基本上是我一年前回答的复制...可以说更不普遍和不易读 :) 尽管如此,它使其更通用,并为链接的美妙使用(以及多元化的缘故)投了赞成票。 - mirekphd
1
有一天我的答案也会过时,非常谦虚的你,谢谢 :=) - Mehmet Burak Sayıcı

4
如果您想检查已加载的模型,但没有训练数据,您可以通过以下方式获取特征重要性和特征名称:
df_feature_importance = (
    pd.DataFrame({
        'feature': model.feature_name(),
        'importance': model.feature_importance(),
    })
    .sort_values('importance', ascending=False)
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接