欢迎大家来到IT世界,在知识的湖畔探索吧!
00、背景
特征选择是机器学习建模流程中最重要的步骤之一,经常有以下的情况:
假设特征目前有10个,准确率为80%,假设只取9个特征,反而准确率却变为90%。
特征选择的好坏直接决定着模型效果的上限,好的特征组合甚至比模型算法更重要。除了模型效果外,特征选择还有以下几点好处:
- 提高模型性能并降低复杂性(维数爆炸)
- 减少训练时间
- 由于无信息和冗余特征而降低了过度拟合的风险
- 简化的部署流程和实时数据管道,这是一个经常被低估的优势
找到了一个可完全自动化的特征选择工具:AutoFeatSelect,使用它可以让繁琐的筛选过程变得非常轻松。
之前曾经写过另一篇,同样目的,但实现效果不同:数据降维技术:主成分分析PCA
文尾有2者的对比。
01、AutoFeatSelect介绍
AutoFeatSelect 是一个 Python 库,可自动化并加速机器学习项目的特征选择过程。
它有助于使用多种方法计算特征重要性分数和排名,还有助于检测和删除高度相关的变量。
GitHub连接:https://github.com/dorukcanga/AutoFeatSelect
安装
pip install autofeatselect -i https://pypi.tuna.tsinghua.edu.cn/simple
欢迎大家来到IT世界,在知识的湖畔探索吧!
主要功能
AutoFeatSelect可以自动执行各种特征筛选步骤,比如计算相关性、消除高度相关的特征以及应用多种特征选择方法,并生成对应的筛选结果。该库自动化并简化了以下特征选择方法的实现:
- 自动特征选择:各种自动特征选择方法,如LightGBM、XGBoost、Random Forest 等。
- 特征重要性分析:分别计算和可视化不同算法的特征重要性分数。
- 相关性分析:执行相关性分析以自动识别并删除相关特征。
下面我们直接通过一个实战案例来说明如何使用AutoFeatSelect。
02、从0到1整理泰坦尼克号数据集
1、准备数据
Titanic数据是一份经典数据挖掘的数据集。
下面是字段的具体含义:
PassengerId:用户id
survival:是否生还,0-否,1-是
pclass:舱位,1-头等舱,2-二等,3-三等
name:姓名
sex:性别
Age:年龄
sibsp:在船上的兄弟/配偶数
parch:在船上父母/孩子数
ticket:票号
fare:票价
cabin:Cabin number;客舱号
embarked:登船地点
2、导入包
欢迎大家来到IT世界,在知识的湖畔探索吧!import re import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score from autofeatselect import CorrelationCalculator, FeatureSelector, AutoFeatureSelect
3、准备数据集
train = pd.read_csv('./train.csv') pred = pd.read_csv('./test.csv') # 加载训练和评估集。 train.head()
欢迎大家来到IT世界,在知识的湖畔探索吧!# 显示信息 print(train.info()) print(pred.info())
# 提取名字变量中的标题(先生、女士等) def get_title(passenger): if re.search('Mr', passenger): return 'Mr' elif re.search('Mrs', passenger): return 'Mrs' elif re.search('Miss', passenger): return 'Miss' elif re.search('Master', passenger): return 'Master' else: return 'Other' train['Title'] = train['Name'].apply(get_title) pred['Title'] = pred['Name'].apply(get_title)
# 删除不必要的变量。 train.drop(['PassengerId', 'Name', 'Ticket'], axis=1, inplace=True) pred.drop(['Name', 'Ticket'], axis=1, inplace=True)
# 保存训练集和评估集。 train.to_csv('titanic_train.csv', index=False) pred.to_csv('titanic_test.csv', index=False)
4、数据探索
target = 'Survived' # 训练集 vars_num = [var for var in train.columns if train[var].dtype != object and var != target] vars_cat = [var for var in train.columns if train[var].dtype == object]
# 评估集 pred_vars_num = [var for var in pred.columns if pred[var].dtype != object and var != target] pred_vars_cat = [var for var in pred.columns if pred[var].dtype == object]
5、找到变量中的缺失值
# train set # first in numerical variables print('Train set: Missing values in numerical vars') print(train[vars_num].isnull().mean()) vars_num_nan = [var for var in vars_num if train[var].isna().sum() > 0] print(vars_num_nan) # then in categorical variables print('Train set: Missing values in categorical vars') print(train[vars_cat].isnull().mean()) vars_cat_nan = [var for var in vars_cat if train[var].isna().sum() > 0] print(vars_cat_nan)
# evaluation set # first in numerical variables print('Evaluation set: Missing values in numerical vars') print(pred[pred_vars_num].isnull().mean()) pred_vars_num_nan = [var for var in pred_vars_num if pred[var].isna().sum() > 0] print(pred_vars_num_nan) # then in categorical variables print('Evaluation set: Missing values in categorical vars') print(pred[pred_vars_cat].isnull().mean()) pred_vars_cat_nan = [var for var in pred_vars_cat if pred[var].isna().sum() > 0] print(pred_vars_cat_nan)
6、确定分类变量的主导类别
# train set print(train[vars_cat].nunique())
7、确定数值变量的分布
train[vars_num].hist(bins=30, figsize=(10, 10)) plt.show()
# 评估集 pred[pred_vars_num].hist(bins=30, figsize=(10, 10)) plt.show()
8、将数据分为训练集和测试集
将数据(训练数据)分为训练集和测试集(评估集没有标签,用于实际预测的真实数据)。 X_train, X_test, y_train, y_test = train_test_split( train.drop('Survived', axis=1), train['Survived'], test_size=0.2, random_state=0) X_pred = pred.copy()
9、特征工程
# 提取变量 Cabin 中的字母(并删除数字) # 训练和测试集 X_train['Cabin'] = X_train['Cabin'].str[0] # 获取首字母 X_test['Cabin'] = X_test['Cabin'].str[0] # 获取首字母 # 评估集 X_pred['Cabin'] = X_pred['Cabin'].str[0] # 获取首字母 X_train['Cabin'].unique()
# 填写数字变量中的缺失数据: # train, test, pred for var in ['Age', 'Fare']: # 添加缺失的指标 X_train[var+'_NA'] = np.where(X_train[var].isnull(), 1, 0) X_test[var+'_NA'] = np.where(X_test[var].isnull(), 1, 0) X_pred[var+'_NA'] = np.where(X_pred[var].isnull(), 1, 0) # 将NaN替换为中位数。 median_val = X_train[var].median() X_train[var].fillna(median_val, inplace=True) X_test[var].fillna(median_val, inplace=True) X_pred[var].fillna(median_val, inplace=True)
# 替换分类变量中缺失的数据为字符串“Missing”。 for var in vars_cat_nan: X_train[var] = X_train[var].fillna('Missing') X_test[var] = X_test[var].fillna('Missing') for var in pred_vars_cat_nan: X_pred[var] = X_pred[var].fillna('Missing')
至此完成了数据的整理,可以看到清洗整理数据是异常耗时的。
03、用AutoFeatSelect选择最重要特征
1、半自动方法
检测高度相关的数字和分类特征并删除
# 检测相关数值特征 print(vars_num) num_static_vars = ['Pclass'] corr_vars_num, num_remove_list = CorrelationCalculator.numeric_correlations(X_train, features=vars_num, static_features=num_static_vars, threshold=0.9) print(corr_vars_num) print(num_remove_list)
# 检测相关分类特征 print(vars_cat) cat_static_vars = ['Sex', 'Title','Cabin'] corr_vars_cat, cat_remove_list = CorrelationCalculator.categorical_correlations(X_train, features=vars_cat, static_features=cat_static_vars, threshold=0.9) print(corr_vars_cat) print(cat_remove_list)
# 移除相关特征 num_feats = [v for v in vars_num if v not in num_remove_list] cat_feats = [v for v in vars_cat if v not in cat_remove_list]
通过计算重要性得分选择应用特征,采用LightGBM
# 创建特征选择器对象 feat_selector = FeatureSelector(modeling_type='classification', X_train=X_train, y_train=y_train, X_test=X_test, y_test=y_test, numeric_columns=num_feats, categorical_columns=cat_feats, seed=24) # 超参数和目标函数LightGBM的值是可以改变的 lgbm_importance_df = feat_selector.lgbm_importance(hyperparam_dict=None, objective=None, return_plot=True)
# 递归特征消除 rfecv_importance_df = feat_selector.rfecv_importance(lgbm_hyperparams=None, rfecv_hyperparams=None, return_plot=False) print(rfecv_importance_df)
2、全自动方法
# 创建AutoFeatureSelect类 feat_selector = AutoFeatureSelect(modeling_type='classification', X_train=X_train, y_train=y_train, X_test=X_test, y_test=y_test, numeric_columns=vars_num, categorical_columns=vars_cat, seed=24) # 检测相关特征 corr_features = feat_selector.calculate_correlated_features(static_features=None, num_threshold=0.9, cat_threshold=0.9) # 删除相关特征 feat_selector.drop_correlated_features() # 确定要应用的选择方法 # 选项: 'lgbm', 'xgb', 'rf','perimp', 'rfecv', 'boruta', 'lassocv' # 所有方法的超参数都可以更改 selection_methods = ['lgbm', 'xgb', 'rf','perimp'] final_importance_df = feat_selector.apply_feature_selection(selection_methods=selection_methods, lgbm_hyperparams=None, xgb_hyperparams=None, rf_hyperparams=None, lassocv_hyperparams=None, perimp_hyperparams=None, rfecv_hyperparams=None, boruta_hyperparams=None) # 打印结果 final_importance_df.head()
04、结论
AutoFeatSelect如名字一样,初衷就是为了简化并高效完成特征选择的过程。
可以看到,只需几行代码就可以应用多种特征选择方法,然后会得到所有特征选择方法对所有特征的计算结果。
基于这个结果,我们就可以通过自己的阈值标准对特征进行子集的组合条件筛选,得到最终的筛选特征了。
05、回答一个疑问
Q:特征选择和PCA降维有啥不同?
A:选择属性和PCA的目的都是一样,都是为了降低特征的数量,减少计算量。
但PCA是将原始特征进行一个映射压缩,这使得原始的特征面目全非,生成新的特征。
也就是说原本20个特征,PCA以后用全新的5个特征(这5个特征我已经不知道是代表原来的啥了)来表示。
但有时这5个特征并不能完全代替这原本的20个特征,而是容纳了98%的信息,这也是能接收的范围。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/85000.html