您现在的位置是:首页 > 编程 > 

kaggle入门级竞赛Spaceship Titanic LIghtgbm+Optuna调参

2025-07-25 23:00:55
kaggle入门级竞赛Spaceship Titanic LIghtgbm+Optuna调参 kaggle入门级竞赛Spaceship Titanic简介欢迎来到 2912 年,需要您的数据科学技能来解开宇宙之谜。我们收到了来自四光年外的信号,情况看起来不太好。 泰坦尼克号宇宙飞船是一个月前下水的一艘星际客轮。船上载有近 1,000 名乘客,这艘船开始了它的处女航,将太阳系的移民运送到绕附近恒

kaggle入门级竞赛Spaceship Titanic LIghtgbm+Optuna调参

kaggle入门级竞赛Spaceship Titanic
简介

欢迎来到 2912 年,需要您的数据科学技能来解开宇宙之谜。我们收到了来自四光年外的信号,情况看起来不太好。 泰坦尼克号宇宙飞船是一个月前下水的一艘星际客轮。船上载有近 1,000 名乘客,这艘船开始了它的处女航,将太阳系的移民运送到绕附近恒星运行的三颗新的宜居系外行星。 在绕行半人马座阿尔法星前往其第一个目的地(炎热的 55 Cancri E)途中,粗心的泰坦尼克号宇宙飞船与隐藏在尘埃云中的时空异常相撞。可悲的是,它遭遇了与 1000 年前同名的相似命运。虽然飞船完好无损,但几乎一半的乘客都被传送到了异次元! 为了帮助救援人员并回失踪的乘客,您面临的挑战是使用从飞船损坏的计算机系统中恢复的记录来预测哪些乘客被异常现象运送。

帮助拯救他们并改变历史!

数据介绍

数据集描述

在本次比赛中,您的任务是预测泰坦尼克号宇宙飞船与时空异常相撞期间乘客是否被传送到另一个维度。为了帮助您做出这些预测,您将获得一组从船上损坏的计算机系统中恢复的个人记录。

数据字段描述
- 约三分之二(~8700)乘客的个人记录,用作培训数据。
  1. PassengerId- 每位乘客都有一个唯一的 ID。每个 ID 均采用以下形式gggg_pp,其中gggg指示乘客随行的团体,并且pp是他们在团体中的编号。体中的人通常是家庭成员,但并非总是如此。
  2. HomePlanet- 乘客离开的星球,通常是他们永久居住的星球。
  3. CryoSleep- 表明乘客是否选择在航程期间处于假死状态。处于冷冻睡眠状态的乘客被限制在自己的客舱内。
  4. Cabin- 乘客所居住的舱室号码。采用以下形式deck/num/side,其中side可以是P左舷或右舷。S
  5. Destination- 乘客将要登陆的星球。
  6. Age- 乘客的年龄。
  7. VIP- 旅客是否在航程中支付了特殊VIP服务费用。
  8. RoomService, FoodCourt, ShoppingMall, Spa, VRDeck- 乘客在泰坦尼克号宇宙飞船的众多豪华设施中所支付的费用。
  9. ame- 乘客的名字和姓氏。
  10. Transported- 乘客是否被传送到另一个维度。这是目标,即您尝试预测的列。
- 剩余三分之一(~400)乘客的个人记录,用作测试数据。您的任务是预测Transported该集合中乘客的价值。
Sample_ - 格式正确的提交文件。
  1. PassengerId- 测试集中每位乘客的 ID。
  2. Transported- 目标。对于每位乘客,预测True或False。

代码

代码语言:javascript代码运行次数:0运行复制
import pandas as pd

train_data = pd.read_csv('/kaggle/input/spaceship-titanic/')
test_data = pd.read_csv('/kaggle/input/spaceship-titanic/')

train_data.shape, test_data.shape

打开数据文件,查看文件的一些基本信息,这里可用的函数有train_data.shape,train_data.head(),train_data.info()等等。

代码语言:javascript代码运行次数:0运行复制
train_data.isna().sum(), test_data.isna().sum()

这里是查看数据集的缺失值。根据缺失值的数据以及类型去选择对缺失值进行删除或者填充操作。

代码语言:javascript代码运行次数:0运行复制
import numpy as np
# 删除缺失值
train_data2 = train_data.dropna()
test_data2 = test_data
# 对需要转换的列进行对数转换
columns_to_transform = ['RoomService', 'FoodCourt', 'ShoppingMall', 'Spa', 'VRDeck']

