编程技术分享平台

网站首页 > 技术教程 正文

自动数据降维:用Titanic数据集验证

xnh888 2024-10-23 16:11:50 技术教程 60 ℃ 0 评论

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

主要功能

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、导入包

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()
# 显示信息
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%的信息,这也是能接收的范围。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表