数据科学:使用Optuna进行特征选择

2024-05-13 17:36

本文主要是介绍数据科学:使用Optuna进行特征选择,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

大家好,特征选择是机器学习流程中的关键步骤,在实践中通常有大量的变量可用作模型的预测变量,但其中只有少数与目标相关。特征选择包括找到这些特征的子集,主要用于改善泛化能力、助力推断预测、提高训练效率。有许多技术可用于执行特征选择,每种技术的复杂性不同。

本文将介绍一种使用强大的开源优化工具Optuna来执行特征选择任务的创新方法,主要思想是通过有效地测试不同的特征组合(例如,不是逐个尝试它们)来处理各种任务的特征选择的灵活工具。下面,将通过一个实际示例来实施这种方法,并将其与其他常见的特征选择策略进行比较。

1.数据准备

将利用基于Kaggle上的Mobile Price Classification数据集进行分类任务。该数据集包含20个特征,其中包括:'battery_power'、'clock_speed'和'ram' 等,用于预测'price_range'特征,该特征可以分为四个不同的价格范围:0、1、2和3。我们将数据集分成训练集和测试集,并在训练集中准备了一个5折交叉验证分割。

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.model_selection import StratifiedKFoldSEED = 32
# Load data
df = pd.read_csv("mpc_train.csv")# Train - test split
df_train, df_test = train_test_split(df, test_size=0.2, stratify=df.iloc[:,-1], random_state=SEED)
df_train = df_train.reset_index(drop=True)
df_test = df_test.reset_index(drop=True)# The last column is the target variable
X_train = df_train.iloc[:,0:20]
y_train = df_train.iloc[:,-1]
X_test = df_test.iloc[:,0:20]
y_test = df_test.iloc[:,-1]# Stratified kfold over the train set for cross validation
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=SEED)
splits = list(skf.split(X_train, y_train))
len(splits)

将使用随机森林分类器模型,使用scikit-learn实现并采用默认参数。我们首先使用所有特征训练模型来设置基准。我们将测量的指标是针对所有四个价格范围加权的F1分数。在对训练集进行学习后,我们在测试集上对其进行评估,得到的F1分数约为0.87。

from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import f1_score, classification_reportmodel = RandomForestClassifier(random_state=SEED)
model.fit(X_train,y_train)
preds = model.predict(X_test)print(classification_report(y_test, preds))
print(f"Global F1: {f1_score(y_test, preds, average='weighted')}")

特征选择的目标是通过选择一个较少的特征集来提高评估指标。首先将描述基于Optuna的方法如何工作,然后测试并将其与其他常见的特征选择策略进行比较。

2.用Optuna进行特征选择

Optuna是一个用于超参数调优的优化框架,采用贝叶斯优化技术搜索参数空间。与传统的网格或随机搜索相比,Optuna更高效。我们使用默认的TPESampler采样器,它基于Tree-structured Parzen Estimator算法(TPE)。

在特征选择的情况下,不是调整模型的超参数,而是选择特征。使用训练数据集,分成五个折交叉,在每次试验中训练模型并评估性能。目标是最大化F1分数,同时对使用的特征进行小惩罚以鼓励更小的特征集。

下面是执行特征选择搜索的实现类:

import optunaclass FeatureSelectionOptuna:"""This class implements feature selection using Optuna optimization framework.Parameters:- model (object): The predictive model to evaluate; this should be any object that implements fit() and predict() methods.- loss_fn (function): The loss function to use for evaluating the model performance. This function should take the true labels and thepredictions as inputs and return a loss value.- features (list of str): A list containing the names of all possible features that can be selected for the model.- X (DataFrame): The complete set of feature data (pandas DataFrame) from which subsets will be selected for training the model.- y (Series): The target variable associated with the X data (pandas Series).- splits (list of tuples): A list of tuples where each tuple contains two elements, the train indices and the validation indices.- penalty (float, optional): A factor used to penalize the objective function based on the number of features used."""def __init__(self,model,loss_fn,features,X,y,splits,penalty=0):self.model = modelself.loss_fn = loss_fnself.features = featuresself.X = Xself.y = yself.splits = splitsself.penalty = penaltydef __call__(self,trial: optuna.trial.Trial):# Select True / False for each featureselected_features = [trial.suggest_categorical(name, [True, False]) for name in self.features]# List with names of selected featuresselected_feature_names = [name for name, selected in zip(self.features, selected_features) if selected]# Optional: adds a penalty for the amount of features usedn_used = len(selected_feature_names)total_penalty = n_used * self.penaltyloss = 0for split in self.splits:train_idx = split[0]valid_idx = split[1]X_train = self.X.iloc[train_idx].copy()y_train = self.y.iloc[train_idx].copy()X_valid = self.X.iloc[valid_idx].copy()y_valid = self.y.iloc[valid_idx].copy()X_train_selected = X_train[selected_feature_names].copy()X_valid_selected = X_valid[selected_feature_names].copy()# Train model, get predictions and accumulate lossself.model.fit(X_train_selected, y_train)pred = self.model.predict(X_valid_selected)loss += self.loss_fn(y_valid, pred)# Take the average loss across all splitsloss /= len(self.splits)# Add the penalty to the lossloss += total_penaltyreturn loss

将每个特征视为一个参数,可以取True或False值,表示是否应该将该特征包含在模型中。使用suggest_categorical方法,让Optuna为每个特征选择两个可能的值之一。

