用户新增预测——baseline学习笔记

一、赛题理解

1. 赛题名称

        用户新增预测挑战赛

2. 赛题数据集

        赛题数据由约62万条训练集、20万条测试集数据组成,共包含13个字段。其中uuid为样本唯一标识,eid为访问行为ID,udmap为行为属性,其中的key1到key9表示不同的行为属性,如项目名、项目id等相关字段,common_ts为应用访问记录发生时间(毫秒时间戳),其余字段x1至x8为用户相关的属性,为匿名处理字段。target字段为预测目标,即是否为新增用户。

3. 赛题链接 

2023 iFLYTEK A.I.开发者大赛-讯飞开放平台 (xfyun.cn)


4. 评估指标

        F1 score,具体公式如下: 

Precision_i = \frac{TP_i}{TP_i + FP_i} Recall_i = \frac{TP_i}{TP_i + FN_i}

F1_i = \frac{2 \cdot Precision_i \cdot Recall_i}{Precision_i + Recall_i}

二、数据竞赛开发步骤

1. 问题分析

        问题分析是竞赛的第一步,它涉及对问题进行定义、目标明确化和数据需求的识别。

2.  数据清洗

        在采集数据完后,对数据进行数据清洗,即把采集到的、不适合用来做机器学习训练的数据进行预处理,从而转化为适合机器学习的数据。

3. 数据探索

        对清洗后的数据进行可视化和统计分析的过程。通过数据探索,可以深入了解数据的特征、分布、相关性等情况,发现数据之间的模式和趋势,为特征工程和特征筛选提供指导。常见的数据探索方法包括绘制直方图、散点图、箱线图等图形,计算统计指标如均值、方差、相关系数等。

4. 特征工程

        根据数据的领域知识和探索结果,对原始数据进行变换、组合、衍生等操作,以创建更有意义、更能表达问题特征的新特征。好的特征工程可以提高模型的性能和泛化能力。常见的特征工程包括特征缩放、编码分类变量、处理时间序列数据、创建多项式特征等。

5. 特征筛选 

        通过一定的评估方法选择对模型训练最有用的特征,去除冗余或不相关的特征。这样可以降低模型复杂度,加快训练速度,减少过拟合的可能性,并提高模型的解释性。常见的特征筛选方法包括基于统计的方法、基于模型的方法和基于特征重要性的方法。

6. 模型训练

        使用清洗、探索和筛选后的数据来训练机器学习模型的过程。根据问题的类型和数据的特点,可以选择合适的机器学习算法和模型架构进行训练。训练过程涉及优化模型参数,使其能够最好地拟合训练数据,并能在未见过的数据上泛化。

7. 模型保存 

        模型训练完成后,需要将训练得到的模型保存起来,以便在后续部署和使用中使用。模型保存可以包括保存模型权重、参数和架构,以及相关的辅助信息。在实际应用中,保存的模型可以用于预测新数据的结果或作为其他任务的基础。

        当然,对于上面的特征工程不是一步到位的,而是不断的通过模型训练的结果进行不断的优化调整,直到最优的特征组合。

三、 baseline详细解读

1. 数据读取

# 1. 导入需要用到的相关库
# 导入 pandas 库,用于数据处理和分析
import pandas as pd
# 导入 numpy 库,用于科学计算和多维数组操作
import numpy as np
# 从 sklearn.tree 模块中导入 DecisionTreeClassifier 类
# DecisionTreeClassifier 用于构建决策树分类模型
from sklearn.tree import DecisionTreeClassifier# 2. 读取训练集和测试集
# 使用 read_csv() 函数从文件中读取训练集数据,文件名为 'train.csv'
train_data = pd.read_csv('用户新增预测挑战赛公开数据/train.csv')
# 使用 read_csv() 函数从文件中读取测试集数据,文件名为 'test.csv'
test_data = pd.read_csv('用户新增预测挑战赛公开数据/test.csv')

2. 特征构造

(1)对'udmap' 列进行 One-Hot 编码 