# 为了避免对数运算中的负值或零,加上常数1,确保数据不为零
for col in columns_to_transform:
    train_data2[col] = np.log(train_data2[col] + 1)  # 对每一列进行对数转换,避免 log(0)
for col in columns_to_transform:
    test_data2[col] = np.log(test_data2[col] + 1)  
train_data2.shape,test_data2.shape

这里的对数转换操作是因为我提前知道这些列的分布情况,并不是很好的正态分布,因此进行对数转换能够增强模型的稳定性。

代码语言:javascript代码运行次数:0运行复制
train_data2[['team', 'team_encoder']] = train_data2['PassengerId'].str.split('_', expand=True)

test_data2[['team', 'team_encoder']] = test_data2['PassengerId'].str.split('_', expand=True)
# 将该列转换为整数类型
train_data2['team'] = train_data2['team'].astype(int)
train_data2['team_encoder'] = train_data2['team'].astype(int)
test_data2['team'] = test_data2['team'].astype(int)
test_data2['team_encoder'] = test_data2['team'].astype(int)
train_data2.shape, test_data2.shape

根据字段的信息可以知道,每个 ID 均采用以下形式gggg_pp,其中gggg指示乘客随行的团体,并且pp是他们在团体中的编号。因此在这里进行了切分操作,而不是直接从特征中删除。一般的唯一标识符所含有的数据信息太少,在入模之前都是进行删除操作。

代码语言:javascript代码运行次数:0运行复制
## 这里计算每个人在飞船上的总消费金额
train_data2.loc[:, 'total_fee'] = train_data2['RoomService'] + train_data2['FoodCourt'] + train_data2['ShoppingMall'] + train_data2['Spa'] + train_data2['VRDeck']
test_data2.loc[:, 'total_fee'] = test_data2['RoomService'] + test_data2['FoodCourt'] + test_data2['ShoppingMall'] + test_data2['Spa'] + test_data2['VRDeck']

# 使用 str.split() 拆分
train_data2[['deck', 'num', 'side']] = train_data2['Cabin'].str.split('/', expand=True)
test_data2[['deck', 'num', 'side']] = test_data2['Cabin'].str.split('/', expand=True)

# 删除多个列 
train_data = train_data2.drop(['Cabin', 'ame','PassengerId'], axis=1)
test_data = test_data2.drop(['Cabin', 'ame','PassengerId'], axis=1)
train_data.drop_duplicates(inplace = True)
PassengerId=test_data2['PassengerId']
# 使用 map() 方法进行编码
train_data['Transported'] = train_data['Transported'].map({True: 1, False: 0})
train_data.shape, test_data.shape

# 准备入模,划分好目标变量和特征
train_data4=train_data.drop(['Transported'], axis=1)
label=train_data['Transported']

以上都是一些数据处理和特征工程的操作,大家自行查看。

代码语言:javascript代码运行次数:0运行复制
from sklearn.preprocessing import OneHotEncoder
import pandas as pd

def encode_categorical_features(train_df, test_df, categorical_columns):
    """
    对指定的类别型特征进行 One-Hot 编码,并对训练集和测试集进行特征对齐。
    
    """
    encoder = OneHotEncoder(sparse_output=False, handle_unknown='ignore')  # 创建 OneHotEncoder
    train_encoded = train_()  # 使用传入的训练集数据
    test_encoded = test_()  # 使用传入的测试集数据
    
    for column in categorical_columns:
        # 对训练集进行 fit_transform
        train_encoded_array = encoder.fit_transform(train_df[[column]])
        # 对测试集使用训练集的规则进行 transform
        test_encoded_array = (test_df[[column]])
        
        # 将编码后的数据转换为 DataFrame
        train_encoded_df = pd.DataFrame(train_encoded_array, 
                                        columns=encoder.get_feature_names_out([column]), 
                                        index=train_df.index)
        test_encoded_df = pd.DataFrame(test_encoded_array, 
                                       columns=encoder.get_feature_names_out([column]), 
                                       index=test_df.index)
        
        # 合并编码后的数据到原始 DataFrame 中
        train_encoded = ([train_encoded, train_encoded_df], axis=1)
        test_encoded = ([test_encoded, test_encoded_df], axis=1)
        
        # 删除原始的类别型列
        train_encoded.drop(column, axis=1, inplace=True)
        test_encoded.drop(column, axis=1, inplace=True)
    
    # 确保训练集和测试集的列顺序一致
    test_encoded = test_encoded.reindex(columns=train_, fill_value=0)
    
    return train_encoded, test_encoded

