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

news2024/11/28 19:37:54

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

本文将介绍一种使用强大的开源优化工具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 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]

# 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_report

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')}")

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

2.用Optuna进行特征选择

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

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

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

import optuna

class 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 the
                          predictions 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 = model
        self.loss_fn = loss_fn
        self.features = features
        self.X = X
        self.y = y
        self.splits = splits
        self.penalty = penalty

    def __call__(self,
                 trial: optuna.trial.Trial):

        # Select True / False for each feature
        selected_features = [trial.suggest_categorical(name, [True, False]) for name in self.features]

        # List with names of selected features
        selected_feature_names = [name for name, selected in zip(self.features, selected_features) if selected]

        # Optional: adds a penalty for the amount of features used
        n_used = len(selected_feature_names)
        total_penalty = n_used * self.penalty

        loss = 0

        for 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 loss
          self.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 splits
        loss /= len(self.splits)

        # Add the penalty to the loss
        loss += total_penalty

        return loss

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

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

from optuna.samplers import TPESampler

def 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 res

features = 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这一强大的优化工具来进行特征选择任务,通过有效地搜索空间,它能够在相对较少的试验中找到好的特征子集。而且它还具有灵活性,并且只要定义模型和损失函数,可以适应许多场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1670649.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【kettle012】kettle访问FTP服务器文件并处理数据至PostgreSQL(已更新)

1.一直以来想写下基于kettle的系列文章,作为较火的数据ETL工具,也是日常项目开发中常用的一款工具,最近刚好挤时间梳理、总结下这块儿的知识体系。 2.熟悉、梳理、总结下FTP服务器相关知识体系 3.欢迎批评指正,跪谢一键三连! kettle访问FTP服务器文件并处理数据至PostgreS…

【Unity UI系统介绍】

Unity UI系统介绍 想了解更多游戏开发知识,可以扫描下方二维码,免费领取游戏开发4天训练营课程 Unity UI 是 Unity 引擎中的一套用户界面(UI)系统,允许开发者创建和管理游戏的用户界面。 Canvas:Canvas 是 Unity UI 的核心组件…

如何3分钟快速训练一个属于自己的(暴躁老哥、猫娘)AI大模型?(弱智吧经典问题为例)

首先我们进入谷歌Gemini:Gemini - Google DeepMind 然后我们进入官网看见左边的几个选项 选择Create new prompt创建新的提示 选择结构化提示 点击action可以增加列,也就是设置更多回答或者选项 那么那个温度(Temperature)是什么…

二、安装、使用Grafana

目录 一、安装Grafana 二、使用grafana 一、安装Grafana 官网:https://grafana.com/ 账号:admin 密码:xxxxxx [rootrabbitmq_2 prometheus]# [rootrabbitmq_2 prometheus]# wget https://dl.grafana.com/enterprise/release/grafana-enter…

redis安装与群集

项目需求: 1.安装redis 2.测试redis性能,100个并发连接,100000个请求测试 3.在当前数据库下创建键值对 a11,a22,a33,a44,a55 4.查看键值对 5.将a1改名为a11,将a2删除 5.将a3移动到1号数据库 6搭建redis集群(可选) 测试环境…

第六十节 Java设计模式 - 过滤器/标准模式