# 数据样例:
#                    udmap  key1  key2  key3  key4  key5  key6  key7  key8  key9
# 0           {'key1': 2}     2     0     0     0     0     0     0     0     0
# 1           {'key2': 1}     0     1     0     0     0     0     0     0     0
# 2  {'key1': 3, 'key2': 2}   3     2     0     0     0     0     0     0     0
# 具体实现代码:
# 定义函数 udmap_onethot,用于将 'udmap' 列进行 One-Hot 编码
def udmap_onethot(d):v = np.zeros(9)  # 创建一个长度为 9 的零数组if d == 'unknown':  # 如果 'udmap' 的值是 'unknown'return v  # 返回零数组d = eval(d)  # 将 'udmap' 的值解析为一个字典for i in range(1, 10):  # 遍历 'key1' 到 'key9'if 'key' + str(i) in d:  # 如果当前键存在于字典中v[i-1] = d['key' + str(i)]  # 将字典中的值存储在对应的索引位置上return v  # 返回 One-Hot 编码后的数组# 使用 apply() 方法将 udmap_onethot 函数应用于每个样本的 'udmap' 列
# np.vstack() 用于将结果堆叠成一个数组
train_udmap_df = pd.DataFrame(np.vstack(train_data['udmap'].apply(udmap_onethot)))
test_udmap_df = pd.DataFrame(np.vstack(test_data['udmap'].apply(udmap_onethot)))
# 为新的特征 DataFrame 命名列名
train_udmap_df.columns = ['key' + str(i) for i in range(1, 10)]
test_udmap_df.columns = ['key' + str(i) for i in range(1, 10)]
# 将编码后的 udmap 特征与原始数据进行拼接,沿着列方向拼接
train_data = pd.concat([train_data, train_udmap_df], axis=1)
test_data = pd.concat([test_data, test_udmap_df], axis=1)

(2) 编码 udmap 是否为空

# 使用比较运算符将每个样本的 'udmap' 列与字符串 'unknown' 进行比较,返回一个布尔值的 Series
# 使用 astype(int) 将布尔值转换为整数(0 或 1),以便进行后续的数值计算和分析
train_data['udmap_isunknown'] = (train_data['udmap'] == 'unknown').astype(int)
test_data['udmap_isunknown'] = (test_data['udmap'] == 'unknown').astype(int)

 (3)提取 eid 的频次特征和标签特征

# 使用 map() 方法将每个样本的 eid 映射到训练数据中 eid 的频次计数
# train_data['eid'].value_counts() 返回每个 eid 出现的频次计数
train_data['eid_freq'] = train_data['eid'].map(train_data['eid'].value_counts())
test_data['eid_freq'] = test_data['eid'].map(train_data['eid'].value_counts())# 使用 groupby() 方法按照 eid 进行分组,然后计算每个 eid 分组的目标值均值
# train_data.groupby('eid')['target'].mean() 返回每个 eid 分组的目标值均值
train_data['eid_mean'] = train_data['eid'].map(train_data.groupby('eid')['target'].mean())
test_data['eid_mean'] = test_data['eid'].map(train_data.groupby('eid')['target'].mean())

 (4)提取时间戳

# 使用 pd.to_datetime() 函数将时间戳列转换为 datetime 类型
# 样例:1678932546000->2023-03-15 15:14:16
# 具体实现代码:
train_data['common_ts'] = pd.to_datetime(train_data['common_ts'], unit='ms')
test_data['common_ts'] = pd.to_datetime(test_data['common_ts'], unit='ms')# 使用 dt.hour 属性从 datetime 列中提取小时信息,并将提取的小时信息存储在新的列 'common_ts_hour'
train_data['common_ts_hour'] = train_data['common_ts'].dt.hour
test_data['common_ts_hour'] = test_data['common_ts'].dt.hour


3. 模型训练

        加载决策树模型进行训练(直接使用sklearn中导入的包进行模型建立);

        对测试集进行预测,并保存结果到result_df中;

        保存结果文件到本地

clf = DecisionTreeClassifier()
# 使用 fit 方法训练模型
# train_data.drop(['udmap', 'common_ts', 'uuid', 'target'], axis=1) 从训练数据集中移除列 'udmap', 'common_ts', 'uuid', 'target'
# 这些列可能是特征或标签,取决于数据集的设置
# train_data['target'] 是训练数据集中的标签列,它包含了每个样本的目标值
clf.fit(train_data.drop(['udmap', 'common_ts', 'uuid', 'target'], axis=1),  # 特征数据:移除指定的列作为特征train_data['target']  # 目标数据:将 'target' 列作为模型的目标进行训练
)# 9. 对测试集进行预测,并保存结果到result_df中
# 创建一个DataFrame来存储预测结果,其中包括两列:'uuid' 和 'target'
# 'uuid' 列来自测试数据集中的 'uuid' 列,'target' 列将用来存储模型的预测结果
result_df = pd.DataFrame({'uuid': test_data['uuid'],  # 使用测试数据集中的 'uuid' 列作为 'uuid' 列的值'target': clf.predict(test_data.drop(['udmap', 'common_ts', 'uuid'], axis=1))  # 使用模型 clf 对测试数据集进行预测,并将预测结果存储在 'target' 列中
})# 10. 保存结果文件到本地
# 将结果DataFrame保存为一个CSV文件,文件名为 'submit.csv'
# 参数 index=None 表示不将DataFrame的索引写入文件中
result_df.to_csv('submit.csv', index=None)

 四、后续提升方案