初始化Optuna研究并进行100次试验的搜索,将第一个试验排入队列,使用所有特征作为搜索的起点,允许Optuna将后续试验与完全特征模型进行比较:

from optuna.samplers import TPESamplerdef loss_fn(y_true, y_pred):"""Returns the negative F1 score, to be treated as a loss function."""res = -f1_score(y_true, y_pred, average='weighted')return resfeatures = list(X_train.columns)model = RandomForestClassifier(random_state=SEED)sampler = TPESampler(seed = SEED)
study = optuna.create_study(direction="minimize",sampler=sampler)# We first try the model using all features
default_features = {ft: True for ft in features}
study.enqueue_trial(default_features)study.optimize(FeatureSelectionOptuna(model=model,loss_fn=loss_fn,features=features,X=X_train,y=y_train,splits=splits,penalty = 1e-4,), n_trials=100)

完成了100次试验后,从研究中获取最佳试验和其中使用的特征,如下所示:

[‘battery_power’, ‘blue’, ‘dual_sim’, ‘fc’, ‘mobile_wt’, ‘px_height’, ‘px_width’, ‘ram’, ‘sc_w’]

上述过程从原始的20个特征中,搜索最终只选出了其中的9个特征变量,这是一个显著的减少。这些特征产生了约为-0.9117的最小验证损失,这意味着它们在所有折叠中实现了约为0.9108的平均F1分数(在考虑到惩罚项后)。

下一步是使用这些选定的特征在整个训练集上训练模型,并在测试集上对其进行评估。结果是约为0.882的F1分数:

# Train - test split
c=['battery_power', 'blue', 'dual_sim', 'fc', 'mobile_wt', 'px_height', 'px_width', 'ram', 'sc_w','price_range']
df_c=df[c]
df_train, df_test = train_test_split(df_c, test_size=0.2, stratify=df.iloc[:,-1], random_state=SEED)
df_train = df_train.reset_index(drop=True)
df_test = df_test.reset_index(drop=True)# The last column is the target variable
X_train = df_train.iloc[:,0:9]
y_train = df_train.iloc[:,-1]
X_test = df_test.iloc[:,0:9]
y_test = df_test.iloc[:,-1]# Stratified kfold over the train set for cross validation
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=SEED)
splits = list(skf.split(X_train, y_train))model = RandomForestClassifier(random_state=SEED)
model.fit(X_train,y_train)
preds = model.predict(X_test)print(classification_report(y_test, preds))
print(f"Global F1: {f1_score(y_test, preds, average='weighted')}")

通过选择合适的特征组合,能够将特征集减少了一半以上,同时仍然实现了比全特征集更高的F1分数。下面是Optuna进行特征选择的一些优缺点:

优点:

  • 高效地搜索特征集,考虑了哪些特征组合最有可能产生良好的结果。

  • 适用于许多场景:只要有模型和损失函数,我们就可以用它来处理任何特征选择任务。

  • 看到了整体情况:与评估单个特征的方法不同,Optuna考虑了哪些特征彼此之间往往配合得好,哪些不好。

  • 作为优化过程的一部分动态确定特征数量。这可以通过惩罚项进行调节。

缺点:

  • 与简单方法相比,不那么直观,对于较小和较简单的数据集可能不值得使用。

  • 尽管与其他方法(如穷举搜索)相比需要的试验次数要少得多,但通常仍需要大约100到1000次试验。根据模型和数据集的不同,这可能耗时且计算成本高昂。

3.其他特征选择方法

SelectKBest是scikit-learn库中的一个特征选择工具,用于选择与目标变量相关性最高的k个特征。它基于给定的评分函数对每个特征进行评分,并返回得分最高的k个特征。这个工具通常用于过滤方法中,它不需要构建模型,而是直接对特征进行评估和选择。通过选择与目标变量高度相关的特征,SelectKBest可以帮助提高模型的预测性能和泛化能力。

from sklearn.feature_selection import SelectKBest, chi2
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.model_selection import StratifiedKFold
SEED = 32
# Load data
df = pd.read_csv("mpc_train.csv")# Train - test split
df_train, df_test = train_test_split(df, test_size=0.2, stratify=df.iloc[:,-1], random_state=SEED)
df_train = df_train.reset_index(drop=True)
df_test = df_test.reset_index(drop=True)# The last column is the target variable
X_train = df_train.iloc[:,0:20]
y_train = df_train.iloc[:,-1]
X_test = df_test.iloc[:,0:20]
y_test = df_test.iloc[:,-1]skb = SelectKBest(score_func=chi2, k=10)
X_train_selected = skb.fit_transform(X_train, y_train)
X_test_selected = skb.transform(X_test)# Train Random Forest Classifier
model = RandomForestClassifier(random_state=SEED)
model.fit(X_train_selected, y_train)# Predictions
preds = model.predict(X_test_selected)# Evaluation
print(classification_report(y_test, preds))
print(f"Global F1: {f1_score(y_test, preds, average='weighted')}")

通过上述对比,可以看出通过Optuna进行特征选择有更高的效率和更好的性能指标。使用Optuna这一强大的优化工具来进行特征选择任务,通过有效地搜索空间,它能够在相对较少的试验中找到好的特征子集。而且它还具有灵活性,并且只要定义模型和损失函数,可以适应许多场景。

这篇关于数据科学:使用Optuna进行特征选择的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/986370

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传