# 需要编码的列名
encoder_columns = ['HomePlanet', 'CryoSleep', 'Destination', 'VIP', 'deck', 'num', 'side']

# 调用函数进行编码,传入指定的类别列
train_data_encoded, test_data_encoded = encode_categorical_features(train_data4, test_data, encoder_columns)

# 查看结果维度
print("训练集维度: ", train_data_encoded.shape)
print("测试集维度: ", test_data_encoded.shape)

以上属于编码的操作,这里使用的OneHotEncoder,一般情况下,模型更想要的是数值数据,因此需要转成数值数据。object类型的编码一般是独热编码用的较多,这里就要提一下分类变量的类型。

分类变量

分类变量(Categorical Variables)是指那些数据值表示不同类别的变量。分类变量本身并没有数量上的顺序,通常用来表示某个对象或现象的类型、类别等。根据其具体的特点,分类变量可分为几种类型,且在机器学习与数据分析中,通常需要对分类变量进行编码,以便进行后续的建模和计算。

  1. 分类变量的类型 分类变量可以根据其类别结构分为两种主要类型:

(1)名义型变量(ominal Variables) 定义:名义型变量表示不同的类别或类型,但这些类别之间没有内在的顺序关系。例如:性别(男、女)、颜(红、蓝、绿)、城市(北京、上海、广州)。 示例: 性别:男、女 城市:纽约、伦敦、东京 (2)顺序型变量(Ordinal Variables) 定义:顺序型变量不仅表示不同的类别,而且这些类别之间具有某种自然的顺序关系,但顺序间的距离不一定是均等的。顺序型变量不仅告诉我们类别的不同,还给出了这些类别之间的相对顺序。例如:教育程度(小学、中学、大专、大学)、星级评价(1星、2星、星、4星、5星)。 示例: 教育程度:小学 < 中学 < 大专 < 本科 星级评价:1星 < 2星 < 星 < 4星 < 5星 2. 分类变量的编码方法 在机器学习和数据分析中,由于大多数算法无法直接处理非数值型的数据,我们需要将分类变量转换为数值型变量。常见的编码方法包括:

(1)独热编码(One-Hot Encoding) 适用范围:适用于名义型变量。

原理:将每个类别转换为一个新的二进制特征列。如果某个样本属于某个类别,则该类别对应的列为1,其他列为0。每个类别都会变成一个独立的列。

示例:

假设有一个“颜”变量,类别为:红、蓝、绿。 编码后的结果: 红 蓝 绿 1 0 0 0 1 0 0 0 1 优点:不会引入任何顺序关系,避免了不必要的模型假设。适用于类别数量较少的变量。

缺点:如果类别数目很大,编码后的数据会变得非常稀疏(维度过高)。

(2)标签编码(Label Encoding) 适用范围:适用于顺序型变量(有内在顺序的分类变量),也可以应用于名义型变量,但对于名义型变量可能会引入不必要的顺序假设。

原理:将每个类别映射为一个整数值。例如,“红” = 0, “蓝” = 1, “绿” = 2。

示例:

假设有一个“教育程度”变量,类别为:小学、中学、大专、本科。 编码后的结果: 教育程度 编码 小学 0 中学 1 大专 2 本科 优点:编码简单,维度低。

缺点:对于名义型变量使用时可能不合适,因为会误导模型认为这些数字之间存在某种顺序或距离(例如,模型可能认为"红"比"蓝"大)。

()目标编码(Target Encoding) 适用范围:适用于分类变量和回归问题,尤其是类别很多时。

原理:通过计算每个类别的目标变量(如标签)的均值或其他统计量来替代类别。例如,对于某个分类变量,每个类别的编码就是该类别对应的目标变量的平均值。

示例:

假设我们有一个“城市”变量和一个“收入”目标变量,通过计算每个城市的平均收入来替代“城市”变量。 优点:能够有效处理高基数(即类别数非常多)的情况。

缺点:可能会导致过拟合,尤其是在数据集较小的时候。

(4)频率编码(Frequency Encoding) 适用范围:适用于类别较多的变量。

原理:将每个类别用该类别在数据集中的出现频率来表示。频率高的类别对应较大的数值。

示例:

假设有一个“城市”变量,并且“纽约”出现了50次,“洛杉矶”出现了0次,“东京”出现了20次。 编码后的结果: 城市 频率编码 纽约 50 洛杉矶 0 东京 20 优点:简洁,且避免了独热编码带来的高维问题。