1. 构建交叉训练框架

def cv_model(clf, train_x, train_y, test_x, clf_name, seed = 23):folds = 5kf = KFold(n_splits=folds, shuffle=True, random_state=seed)oof = np.zeros(train_x.shape[0])test_predict = np.zeros(test_x.shape[0])cv_scores = []for i, (train_index, valid_index) in enumerate(kf.split(train_x, train_y)):print('************************************ {} ************************************'.format(str(i+1)))trn_x, trn_y, val_x, val_y = train_x.iloc[train_index], train_y[train_index], train_x.iloc[valid_index], train_y[valid_index]if clf_name == "cat":params = {'learning_rate': 0.03, 'depth': 6, 'bootstrap_type':'Bernoulli','random_seed':2023,'od_type': 'Iter', 'od_wait': 100, 'random_seed': 23, 'allow_writing_files': False, 'task_type' : 'GPU'}model = clf(iterations=20000, **params, eval_metric='F1')model.fit(trn_x, trn_y, eval_set=(val_x, val_y),metric_period=100,use_best_model=True, cat_features=[],verbose=1)val_pred  = model.predict_proba(val_x)[:,1]test_pred = model.predict_proba(test_x)[:,1]oof[valid_index] = val_predtest_predict += test_pred / kf.n_splitsF1_score = f1_score(val_y, [1 if prob >= 0.5 else 0 for prob in val_pred])cv_scores.append(F1_score)print(cv_scores)return oof, test_predict

2. 特征筛选

(1)相关性

        通过统计单个特征与目标变量之间的相关性,选取相关性较高的特征。

(2)递归特征消除

        通过递归地拟合模型并去除对模型性能贡献较小的特征,直到达到所需的特征数量

(3)特征重要性

        通过查看模型内部的特征重要性指标

(4)具有空重要性的特征选择

        使用目标排列的特征选择过程测试与噪声(混洗目标)拟合时特征重要性分布的实际重要性显着性。

Feature Selection with Null Importances | Kaggle

强烈推荐此方案 

3. 特征交叉

        选取特征重要性排名靠前进行特征交叉,可以选择排名靠前的特征组合来构建新的特征,从而增强模型的表现。

4. 模型调参

        机器学习和深度学习中,通过调整模型的超参数来优化模型性能。超参数是在模型训练之前设置的参数,它们不会在训练过程中自动学习,而需要手动选择。

        一般常用的调参方法:

        a. 网格搜索(Grid Search):遍历所有超参数的组合,逐一尝试。虽然它是全面搜索,但在超参数空间较大时计算代价较高。

         b. 随机搜索(Random Search):随机从超参数空间中抽取组合进行尝试。相比网格搜索,它的计算代价较低,但可能需要更多的尝试次数。

         c. 贝叶斯优化(Bayesian Optimization):通过构建超参数组合的概率模型,根据模型对性能的估计来选择最有可能改善性能的组合。

         d. 遗传算法(Genetic Algorithms):借鉴自然进化的原理,通过基因交叉和变异等方式逐渐优化超参数组合。

        网格搜索一般在数据量很大时不建议使用,会导致迭代的次数很多,而无法跑出最优的参数组合。强烈建议使用贝叶斯优化进行模型调参

5. 特征构造

        (1)eid存在多个数据样本,可以进行mean,max,min,std,skew等数据的统计。

        (2)补充完整频次特征和标签特征;

        (3)提取更多的时间信息;

        (4)对label进行阈值调整

 6. stacking集成

        stacking是一种分层模型集成框架。以两层为例,第一层由多个基学习器组成,其输入为原始训练集,第二层的模型则是以第一层基学习器的输出作为特征加入训练集进行再训练,从而得到完整的stacking模型。

五、降低内存方法

        比赛按照上面的baseline会读取较大的数据内存,因此在此处放入一个降低内存的方法:

        通过减少数字列的数据类型并将对象列转换为分类类型来优化 DataFrame 'train_df' 的内存使用量,从而减少内存使用量。