Java设计模式 - 过滤器/标准模式 过滤器模式使用不同的条件过滤对象。 这些标准可以通过逻辑操作链接在一起。 过滤器模式是一种结构型模式。 例子 import java.util.List; import java.util.ArrayList;class Employee {private String name;private String gender;private…

【Spring】Springmvc学习Ⅲ

# Springmvc学习Ⅲ 文章目录 一、图书管理系统1. 功能1.1 登录前端接口前端代码后端接口后端代码 1.2 图书列表展示步骤:图书类代码mock数据代码控制层调用代码服务层代码(存储除数据库中需要存储的数据) 2. 分层控制2.1 三层架构2.2 代码重…

C语言实现简单的日历功能

开篇 本篇文章的题目来源于《编程珠玑》第三章课后习题的第四个问题,也是我会手动实现的本章的最后一个功能。 问题概要 给定月和年,使用字符数组生成该月的日历(含有周几的日历)。 思路分析 为了生成给定年份中某个月的日历&…

【光线重塑技术】小姐姐,美得不可方物——lllyasviel/ic-light

在英伟达自18年宣布光追技术之后,RTX显卡也成了目前Steam游戏的常客。就连 AMD、Intel 和 Apple Silicon 都宣布要在GPU上支持光追算法。这次我要介绍的是huggingface上比较火的relight技术—— ic-light 介绍 IC-Light 是一个操纵图像照明的项目。 IC-Light &qu…

商务分析方法与工具(十):Python的趣味快捷-公司财务数据最炫酷可视化

Tips:"分享是快乐的源泉💧,在我的博客里,不仅有知识的海洋🌊,还有满满的正能量加持💪,快来和我一起分享这份快乐吧😊! 喜欢我的博客的话,记得…

【FreeRTOS 快速入门】-- 1、STM32工程移植FreeRTOS

目录 一、新建STM32工程 为了示范完整的移植过程,我们从0开始,新建一个标准的STM32点灯工程。 (本篇以CubeMX作示范,CubeIDE操作近同,可作对比参考) 1、新建工程 选择 芯片型号 新建工程 2、搜索芯片型号…

Pytest自动化测试框架完美结合Allure

🍅 视频学习:文末有免费的配套视频可观看 🍅 关注公众号【互联网杂货铺】,回复 1 ,免费获取软件测试全套资料,资料在手,涨薪更快 简介 Allure Framework是一种灵活的、轻量级、多语言测试报告工…

weblogic [WeakPassword]

一、漏洞描述 开放了wblogic端口,进去发现有任意读取文件漏洞,配合解密工具读出密码,登录后台传入webshell 二、影响版本 当前版本 三、影响组件 weblogic 四、漏洞判断 hello/file.jsp?path/etc/passwd 发现有任意文件下载 五、漏洞…

C++牛客周赛题目分享(2)小红叕战小紫,小红的数组移动,小红的素数合并,小红的子序列求和

目录 ​编辑 1.前言 2.四道题目 1.小红叕战小紫 1.题目描述 2.输入描述 3.输出描述 4.示例 5.题解与思路 2.小红的数组移动 1.题目描述 2.输入描述 3.输出描述 4.示例 5.题解与思路 3.小红的素数合并 1.题目描述 2.输入描述 3.输出描述 4.示例 5.题解与思…

2024年淘宝天猫618超级红包领取口令活动时间是从什么时候开始到几月几号结束?

2024年淘宝天猫618活动,将于2024年5月19日开始,今年618淘宝天猫取消了预售环节。同时,618淘宝天猫也提供了多项优惠活动:超级红包、跨店满减、官方立减、全程价保及草柴APP领优惠券拿购物返利等多重优惠活动。 2024年淘宝天猫618…

【C语言】指针(一)

目录 一、内存 1.1 ❥ 理解内存和地址的关系 1.2 ❥ 编址 二、指针变量 2.1 ❥ 取地址操作符(&) 2.2 ❥ 指针变量和解引用操作符(*) 2.3 ❥ 指针变量的大小 三、指针类型的意义 3.1 ❥ 指针的解引用 3.2 ❥ 指针-整数 3…

智能制造装备业项目数字化管理之项目模板管理

智能制造装备,作为工业4.0的核心组成部分,正日益受到全球制造业的关注。这类装备融合了信息技术和制造技术,旨在提高生产效率、降低成本并增强产品的个性化。然而,随着智能制造装备行业的飞速发展,项目管理复杂性也在不…

AI图像生成-原理

一、图像生成流程总结 【AI绘画】深入理解Stable Diffusion!站内首个深入教程,30分钟从原理到模型训练 买不到的课程_哔哩哔哩_bilibili 二、如果只是用comfy UI生成图片 1、找到下面几个文件,把对应模型移动到对应文件夹即可使用 2、选择对…

大学c语言基础很差,能不能学51单片机?会不会很困难?

开始前我分享下我的经历,我刚入行时遇到一个好公司和师父,给了我机会,一年时间从3k薪资涨到18k的, 我师父给了一些51单片机学习方法和资料,让我不断提升自己,感谢帮助过我的人, 如大家和我一样…

Springboot项目如何创建单元测试

文章目录 目录 文章目录 前言 一、SpringBoot单元测试的使用 1.1 引入依赖 1.2 创建单元测试类 二、Spring Boot使用Mockito进行单元测试 2.1 Mockito中经常使用的注解以及注解的作用 2.2 使用Mockito测试类中的方法 2.3 使用Mockito测试Controller层的方法 2.4 mock…