缺点:可能丧失类别的具体信息,且频率高的类别可能在某些算法中被错误地解释为重要。

(5)二进制编码(Binary Encoding) 适用范围:适用于类别数目较多且需要减少维度的情况。

原理:首先将类别用整数编码,然后将这些整数转换为二进制数,最终将二进制数拆分成多个列。

示例:

假设有5个类别,我们首先对其进行整数编码(例如:0, 1, 2, , 4),然后将这些整数转换为二进制:000, 001, 010, 011, 100。 编码后的结果: 类别 二进制编码 0 000 1 001 2 010 011 4 100 优点:相比独热编码,维度较低。

缺点:对模型来说,二进制编码可能难以解释,尤其是在类别很多时。

总结 对于 名义型变量,常用的编码方式是 独热编码,但如果类别很多也可以使用 频率编码 或 目标编码。 对于 顺序型变量,适合使用 标签编码,因为这些变量本身存在一定的顺序关系。 对于类别数目较多的变量,除了常规的独热编码和标签编码, 目标编码 和 频率编码 也可以作为有效选择。 选择哪种编码方式,主要取决于数据的特点、所选模型以及任务的具体要求。

代码语言:javascript代码运行次数:0运行复制
from _selection import train_test_split
from  import precision_score, recall_score, f1_score, roc_auc_score
import lightgbm as lgb
import optuna
import joblib  # 用于保存模型

x = train_data_encoded
y = label

# 切分数据集
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)

# 定义目标函数
def objective(trial):
    params = {
        'objective': 'binary',
        'scale_pos_weight': 0.98557,  
        'boosting_type': 'gbdt',
        'max_depth': trial.suggest_int('max_depth', , 10),
        'num_leaves': trial.suggest_int('num_leaves', 20, 150),
        'min_child_samples': trial.suggest_int('min_child_samples', 10, 100),
        'min_child_weight': trial.suggest_loguniform('min_child_weight', 1e-, 10.0),
        'subsample': trial.suggest_uniform('subsample', 0.6, 1.0),
        'colsample_bytree': trial.suggest_uniform('colsample_bytree', 0.6, 1.0),
        'learning_rate': trial.suggest_loguniform('learning_rate', 1e-4, 0.1),
        'reg_lambda': trial.suggest_loguniform('reg_lambda', 1e-, 10.0),
        'reg_alpha': trial.suggest_loguniform('reg_alpha', 1e-, 10.0),
    }
    
    model = lgb.LGBMClassifier(**params, random_state=42)
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)
    f1 = f1_score(y_test, y_pred)
    return f1

# 启动优化
study = _study(direction='maximize')
(objective, n_trials=50)

# 使用最佳参数训练模型
best_params = study.best_trial.params
best_model = lgb.LGBMClassifier(**best_params, random_state=42)
best_model.fit(X_train, y_train)

# 保存模型
joblib.dump(best_model, "best_lightgbm_model.pkl")

# 评估
y_pred = best_model.predict(X_test)
y_proba = best_model.predict_proba(X_test)[:, 1]
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
auc = roc_auc_score(y_test, y_proba)

# 输出结果
print("最佳参数: ", best_params)
print("查准率: {:.5f}".format(precision))
print("查全率: {:.5f}".format(recall))
print("F1分数: {:.5f}".format(f1))
print("AUC分数: {:.5f}".format(auc))
print("模型已保存为 'best_lightgbm_model.pkl'")

运行结果如下

代码语言:javascript代码运行次数:0运行复制
最佳参数:  {'max_depth': 5, 'num_leaves': 64, 'min_child_samples': 49, 'min_child_weight': 2.42059675927095, 'subsample': 0.82846179682849, 'colsample_bytree': 0.815004121704074, 'learning_rate': 0.0520569110582605, 'reg_lambda': 0.00242109962401076, 'reg_alpha': 9.08872819209626}
查准率: 0.77869
查全率: 0.8700
F1分数: 0.80679
AUC分数: 0.88882
模型已保存为 'best_lightgbm_model.pkl'

这里选择使用lightgbm完全是本人习惯,主要是因为其运行速度较其他算法更快。大家可以选择别的模型进行尝试,或者直接使用堆叠,堆叠在竞赛中是比较玩赖的算法,将多种模型的效果可以进行叠加。 LightGBM的主要优点包括训练速度快、内存使用高效、支持类别特征、能够处理大规模数据集、支持分布式训练和GPU加速、具有灵活的调参能力、强大的可解释性以及支持多种任务类型。这些优点使得LightGBM在解决机器学习问题时,特别是在数据量较大时,成为一种非常流行和高效的工具。 这里的参数优化使用了optuna,大家也可以使用网格搜索或者遗传算法和粒子算法进行参数优化。