predictor_columns = [col for col in test_df.columns if col not in ['uuid','time','file']]
def reduce_mem_usage(df):start_mem = df.memory_usage().sum() / 1024**2print('Memory usage of dataframe is {:.2f} MB'.format(start_mem))for col in tqdm.tqdm(predictor_columns):col_type = df[col].dtypeif col_type != object:c_min = df[col].min()c_max = df[col].max()if str(col_type)[:3] == 'int':if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:df[col] = df[col].astype(np.int8)elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:df[col] = df[col].astype(np.int16)elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:df[col] = df[col].astype(np.int32)elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:df[col] = df[col].astype(np.int64)else:if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:df[col] = df[col].astype(np.float16)elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:df[col] = df[col].astype(np.float32)else:df[col] = df[col].astype(np.float64)else:df[col] = df[col].astype('category')end_mem = df.memory_usage().sum() / 1024**2print('Memory usage after optimization is: {:.2f} MB'.format(end_mem))print('Decreased by {:.1f}%'.format(100 * (start_mem - end_mem) / start_mem))return dftrain_df = reduce_mem_usage(train_df)

 https://datawhaler.feishu.cn/docx/HBIHd7ugzoOsMqx0LEncR1lJnCf

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

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

相关文章

S-Video端口接口芯片ESD保护方案图

在音/视频领域&#xff0c;除了常见的HDMI、DVI接口等&#xff0c;还有一些冷门的接口&#xff0c;比如S-Video端口&#xff0c;相信很多人可能都没有听说过。S-Video视频端口同样拥有较好的数据传输功能。S-Video二分量视频端口&#xff0c;英文全称Separate Video&#xff0c…

Lua学习记录