optuna算法简介

Optuna 是一个自动化的超参数优化框架,旨在帮助机器学习模型在不同的超参数配置下到最优解。它提供了高效、灵活且易于使用的超参数调优工具,适用于各种机器学习任务,包括深度学习、传统机器学习以及强化学习等。Optuna的核心特点是通过高效的算法自动化调整模型的超参数,极大地减少了人工调参的时间和工作量。

Optuna的主要特点和优势 自动化超参数优化: Optuna 旨在通过自动化搜索超参数空间来帮助优化机器学习模型。它通过定义一个目标函数(objective function),在该函数中评估模型的性能,并通过智能搜索来到最优的超参数组合。

高效的优化算法: Optuna 使用基于 TPE(Tree-structured Parzen Estimator) 算法的贝叶斯优化方法。TPE 是一种先进的序列模型优化方法,比传统的网格搜索和随机搜索更加高效,能够在较少的试验次数下到优秀的超参数配置。

TPE(Tree-structured Parzen Estimator):一种贝叶斯优化技术,它根据已评估的超参数配置的性能来逐步优化后续的超参数选择。 灵活的搜索空间定义: Optuna 支持通过用户自定义的搜索空间来定义超参数的范围,支持离散和连续类型的参数。用户可以灵活选择各种超参数的搜索策略(如uniform、loguniform等),同时支持多种搜索空间约束。

试验和算法的分布式支持: Optuna 支持分布式训练,通过集成分布式计算框架(如Dask或MPI),可以在多台机器或多个进程中并行化超参数优化过程,加速搜索过程。

早停机制(Pruning): 在训练过程中,Optuna 提供了 早停机制,可以提前终止那些表现不佳的试验,从而节省计算资源。Optuna可以自动监控训练过程中的指标,并根据设定的阈值决定是否停止试验,进一步提高效率。

易于集成: Optuna 与常见的机器学习库(如 Scikit-learn, XGBoost, LightGBM, TensorFlow, PyTorch)有很好的兼容性,可以方便地与现有的工作流集成。Optuna 提供了简单易用的接口,帮助用户快速上手。

可视化: Optuna 提供了强大的可视化工具,可以帮助用户查看超参数搜索的过程、结果以及模型的性能趋势。例如,可以绘制超参数与目标值之间的关系图,或者查看优化过程中不同超参数组合的表现。

以上就是该次竞赛的所有内容,分享给大家更多是为了交流,本人以后的内容还是以实战的项目为主,项目中用到的知识点顺便进行一些分享,本次的分享到这里就结束了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2024-12-25,如有侵权请联系 cloudcommunity@tencent 删除模型数据腾讯技术创作特训营S11#重启人生kaggle变量

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1146431.html

相关标签:无
上传时间: 2025-07-19 14:21:29
留言与评论(共有 16 条评论)
本站网友 丝诺萄官网
19分钟前 发表
1
本站网友 王小佳
27分钟前 发表
trial.suggest_uniform('subsample'
本站网友 宠物经济学家
3分钟前 发表
0.98557
本站网友 ff9
1分钟前 发表
这里的参数优化使用了optuna
本站网友 科技博客
14分钟前 发表
最终将二进制数拆分成多个列
本站网友 uclg
8分钟前 发表
通常需要对分类变量进行编码
本站网友 三星平板
20分钟前 发表
如果某个样本属于某个类别
本站网友 星美传媒
6分钟前 发表
将太阳系的移民运送到绕附近恒星运行的三颗新的宜居系外行星
本站网友 古典风格装修效果图
1分钟前 发表
- 剩余三分之一(~400)乘客的个人记录
本站网友 男生喜欢女生在上面吗
26分钟前 发表
尤其是在数据集较小的时候
本站网友 虹口足球场羽毛球
6分钟前 发表
010
本站网友 网络助手
2分钟前 发表
'min_child_weight'
本站网友 非安全
13分钟前 发表
避免了不必要的模型假设
本站网友 丑宝
9分钟前 发表
但几乎一半的乘客都被传送到了异次元! 为了帮助救援人员并回失踪的乘客
本站网友 燕莎奥特莱斯
15分钟前 发表
这里就要提一下分类变量的类型