Lua基础了解 Lua的注释通过 (-- 单行注释&#xff0c;--[[ ]] 多行注释)可以不加&#xff1b; 多个变量赋值&#xff0c;按顺序赋值&#xff0c;没有则为nil&#xff1b; function的简单用法&#xff0c;多个返回值配合多重赋值&#xff0c;以end为结束标志 Lua下标从1开始&…

JSP-学习笔记

文章目录 1.JSP介绍2 JSP快速入门3 JSP 脚本3.1 JSP脚本案例3.2 JSP缺点 4 EL表达式4.1 快速入门案例 5. JSTL标签6. MVC模式和三层架构6.1 MVC6.2 三层架构 7. 案例-基于MVC和三层架构实现商品表的增删改查 1.JSP介绍 概念 JSP&#xff08;JavaServer Pages&#xff09;是一种…

Azure存储账户

存储账户的概念 Azure存储账户是Azure提供的一种云存储解决方案&#xff0c;用于存储和访问各种类型的数据&#xff0c;包括文件、磁盘、队列、表格和Blob&#xff08;二进制大对象&#xff09;数据。存储账户可以基于访问模式和冗余需求来选择不同的类型&#xff0c;以满足应…

【MySQL--->表的操作】

文章目录 [TOC](文章目录) 一、创建表二、查看表三、修改表四、删除表drop table 表名; ![在这里插入图片描述](https://img-blog.csdnimg.cn/15227b8335364d41bd01b4b4dd83ee55.png) 一、创建表 语句格式:create table 表名(列名 类型,…)字符集 校验规则 存储引擎;字符集和校…

我还不知道?Android组件化插件化模块化

Android组件化、插件化和模块化是针对Android应用程序开发的一种架构设计思想和开发方式。 组件化&#xff08;Componentization&#xff09;&#xff1a; 组件化是将一个大型的Android应用程序拆分成多个独立的组件&#xff08;Module&#xff09;&#xff0c;每个组件可以独…

python使用装饰器记录方法耗时

思路 python使用修饰器记录方法耗时&#xff0c;目的是每当方法执行完后&#xff0c;可以记录该方法耗时&#xff0c;而不需要在每个方法的执行前后&#xff0c;去创建一个临时变量&#xff0c;来记录耗时。 方式一&#xff08;不推荐&#xff09;&#xff1a; 在每个方法的…

source insight 添加宏-文件头加注释

source insight 3.5 自带的一些宏&#xff0c;在安装目录下的 utils.em 文件中&#xff0c;用户也可以自己写文件&#xff0c;命令为xxx.em &#xff0c;然后把这个文件添加到项目中即可&#xff0c;添加后在菜单栏 Options -> Key Assignments 里输入macro 就能显示新添加的…

第一个ArkTS项目实践-鸿蒙ArkTS

第一个ArkTS项目实践-ArkTS 第一个ArkTS项目实践-ArkTS自定义组件的组成配置属性与布局配置属性布局 改变组件状态循环渲染列表数据代码ToDoItem组件ToDoList页面 效果参考资料 第一个ArkTS项目实践-ArkTS 本篇文章是官网上视频对ArkTS开发实践的第一个视频&#xff0c;主要是引…

Matplotlib数据可视化(三)

目录 1.绘图的填充 1.1 曲线下方区域的填充 1.2 填充部分区域 1.3 两条曲线之间的区域填充 1.4 直接使用fill进行填充 1.绘图的填充 绘图的填充可以调用fill_between()或fill()进行填充。 1.1 曲线下方区域的填充 x np.linspace(0,1,500) y np.sin(3*np.pi*x)*np.exp…

【C语言】每日一题(找到所有数组中消失的数字)

找到所有数组中消失的数字&#xff0c;链接奉上。 这里简单说一下&#xff0c;因为还没有接触到动态内存&#xff0c;数据结构&#xff0c;所以知识有限&#xff0c;也是尽力而为&#xff0c;结合题库的评论区找到了适合我的解法&#xff0c;以后有机会&#xff0c;会补上各种…

如何在HTML中使用React

突发奇想 查了查真的可以,官方文档: 在网站中添加 React – React 开始 引入js <!-- 开发环境使用 --><script src"https://unpkg.com/react18/umd/react.development.js"></script><script src"https://unpkg.com/react-dom18/umd/reac…

穿越数字奇境:探寻元宇宙中的科技奇迹

随着科技的迅速发展&#xff0c;元宇宙正逐渐成为一个备受关注的话题&#xff0c;它不仅是虚拟现实的延伸&#xff0c;更是将现实世界与数字世界融合的未来典范。在这个神秘而充满活力的数字奇境中&#xff0c;涉及了众多领域和技术&#xff0c;为我们呈现出了一个无限的创新和…

创建Azure资源锁

锁的介绍 在Azure中&#xff0c;资源锁是一种用于保护订阅、资源组或者单个资源的机制。它可以防止对受锁定的资源进行删除或修改操作&#xff0c;帮助确保资源的连续可用性和安全性。 Azure中的资源锁可以分为两种类型&#xff1a; 删除锁&#xff08;CanNotDelete&#xf…

javaScript:模板字符串让你忘记字符串拼接

目录 一.前言 二.模板字符串的使用 1.介绍 2.模板字符串 支持换行 模板字符串更适合元素写入 innerHTML模板字符串写法 3.模板字符串中&#xff0c;可以运行表达式 4.模板字符串中可以运行函数 三.总结 语法&#xff1a; 多行字符串&#xff1a; 变量插值&#xff1a; …

μCOS-Ⅲ_简介

μCOS-Ⅲ简介 文章目录 μCOS-Ⅲ简介前言一、什么是 C/OS-III&#xff1f;二、C/OS-III的特点三、C/OS-III的版本和参考资料1、C/OS-III版本2、C/OS-III源码获取3、C/OS-III参考资料 四、C/OS-III源码简介总结 前言 μcos-III是一个可以基于ROM运行的、可裁剪的、抢占式、实时…

latex 笔记:cs论文需要的排版格式

主要针对英文文献 1 基本环境 连字符 不同长度的"-"表示不同含义。 一个"-"长度的连字符用于词中两个"-"长度的连字符常用于制定范围三个"-"长度的连字符是破折号数学中的负数要用数学环境下的-得到 强调 在正式文章中, 通常不…

ARM64 程序调用标准

ARM64 程序调用标准 1 Machine Registers1.1 General-purpose Registers1.2 SIMD and Floating-Point Registers 2 Processes, Memory and the Stack2.1 Memory Addresses2.2 The Stack2.2.1 Universal stack constraints2.2.2 Stack constraints at a public interface 2.3 Th…

【C语言】字符串和内存函数的介绍 -- 详解

重点介绍处理字符和字符串的库函数的使用和注意事项。 C语言中对字符和字符串的处理很是频繁&#xff0c;但是C语言本身是没有字符串类型的&#xff0c;字符串通常放在常量字符串中或者字符数组中。字符串常量适用于那些对它不做修改的字符串函数。 一、求字符串长度⚪strlen …

【Rust】Rust学习 第十四章进一步认识 Cargo 和 Crates.io

本章会讨论 Cargo 其他一些更为高级的功能&#xff0c;我们将展示如何&#xff1a; 使用发布配置来自定义构建将库发布到 crates.io使用工作空间来组织更大的项目从 crates.io 安装二进制文件使用自定义的命令来扩展 Cargo Cargo 的功能不止本章所介绍的&#xff0c;关于其全…